1 // SPDX-License-Identifier: GPL-2.0
3 #include <netinet/in.h>
4 #include <netinet/tcp.h>
6 #include <bpf/bpf_helpers.h>
8 char _license
[] SEC("license") = "GPL";
9 __u32 _version
SEC("version") = 1;
11 #define SOL_CUSTOM 0xdeadbeef
18 __uint(type
, BPF_MAP_TYPE_SK_STORAGE
);
19 __uint(map_flags
, BPF_F_NO_PREALLOC
);
21 __type(value
, struct sockopt_sk
);
22 } socket_storage_map
SEC(".maps");
24 SEC("cgroup/getsockopt")
25 int _getsockopt(struct bpf_sockopt
*ctx
)
27 __u8
*optval_end
= ctx
->optval_end
;
28 __u8
*optval
= ctx
->optval
;
29 struct sockopt_sk
*storage
;
31 if (ctx
->level
== SOL_IP
&& ctx
->optname
== IP_TOS
)
32 /* Not interested in SOL_IP:IP_TOS;
33 * let next BPF program in the cgroup chain or kernel
38 if (ctx
->level
== SOL_SOCKET
&& ctx
->optname
== SO_SNDBUF
) {
39 /* Not interested in SOL_SOCKET:SO_SNDBUF;
40 * let next BPF program in the cgroup chain or kernel
46 if (ctx
->level
== SOL_TCP
&& ctx
->optname
== TCP_CONGESTION
) {
47 /* Not interested in SOL_TCP:TCP_CONGESTION;
48 * let next BPF program in the cgroup chain or kernel
54 if (ctx
->level
!= SOL_CUSTOM
)
55 return 0; /* EPERM, deny everything except custom level */
57 if (optval
+ 1 > optval_end
)
58 return 0; /* EPERM, bounds check */
60 storage
= bpf_sk_storage_get(&socket_storage_map
, ctx
->sk
, 0,
61 BPF_SK_STORAGE_GET_F_CREATE
);
63 return 0; /* EPERM, couldn't get sk storage */
66 return 0; /* EPERM, kernel should not have handled
67 * SOL_CUSTOM, something is wrong!
69 ctx
->retval
= 0; /* Reset system call return value to zero */
71 optval
[0] = storage
->val
;
77 SEC("cgroup/setsockopt")
78 int _setsockopt(struct bpf_sockopt
*ctx
)
80 __u8
*optval_end
= ctx
->optval_end
;
81 __u8
*optval
= ctx
->optval
;
82 struct sockopt_sk
*storage
;
84 if (ctx
->level
== SOL_IP
&& ctx
->optname
== IP_TOS
)
85 /* Not interested in SOL_IP:IP_TOS;
86 * let next BPF program in the cgroup chain or kernel
91 if (ctx
->level
== SOL_SOCKET
&& ctx
->optname
== SO_SNDBUF
) {
92 /* Overwrite SO_SNDBUF value */
94 if (optval
+ sizeof(__u32
) > optval_end
)
95 return 0; /* EPERM, bounds check */
97 *(__u32
*)optval
= 0x55AA;
103 if (ctx
->level
== SOL_TCP
&& ctx
->optname
== TCP_CONGESTION
) {
104 /* Always use cubic */
106 if (optval
+ 5 > optval_end
)
107 return 0; /* EPERM, bounds check */
109 memcpy(optval
, "cubic", 5);
115 if (ctx
->level
!= SOL_CUSTOM
)
116 return 0; /* EPERM, deny everything except custom level */
118 if (optval
+ 1 > optval_end
)
119 return 0; /* EPERM, bounds check */
121 storage
= bpf_sk_storage_get(&socket_storage_map
, ctx
->sk
, 0,
122 BPF_SK_STORAGE_GET_F_CREATE
);
124 return 0; /* EPERM, couldn't get sk storage */
126 storage
->val
= optval
[0];
127 ctx
->optlen
= -1; /* BPF has consumed this option, don't call kernel
128 * setsockopt handler.