18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/bpf.h> 38c2ecf20Sopenharmony_ci#include <bpf/bpf_helpers.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_cichar _license[] SEC("license") = "GPL"; 68c2ecf20Sopenharmony_ci__u32 _version SEC("version") = 1; 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define SOL_CUSTOM 0xdeadbeef 98c2ecf20Sopenharmony_ci#define CUSTOM_INHERIT1 0 108c2ecf20Sopenharmony_ci#define CUSTOM_INHERIT2 1 118c2ecf20Sopenharmony_ci#define CUSTOM_LISTENER 2 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistruct sockopt_inherit { 148c2ecf20Sopenharmony_ci __u8 val; 158c2ecf20Sopenharmony_ci}; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct { 188c2ecf20Sopenharmony_ci __uint(type, BPF_MAP_TYPE_SK_STORAGE); 198c2ecf20Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 208c2ecf20Sopenharmony_ci __type(key, int); 218c2ecf20Sopenharmony_ci __type(value, struct sockopt_inherit); 228c2ecf20Sopenharmony_ci} cloned1_map SEC(".maps"); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct { 258c2ecf20Sopenharmony_ci __uint(type, BPF_MAP_TYPE_SK_STORAGE); 268c2ecf20Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC | BPF_F_CLONE); 278c2ecf20Sopenharmony_ci __type(key, int); 288c2ecf20Sopenharmony_ci __type(value, struct sockopt_inherit); 298c2ecf20Sopenharmony_ci} cloned2_map SEC(".maps"); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct { 328c2ecf20Sopenharmony_ci __uint(type, BPF_MAP_TYPE_SK_STORAGE); 338c2ecf20Sopenharmony_ci __uint(map_flags, BPF_F_NO_PREALLOC); 348c2ecf20Sopenharmony_ci __type(key, int); 358c2ecf20Sopenharmony_ci __type(value, struct sockopt_inherit); 368c2ecf20Sopenharmony_ci} listener_only_map SEC(".maps"); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic __inline struct sockopt_inherit *get_storage(struct bpf_sockopt *ctx) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci if (ctx->optname == CUSTOM_INHERIT1) 418c2ecf20Sopenharmony_ci return bpf_sk_storage_get(&cloned1_map, ctx->sk, 0, 428c2ecf20Sopenharmony_ci BPF_SK_STORAGE_GET_F_CREATE); 438c2ecf20Sopenharmony_ci else if (ctx->optname == CUSTOM_INHERIT2) 448c2ecf20Sopenharmony_ci return bpf_sk_storage_get(&cloned2_map, ctx->sk, 0, 458c2ecf20Sopenharmony_ci BPF_SK_STORAGE_GET_F_CREATE); 468c2ecf20Sopenharmony_ci else 478c2ecf20Sopenharmony_ci return bpf_sk_storage_get(&listener_only_map, ctx->sk, 0, 488c2ecf20Sopenharmony_ci BPF_SK_STORAGE_GET_F_CREATE); 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ciSEC("cgroup/getsockopt") 528c2ecf20Sopenharmony_ciint _getsockopt(struct bpf_sockopt *ctx) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci __u8 *optval_end = ctx->optval_end; 558c2ecf20Sopenharmony_ci struct sockopt_inherit *storage; 568c2ecf20Sopenharmony_ci __u8 *optval = ctx->optval; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (ctx->level != SOL_CUSTOM) 598c2ecf20Sopenharmony_ci return 1; /* only interested in SOL_CUSTOM */ 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (optval + 1 > optval_end) 628c2ecf20Sopenharmony_ci return 0; /* EPERM, bounds check */ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci storage = get_storage(ctx); 658c2ecf20Sopenharmony_ci if (!storage) 668c2ecf20Sopenharmony_ci return 0; /* EPERM, couldn't get sk storage */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci ctx->retval = 0; /* Reset system call return value to zero */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci optval[0] = storage->val; 718c2ecf20Sopenharmony_ci ctx->optlen = 1; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return 1; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ciSEC("cgroup/setsockopt") 778c2ecf20Sopenharmony_ciint _setsockopt(struct bpf_sockopt *ctx) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci __u8 *optval_end = ctx->optval_end; 808c2ecf20Sopenharmony_ci struct sockopt_inherit *storage; 818c2ecf20Sopenharmony_ci __u8 *optval = ctx->optval; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (ctx->level != SOL_CUSTOM) 848c2ecf20Sopenharmony_ci return 1; /* only interested in SOL_CUSTOM */ 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (optval + 1 > optval_end) 878c2ecf20Sopenharmony_ci return 0; /* EPERM, bounds check */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci storage = get_storage(ctx); 908c2ecf20Sopenharmony_ci if (!storage) 918c2ecf20Sopenharmony_ci return 0; /* EPERM, couldn't get sk storage */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci storage->val = optval[0]; 948c2ecf20Sopenharmony_ci ctx->optlen = -1; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci return 1; 978c2ecf20Sopenharmony_ci} 98