165b4414aSStanislav Fomichev // SPDX-License-Identifier: GPL-2.0 265b4414aSStanislav Fomichev #include <netinet/in.h> 365b4414aSStanislav Fomichev #include <linux/bpf.h> 43e689141SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h> 565b4414aSStanislav Fomichev 665b4414aSStanislav Fomichev char _license[] SEC("license") = "GPL"; 765b4414aSStanislav Fomichev 8*e01b4a72SStanislav Fomichev __u32 page_size = 0; 9*e01b4a72SStanislav Fomichev 1015669e1dSAndrii Nakryiko SEC("cgroup/getsockopt") _getsockopt_child(struct bpf_sockopt * ctx)1165b4414aSStanislav Fomichevint _getsockopt_child(struct bpf_sockopt *ctx) 1265b4414aSStanislav Fomichev { 1365b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 1465b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 1565b4414aSStanislav Fomichev 1665b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 17*e01b4a72SStanislav Fomichev goto out; 1865b4414aSStanislav Fomichev 1965b4414aSStanislav Fomichev if (optval + 1 > optval_end) 2065b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 2165b4414aSStanislav Fomichev 2265b4414aSStanislav Fomichev if (optval[0] != 0x80) 2365b4414aSStanislav Fomichev return 0; /* EPERM, unexpected optval from the kernel */ 2465b4414aSStanislav Fomichev 2565b4414aSStanislav Fomichev ctx->retval = 0; /* Reset system call return value to zero */ 2665b4414aSStanislav Fomichev 2765b4414aSStanislav Fomichev optval[0] = 0x90; 2865b4414aSStanislav Fomichev ctx->optlen = 1; 2965b4414aSStanislav Fomichev 3065b4414aSStanislav Fomichev return 1; 31*e01b4a72SStanislav Fomichev 32*e01b4a72SStanislav Fomichev out: 33*e01b4a72SStanislav Fomichev /* optval larger than PAGE_SIZE use kernel's buffer. */ 34*e01b4a72SStanislav Fomichev if (ctx->optlen > page_size) 35*e01b4a72SStanislav Fomichev ctx->optlen = 0; 36*e01b4a72SStanislav Fomichev return 1; 3765b4414aSStanislav Fomichev } 3865b4414aSStanislav Fomichev 3915669e1dSAndrii Nakryiko SEC("cgroup/getsockopt") _getsockopt_parent(struct bpf_sockopt * ctx)4065b4414aSStanislav Fomichevint _getsockopt_parent(struct bpf_sockopt *ctx) 4165b4414aSStanislav Fomichev { 4265b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 4365b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 4465b4414aSStanislav Fomichev 4565b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 46*e01b4a72SStanislav Fomichev goto out; 4765b4414aSStanislav Fomichev 4865b4414aSStanislav Fomichev if (optval + 1 > optval_end) 4965b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 5065b4414aSStanislav Fomichev 5165b4414aSStanislav Fomichev if (optval[0] != 0x90) 5265b4414aSStanislav Fomichev return 0; /* EPERM, unexpected optval from the kernel */ 5365b4414aSStanislav Fomichev 5465b4414aSStanislav Fomichev ctx->retval = 0; /* Reset system call return value to zero */ 5565b4414aSStanislav Fomichev 5665b4414aSStanislav Fomichev optval[0] = 0xA0; 5765b4414aSStanislav Fomichev ctx->optlen = 1; 5865b4414aSStanislav Fomichev 5965b4414aSStanislav Fomichev return 1; 60*e01b4a72SStanislav Fomichev 61*e01b4a72SStanislav Fomichev out: 62*e01b4a72SStanislav Fomichev /* optval larger than PAGE_SIZE use kernel's buffer. */ 63*e01b4a72SStanislav Fomichev if (ctx->optlen > page_size) 64*e01b4a72SStanislav Fomichev ctx->optlen = 0; 65*e01b4a72SStanislav Fomichev return 1; 6665b4414aSStanislav Fomichev } 6765b4414aSStanislav Fomichev 6865b4414aSStanislav Fomichev SEC("cgroup/setsockopt") _setsockopt(struct bpf_sockopt * ctx)6965b4414aSStanislav Fomichevint _setsockopt(struct bpf_sockopt *ctx) 7065b4414aSStanislav Fomichev { 7165b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 7265b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 7365b4414aSStanislav Fomichev 7465b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 75*e01b4a72SStanislav Fomichev goto out; 7665b4414aSStanislav Fomichev 7765b4414aSStanislav Fomichev if (optval + 1 > optval_end) 7865b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 7965b4414aSStanislav Fomichev 8065b4414aSStanislav Fomichev optval[0] += 0x10; 8165b4414aSStanislav Fomichev ctx->optlen = 1; 8265b4414aSStanislav Fomichev 8365b4414aSStanislav Fomichev return 1; 84*e01b4a72SStanislav Fomichev 85*e01b4a72SStanislav Fomichev out: 86*e01b4a72SStanislav Fomichev /* optval larger than PAGE_SIZE use kernel's buffer. */ 87*e01b4a72SStanislav Fomichev if (ctx->optlen > page_size) 88*e01b4a72SStanislav Fomichev ctx->optlen = 0; 89*e01b4a72SStanislav Fomichev return 1; 9065b4414aSStanislav Fomichev } 91