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