brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · b7ddf8e Raw
168 lines · c
1// SPDX-License-Identifier: GPL-2.02 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		404019#define SERV4_REWRITE_IP	0x7f000001U /* 127.0.0.1 */20#define SERV4_REWRITE_PORT	444421 22#ifndef IFNAMSIZ23#define IFNAMSIZ 1624#endif25 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";168