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