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 Fomichev int _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 Fomichev int _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 Fomichev int _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