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*15669e1dSAndrii Nakryiko SEC("cgroup/getsockopt") 965b4414aSStanislav Fomichev int _getsockopt_child(struct bpf_sockopt *ctx) 1065b4414aSStanislav Fomichev { 1165b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 1265b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 1365b4414aSStanislav Fomichev 1465b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 1565b4414aSStanislav Fomichev return 1; 1665b4414aSStanislav Fomichev 1765b4414aSStanislav Fomichev if (optval + 1 > optval_end) 1865b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 1965b4414aSStanislav Fomichev 2065b4414aSStanislav Fomichev if (optval[0] != 0x80) 2165b4414aSStanislav Fomichev return 0; /* EPERM, unexpected optval from the kernel */ 2265b4414aSStanislav Fomichev 2365b4414aSStanislav Fomichev ctx->retval = 0; /* Reset system call return value to zero */ 2465b4414aSStanislav Fomichev 2565b4414aSStanislav Fomichev optval[0] = 0x90; 2665b4414aSStanislav Fomichev ctx->optlen = 1; 2765b4414aSStanislav Fomichev 2865b4414aSStanislav Fomichev return 1; 2965b4414aSStanislav Fomichev } 3065b4414aSStanislav Fomichev 31*15669e1dSAndrii Nakryiko SEC("cgroup/getsockopt") 3265b4414aSStanislav Fomichev int _getsockopt_parent(struct bpf_sockopt *ctx) 3365b4414aSStanislav Fomichev { 3465b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 3565b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 3665b4414aSStanislav Fomichev 3765b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 3865b4414aSStanislav Fomichev return 1; 3965b4414aSStanislav Fomichev 4065b4414aSStanislav Fomichev if (optval + 1 > optval_end) 4165b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 4265b4414aSStanislav Fomichev 4365b4414aSStanislav Fomichev if (optval[0] != 0x90) 4465b4414aSStanislav Fomichev return 0; /* EPERM, unexpected optval from the kernel */ 4565b4414aSStanislav Fomichev 4665b4414aSStanislav Fomichev ctx->retval = 0; /* Reset system call return value to zero */ 4765b4414aSStanislav Fomichev 4865b4414aSStanislav Fomichev optval[0] = 0xA0; 4965b4414aSStanislav Fomichev ctx->optlen = 1; 5065b4414aSStanislav Fomichev 5165b4414aSStanislav Fomichev return 1; 5265b4414aSStanislav Fomichev } 5365b4414aSStanislav Fomichev 5465b4414aSStanislav Fomichev SEC("cgroup/setsockopt") 5565b4414aSStanislav Fomichev int _setsockopt(struct bpf_sockopt *ctx) 5665b4414aSStanislav Fomichev { 5765b4414aSStanislav Fomichev __u8 *optval_end = ctx->optval_end; 5865b4414aSStanislav Fomichev __u8 *optval = ctx->optval; 5965b4414aSStanislav Fomichev 6065b4414aSStanislav Fomichev if (ctx->level != SOL_IP || ctx->optname != IP_TOS) 6165b4414aSStanislav Fomichev return 1; 6265b4414aSStanislav Fomichev 6365b4414aSStanislav Fomichev if (optval + 1 > optval_end) 6465b4414aSStanislav Fomichev return 0; /* EPERM, bounds check */ 6565b4414aSStanislav Fomichev 6665b4414aSStanislav Fomichev optval[0] += 0x10; 6765b4414aSStanislav Fomichev ctx->optlen = 1; 6865b4414aSStanislav Fomichev 6965b4414aSStanislav Fomichev return 1; 7065b4414aSStanislav Fomichev } 71