Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <string.h>
  4
  5#include <linux/stddef.h>
  6#include <linux/bpf.h>
  7#include <linux/in.h>
  8#include <linux/in6.h>
  9#include <linux/if.h>
 10#include <errno.h>
 11
 12#include <bpf/bpf_helpers.h>
 13#include <bpf/bpf_endian.h>
 14
 15#include "bind_prog.h"
 16
 17#define SERV4_IP		0xc0a801feU /* 192.168.1.254 */
 18#define SERV4_PORT		4040
 19#define SERV4_REWRITE_IP	0x7f000001U /* 127.0.0.1 */
 20#define SERV4_REWRITE_PORT	4444
 21
 22#ifndef IFNAMSIZ
 23#define IFNAMSIZ 16
 24#endif
 25
 26static __inline int bind_to_device(struct bpf_sock_addr *ctx)
 27{
 28	char veth1[IFNAMSIZ] = "test_sock_addr1";
 29	char veth2[IFNAMSIZ] = "test_sock_addr2";
 30	char missing[IFNAMSIZ] = "nonexistent_dev";
 31	char del_bind[IFNAMSIZ] = "";
 32	int veth1_idx, veth2_idx;
 33
 34	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 35			   &veth1, sizeof(veth1)))
 36		return 1;
 37	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 38			   &veth1_idx, sizeof(veth1_idx)) || !veth1_idx)
 39		return 1;
 40	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 41			   &veth2, sizeof(veth2)))
 42		return 1;
 43	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 44			   &veth2_idx, sizeof(veth2_idx)) || !veth2_idx ||
 45	    veth1_idx == veth2_idx)
 46		return 1;
 47	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 48			   &missing, sizeof(missing)) != -ENODEV)
 49		return 1;
 50	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 51			   &veth1_idx, sizeof(veth1_idx)))
 52		return 1;
 53	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 54			   &del_bind, sizeof(del_bind)))
 55		return 1;
 56
 57	return 0;
 58}
 59
 60static __inline int bind_reuseport(struct bpf_sock_addr *ctx)
 61{
 62	int val = 1;
 63
 64	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 65			   &val, sizeof(val)))
 66		return 1;
 67	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 68			   &val, sizeof(val)) || !val)
 69		return 1;
 70	val = 0;
 71	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 72			   &val, sizeof(val)))
 73		return 1;
 74	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 75			   &val, sizeof(val)) || val)
 76		return 1;
 77
 78	return 0;
 79}
 80
 81static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt)
 82{
 83	int old, tmp, new = 0xeb9f;
 84
 85	/* Socket in test case has guarantee that old never equals to new. */
 86	if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)) ||
 87	    old == new)
 88		return 1;
 89	if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &new, sizeof(new)))
 90		return 1;
 91	if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &tmp, sizeof(tmp)) ||
 92	    tmp != new)
 93		return 1;
 94	if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)))
 95		return 1;
 96
 97	return 0;
 98}
 99
100SEC("cgroup/bind4")
101int bind_v4_prog(struct bpf_sock_addr *ctx)
102{
103	struct bpf_sock *sk;
104	__u32 user_ip4;
105	__u16 user_port;
106
107	sk = ctx->sk;
108	if (!sk)
109		return 0;
110
111	if (sk->family != AF_INET)
112		return 0;
113
114	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
115		return 0;
116
117	if (ctx->user_ip4 != bpf_htonl(SERV4_IP) ||
118	    ctx->user_port != bpf_htons(SERV4_PORT))
119		return 0;
120
121	// u8 narrow loads:
122	user_ip4 = 0;
123	user_ip4 |= load_byte(ctx->user_ip4, 0, sizeof(user_ip4));
124	user_ip4 |= load_byte(ctx->user_ip4, 1, sizeof(user_ip4));
125	user_ip4 |= load_byte(ctx->user_ip4, 2, sizeof(user_ip4));
126	user_ip4 |= load_byte(ctx->user_ip4, 3, sizeof(user_ip4));
127	if (ctx->user_ip4 != user_ip4)
128		return 0;
129
130	user_port = 0;
131	user_port |= load_byte(ctx->user_port, 0, sizeof(user_port));
132	user_port |= load_byte(ctx->user_port, 1, sizeof(user_port));
133	if (ctx->user_port != user_port)
134		return 0;
135
136	// u16 narrow loads:
137	user_ip4 = 0;
138	user_ip4 |= load_word(ctx->user_ip4, 0, sizeof(user_ip4));
139	user_ip4 |= load_word(ctx->user_ip4, 1, sizeof(user_ip4));
140	if (ctx->user_ip4 != user_ip4)
141		return 0;
142
143	/* Bind to device and unbind it. */
144	if (bind_to_device(ctx))
145		return 0;
146
147	/* Test for misc socket options. */
148	if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY))
149		return 0;
150
151	/* Set reuseport and unset */
152	if (bind_reuseport(ctx))
153		return 0;
154
155	ctx->user_ip4 = bpf_htonl(SERV4_REWRITE_IP);
156	ctx->user_port = bpf_htons(SERV4_REWRITE_PORT);
157
158	return 1;
159}
160
161SEC("cgroup/bind4")
162int bind_v4_deny_prog(struct bpf_sock_addr *ctx)
163{
164	return 0;
165}
166
167char _license[] SEC("license") = "GPL";
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <string.h>
  4
  5#include <linux/stddef.h>
  6#include <linux/bpf.h>
  7#include <linux/in.h>
  8#include <linux/in6.h>
  9#include <linux/if.h>
 10#include <errno.h>
 11
 12#include <bpf/bpf_helpers.h>
 13#include <bpf/bpf_endian.h>
 14
 
 
 15#define SERV4_IP		0xc0a801feU /* 192.168.1.254 */
 16#define SERV4_PORT		4040
 17#define SERV4_REWRITE_IP	0x7f000001U /* 127.0.0.1 */
 18#define SERV4_REWRITE_PORT	4444
 19
 20#ifndef IFNAMSIZ
 21#define IFNAMSIZ 16
 22#endif
 23
 24static __inline int bind_to_device(struct bpf_sock_addr *ctx)
 25{
 26	char veth1[IFNAMSIZ] = "test_sock_addr1";
 27	char veth2[IFNAMSIZ] = "test_sock_addr2";
 28	char missing[IFNAMSIZ] = "nonexistent_dev";
 29	char del_bind[IFNAMSIZ] = "";
 30	int veth1_idx, veth2_idx;
 31
 32	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 33			   &veth1, sizeof(veth1)))
 34		return 1;
 35	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 36			   &veth1_idx, sizeof(veth1_idx)) || !veth1_idx)
 37		return 1;
 38	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 39			   &veth2, sizeof(veth2)))
 40		return 1;
 41	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 42			   &veth2_idx, sizeof(veth2_idx)) || !veth2_idx ||
 43	    veth1_idx == veth2_idx)
 44		return 1;
 45	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 46			   &missing, sizeof(missing)) != -ENODEV)
 47		return 1;
 48	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTOIFINDEX,
 49			   &veth1_idx, sizeof(veth1_idx)))
 50		return 1;
 51	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_BINDTODEVICE,
 52			   &del_bind, sizeof(del_bind)))
 53		return 1;
 54
 55	return 0;
 56}
 57
 58static __inline int bind_reuseport(struct bpf_sock_addr *ctx)
 59{
 60	int val = 1;
 61
 62	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 63			   &val, sizeof(val)))
 64		return 1;
 65	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 66			   &val, sizeof(val)) || !val)
 67		return 1;
 68	val = 0;
 69	if (bpf_setsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 70			   &val, sizeof(val)))
 71		return 1;
 72	if (bpf_getsockopt(ctx, SOL_SOCKET, SO_REUSEPORT,
 73			   &val, sizeof(val)) || val)
 74		return 1;
 75
 76	return 0;
 77}
 78
 79static __inline int misc_opts(struct bpf_sock_addr *ctx, int opt)
 80{
 81	int old, tmp, new = 0xeb9f;
 82
 83	/* Socket in test case has guarantee that old never equals to new. */
 84	if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)) ||
 85	    old == new)
 86		return 1;
 87	if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &new, sizeof(new)))
 88		return 1;
 89	if (bpf_getsockopt(ctx, SOL_SOCKET, opt, &tmp, sizeof(tmp)) ||
 90	    tmp != new)
 91		return 1;
 92	if (bpf_setsockopt(ctx, SOL_SOCKET, opt, &old, sizeof(old)))
 93		return 1;
 94
 95	return 0;
 96}
 97
 98SEC("cgroup/bind4")
 99int bind_v4_prog(struct bpf_sock_addr *ctx)
100{
101	struct bpf_sock *sk;
102	__u32 user_ip4;
103	__u16 user_port;
104
105	sk = ctx->sk;
106	if (!sk)
107		return 0;
108
109	if (sk->family != AF_INET)
110		return 0;
111
112	if (ctx->type != SOCK_STREAM && ctx->type != SOCK_DGRAM)
113		return 0;
114
115	if (ctx->user_ip4 != bpf_htonl(SERV4_IP) ||
116	    ctx->user_port != bpf_htons(SERV4_PORT))
117		return 0;
118
119	// u8 narrow loads:
120	user_ip4 = 0;
121	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[0] << 0;
122	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[1] << 8;
123	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[2] << 16;
124	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[3] << 24;
125	if (ctx->user_ip4 != user_ip4)
126		return 0;
127
128	user_port = 0;
129	user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0;
130	user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8;
131	if (ctx->user_port != user_port)
132		return 0;
133
134	// u16 narrow loads:
135	user_ip4 = 0;
136	user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[0] << 0;
137	user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[1] << 16;
138	if (ctx->user_ip4 != user_ip4)
139		return 0;
140
141	/* Bind to device and unbind it. */
142	if (bind_to_device(ctx))
143		return 0;
144
145	/* Test for misc socket options. */
146	if (misc_opts(ctx, SO_MARK) || misc_opts(ctx, SO_PRIORITY))
147		return 0;
148
149	/* Set reuseport and unset */
150	if (bind_reuseport(ctx))
151		return 0;
152
153	ctx->user_ip4 = bpf_htonl(SERV4_REWRITE_IP);
154	ctx->user_port = bpf_htons(SERV4_REWRITE_PORT);
155
156	return 1;
 
 
 
 
 
 
157}
158
159char _license[] SEC("license") = "GPL";