// 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 __u32 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; }