1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/bpf.h> 3 #include <bpf/bpf_helpers.h> 4 5 char _license[] SEC("license") = "GPL"; 6 7 #define SOL_CUSTOM 0xdeadbeef 8 #define CUSTOM_INHERIT1 0 9 #define CUSTOM_INHERIT2 1 10 #define CUSTOM_LISTENER 2 11 12 __s32 page_size = 0; 13 14 struct sockopt_inherit { 15 __u8 val; 16 }; 17 18 struct { 19 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 20 __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 21 __type(key, int); 22 __type(value, struct sockopt_inherit); 23 } cloned1_map SEC(".maps"); 24 25 struct { 26 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 27 __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 28 __type(key, int); 29 __type(value, struct sockopt_inherit); 30 } cloned2_map SEC(".maps"); 31 32 struct { 33 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 34 __uint(map_flags, BPF_F_NO_PREALLOC); 35 __type(key, int); 36 __type(value, struct sockopt_inherit); 37 } listener_only_map SEC(".maps"); 38 39 static __inline struct sockopt_inherit *get_storage(struct bpf_sockopt *ctx) 40 { 41 if (ctx->optname == CUSTOM_INHERIT1) 42 return bpf_sk_storage_get(&cloned1_map, ctx->sk, 0, 43 BPF_SK_STORAGE_GET_F_CREATE); 44 else if (ctx->optname == CUSTOM_INHERIT2) 45 return bpf_sk_storage_get(&cloned2_map, ctx->sk, 0, 46 BPF_SK_STORAGE_GET_F_CREATE); 47 else 48 return bpf_sk_storage_get(&listener_only_map, ctx->sk, 0, 49 BPF_SK_STORAGE_GET_F_CREATE); 50 } 51 52 SEC("cgroup/getsockopt") 53 int _getsockopt(struct bpf_sockopt *ctx) 54 { 55 __u8 *optval_end = ctx->optval_end; 56 struct sockopt_inherit *storage; 57 __u8 *optval = ctx->optval; 58 59 if (ctx->level != SOL_CUSTOM) 60 goto out; /* only interested in SOL_CUSTOM */ 61 62 if (optval + 1 > optval_end) 63 return 0; /* EPERM, bounds check */ 64 65 storage = get_storage(ctx); 66 if (!storage) 67 return 0; /* EPERM, couldn't get sk storage */ 68 69 ctx->retval = 0; /* Reset system call return value to zero */ 70 71 optval[0] = storage->val; 72 ctx->optlen = 1; 73 74 return 1; 75 76 out: 77 /* optval larger than PAGE_SIZE use kernel's buffer. */ 78 if (ctx->optlen > page_size) 79 ctx->optlen = 0; 80 return 1; 81 } 82 83 SEC("cgroup/setsockopt") 84 int _setsockopt(struct bpf_sockopt *ctx) 85 { 86 __u8 *optval_end = ctx->optval_end; 87 struct sockopt_inherit *storage; 88 __u8 *optval = ctx->optval; 89 90 if (ctx->level != SOL_CUSTOM) 91 goto out; /* only interested in SOL_CUSTOM */ 92 93 if (optval + 1 > optval_end) 94 return 0; /* EPERM, bounds check */ 95 96 storage = get_storage(ctx); 97 if (!storage) 98 return 0; /* EPERM, couldn't get sk storage */ 99 100 storage->val = optval[0]; 101 ctx->optlen = -1; 102 103 return 1; 104 105 out: 106 /* optval larger than PAGE_SIZE use kernel's buffer. */ 107 if (ctx->optlen > page_size) 108 ctx->optlen = 0; 109 return 1; 110 } 111