1// SPDX-License-Identifier: GPL-2.0 2#include <linux/bpf.h> 3#include <bpf/bpf_helpers.h> 4 5char _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 13struct sockopt_inherit { 14 __u8 val; 15}; 16 17struct { 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 24struct { 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 31struct { 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 38static __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 51SEC("cgroup/getsockopt") 52int _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 76SEC("cgroup/setsockopt") 77int _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