cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bind4_prog.c (4016B)


      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 <sys/socket.h>
     10#include <netinet/tcp.h>
     11#include <linux/if.h>
     12#include <errno.h>
     13
     14#include <bpf/bpf_helpers.h>
     15#include <bpf/bpf_endian.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 |= ((volatile __u8 *)&ctx->user_ip4)[0] << 0;
    124	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[1] << 8;
    125	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[2] << 16;
    126	user_ip4 |= ((volatile __u8 *)&ctx->user_ip4)[3] << 24;
    127	if (ctx->user_ip4 != user_ip4)
    128		return 0;
    129
    130	user_port = 0;
    131	user_port |= ((volatile __u8 *)&ctx->user_port)[0] << 0;
    132	user_port |= ((volatile __u8 *)&ctx->user_port)[1] << 8;
    133	if (ctx->user_port != user_port)
    134		return 0;
    135
    136	// u16 narrow loads:
    137	user_ip4 = 0;
    138	user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[0] << 0;
    139	user_ip4 |= ((volatile __u16 *)&ctx->user_ip4)[1] << 16;
    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
    161char _license[] SEC("license") = "GPL";