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 __u32 _version SEC("version") = 1; 7 8 #define SOL_CUSTOM 0xdeadbeef 9 #define CUSTOM_INHERIT1 0 10 #define CUSTOM_INHERIT2 1 11 #define CUSTOM_LISTENER 2 12 13 struct sockopt_inherit { 14 __u8 val; 15 }; 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 19 __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 20 __type(key, int); 21 __type(value, struct sockopt_inherit); 22 } cloned1_map SEC(".maps"); 23 24 struct { 25 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 26 __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 27 __type(key, int); 28 __type(value, struct sockopt_inherit); 29 } cloned2_map SEC(".maps"); 30 31 struct { 32 __uint(type, BPF_MAP_TYPE_SK_STORAGE); 33 __uint(map_flags, BPF_F_NO_PREALLOC); 34 __type(key, int); 35 __type(value, struct sockopt_inherit); 36 } listener_only_map SEC(".maps"); 37 38 static __inline struct sockopt_inherit *get_storage(struct bpf_sockopt *ctx) 39 { 40 if (ctx->optname == CUSTOM_INHERIT1) 41 return bpf_sk_storage_get(&cloned1_map, ctx->sk, 0, 42 BPF_SK_STORAGE_GET_F_CREATE); 43 else if (ctx->optname == CUSTOM_INHERIT2) 44 return bpf_sk_storage_get(&cloned2_map, ctx->sk, 0, 45 BPF_SK_STORAGE_GET_F_CREATE); 46 else 47 return bpf_sk_storage_get(&listener_only_map, ctx->sk, 0, 48 BPF_SK_STORAGE_GET_F_CREATE); 49 } 50 51 SEC("cgroup/getsockopt") 52 int _getsockopt(struct bpf_sockopt *ctx) 53 { 54 __u8 *optval_end = ctx->optval_end; 55 struct sockopt_inherit *storage; 56 __u8 *optval = ctx->optval; 57 58 if (ctx->level != SOL_CUSTOM) 59 return 1; /* only interested in SOL_CUSTOM */ 60 61 if (optval + 1 > optval_end) 62 return 0; /* EPERM, bounds check */ 63 64 storage = get_storage(ctx); 65 if (!storage) 66 return 0; /* EPERM, couldn't get sk storage */ 67 68 ctx->retval = 0; /* Reset system call return value to zero */ 69 70 optval[0] = storage->val; 71 ctx->optlen = 1; 72 73 return 1; 74 } 75 76 SEC("cgroup/setsockopt") 77 int _setsockopt(struct bpf_sockopt *ctx) 78 { 79 __u8 *optval_end = ctx->optval_end; 80 struct sockopt_inherit *storage; 81 __u8 *optval = ctx->optval; 82 83 if (ctx->level != SOL_CUSTOM) 84 return 1; /* only interested in SOL_CUSTOM */ 85 86 if (optval + 1 > optval_end) 87 return 0; /* EPERM, bounds check */ 88 89 storage = get_storage(ctx); 90 if (!storage) 91 return 0; /* EPERM, couldn't get sk storage */ 92 93 storage->val = optval[0]; 94 ctx->optlen = -1; 95 96 return 1; 97 } 98