1*8259fdebSStanislav Fomichev // SPDX-License-Identifier: GPL-2.0
2*8259fdebSStanislav Fomichev 
3*8259fdebSStanislav Fomichev #include <linux/stddef.h>
4*8259fdebSStanislav Fomichev #include <linux/bpf.h>
5*8259fdebSStanislav Fomichev #include <sys/types.h>
6*8259fdebSStanislav Fomichev #include <sys/socket.h>
7*8259fdebSStanislav Fomichev #include <bpf/bpf_helpers.h>
8*8259fdebSStanislav Fomichev #include <bpf/bpf_endian.h>
9*8259fdebSStanislav Fomichev 
bind_prog(struct bpf_sock_addr * ctx,int family)10*8259fdebSStanislav Fomichev static __always_inline int bind_prog(struct bpf_sock_addr *ctx, int family)
11*8259fdebSStanislav Fomichev {
12*8259fdebSStanislav Fomichev 	struct bpf_sock *sk;
13*8259fdebSStanislav Fomichev 
14*8259fdebSStanislav Fomichev 	sk = ctx->sk;
15*8259fdebSStanislav Fomichev 	if (!sk)
16*8259fdebSStanislav Fomichev 		return 0;
17*8259fdebSStanislav Fomichev 
18*8259fdebSStanislav Fomichev 	if (sk->family != family)
19*8259fdebSStanislav Fomichev 		return 0;
20*8259fdebSStanislav Fomichev 
21*8259fdebSStanislav Fomichev 	if (ctx->type != SOCK_STREAM)
22*8259fdebSStanislav Fomichev 		return 0;
23*8259fdebSStanislav Fomichev 
24*8259fdebSStanislav Fomichev 	/* Return 1 OR'ed with the first bit set to indicate
25*8259fdebSStanislav Fomichev 	 * that CAP_NET_BIND_SERVICE should be bypassed.
26*8259fdebSStanislav Fomichev 	 */
27*8259fdebSStanislav Fomichev 	if (ctx->user_port == bpf_htons(111))
28*8259fdebSStanislav Fomichev 		return (1 | 2);
29*8259fdebSStanislav Fomichev 
30*8259fdebSStanislav Fomichev 	return 1;
31*8259fdebSStanislav Fomichev }
32*8259fdebSStanislav Fomichev 
33*8259fdebSStanislav Fomichev SEC("cgroup/bind4")
bind_v4_prog(struct bpf_sock_addr * ctx)34*8259fdebSStanislav Fomichev int bind_v4_prog(struct bpf_sock_addr *ctx)
35*8259fdebSStanislav Fomichev {
36*8259fdebSStanislav Fomichev 	return bind_prog(ctx, AF_INET);
37*8259fdebSStanislav Fomichev }
38*8259fdebSStanislav Fomichev 
39*8259fdebSStanislav Fomichev SEC("cgroup/bind6")
bind_v6_prog(struct bpf_sock_addr * ctx)40*8259fdebSStanislav Fomichev int bind_v6_prog(struct bpf_sock_addr *ctx)
41*8259fdebSStanislav Fomichev {
42*8259fdebSStanislav Fomichev 	return bind_prog(ctx, AF_INET6);
43*8259fdebSStanislav Fomichev }
44*8259fdebSStanislav Fomichev 
45*8259fdebSStanislav Fomichev char _license[] SEC("license") = "GPL";
46