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

test_sock_addr.c (31380B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (c) 2018 Facebook
      3
      4#define _GNU_SOURCE
      5
      6#include <stdio.h>
      7#include <stdlib.h>
      8#include <unistd.h>
      9
     10#include <arpa/inet.h>
     11#include <netinet/in.h>
     12#include <sys/types.h>
     13#include <sys/select.h>
     14#include <sys/socket.h>
     15
     16#include <linux/filter.h>
     17
     18#include <bpf/bpf.h>
     19#include <bpf/libbpf.h>
     20
     21#include "cgroup_helpers.h"
     22#include "bpf_util.h"
     23
     24#ifndef ENOTSUPP
     25# define ENOTSUPP 524
     26#endif
     27
     28#define CG_PATH	"/foo"
     29#define CONNECT4_PROG_PATH	"./connect4_prog.o"
     30#define CONNECT6_PROG_PATH	"./connect6_prog.o"
     31#define SENDMSG4_PROG_PATH	"./sendmsg4_prog.o"
     32#define SENDMSG6_PROG_PATH	"./sendmsg6_prog.o"
     33#define RECVMSG4_PROG_PATH	"./recvmsg4_prog.o"
     34#define RECVMSG6_PROG_PATH	"./recvmsg6_prog.o"
     35#define BIND4_PROG_PATH		"./bind4_prog.o"
     36#define BIND6_PROG_PATH		"./bind6_prog.o"
     37
     38#define SERV4_IP		"192.168.1.254"
     39#define SERV4_REWRITE_IP	"127.0.0.1"
     40#define SRC4_IP			"172.16.0.1"
     41#define SRC4_REWRITE_IP		"127.0.0.4"
     42#define SERV4_PORT		4040
     43#define SERV4_REWRITE_PORT	4444
     44
     45#define SERV6_IP		"face:b00c:1234:5678::abcd"
     46#define SERV6_REWRITE_IP	"::1"
     47#define SERV6_V4MAPPED_IP	"::ffff:192.168.0.4"
     48#define SRC6_IP			"::1"
     49#define SRC6_REWRITE_IP		"::6"
     50#define WILDCARD6_IP		"::"
     51#define SERV6_PORT		6060
     52#define SERV6_REWRITE_PORT	6666
     53
     54#define INET_NTOP_BUF	40
     55
     56struct sock_addr_test;
     57
     58typedef int (*load_fn)(const struct sock_addr_test *test);
     59typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
     60
     61char bpf_log_buf[BPF_LOG_BUF_SIZE];
     62
     63struct sock_addr_test {
     64	const char *descr;
     65	/* BPF prog properties */
     66	load_fn loadfn;
     67	enum bpf_attach_type expected_attach_type;
     68	enum bpf_attach_type attach_type;
     69	/* Socket properties */
     70	int domain;
     71	int type;
     72	/* IP:port pairs for BPF prog to override */
     73	const char *requested_ip;
     74	unsigned short requested_port;
     75	const char *expected_ip;
     76	unsigned short expected_port;
     77	const char *expected_src_ip;
     78	/* Expected test result */
     79	enum {
     80		LOAD_REJECT,
     81		ATTACH_REJECT,
     82		ATTACH_OKAY,
     83		SYSCALL_EPERM,
     84		SYSCALL_ENOTSUPP,
     85		SUCCESS,
     86	} expected_result;
     87};
     88
     89static int bind4_prog_load(const struct sock_addr_test *test);
     90static int bind6_prog_load(const struct sock_addr_test *test);
     91static int connect4_prog_load(const struct sock_addr_test *test);
     92static int connect6_prog_load(const struct sock_addr_test *test);
     93static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
     94static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
     95static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
     96static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
     97static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
     98static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test);
     99static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
    100static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
    101static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
    102static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
    103static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
    104static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
    105
    106static struct sock_addr_test tests[] = {
    107	/* bind */
    108	{
    109		"bind4: load prog with wrong expected attach type",
    110		bind4_prog_load,
    111		BPF_CGROUP_INET6_BIND,
    112		BPF_CGROUP_INET4_BIND,
    113		AF_INET,
    114		SOCK_STREAM,
    115		NULL,
    116		0,
    117		NULL,
    118		0,
    119		NULL,
    120		LOAD_REJECT,
    121	},
    122	{
    123		"bind4: attach prog with wrong attach type",
    124		bind4_prog_load,
    125		BPF_CGROUP_INET4_BIND,
    126		BPF_CGROUP_INET6_BIND,
    127		AF_INET,
    128		SOCK_STREAM,
    129		NULL,
    130		0,
    131		NULL,
    132		0,
    133		NULL,
    134		ATTACH_REJECT,
    135	},
    136	{
    137		"bind4: rewrite IP & TCP port in",
    138		bind4_prog_load,
    139		BPF_CGROUP_INET4_BIND,
    140		BPF_CGROUP_INET4_BIND,
    141		AF_INET,
    142		SOCK_STREAM,
    143		SERV4_IP,
    144		SERV4_PORT,
    145		SERV4_REWRITE_IP,
    146		SERV4_REWRITE_PORT,
    147		NULL,
    148		SUCCESS,
    149	},
    150	{
    151		"bind4: rewrite IP & UDP port in",
    152		bind4_prog_load,
    153		BPF_CGROUP_INET4_BIND,
    154		BPF_CGROUP_INET4_BIND,
    155		AF_INET,
    156		SOCK_DGRAM,
    157		SERV4_IP,
    158		SERV4_PORT,
    159		SERV4_REWRITE_IP,
    160		SERV4_REWRITE_PORT,
    161		NULL,
    162		SUCCESS,
    163	},
    164	{
    165		"bind6: load prog with wrong expected attach type",
    166		bind6_prog_load,
    167		BPF_CGROUP_INET4_BIND,
    168		BPF_CGROUP_INET6_BIND,
    169		AF_INET6,
    170		SOCK_STREAM,
    171		NULL,
    172		0,
    173		NULL,
    174		0,
    175		NULL,
    176		LOAD_REJECT,
    177	},
    178	{
    179		"bind6: attach prog with wrong attach type",
    180		bind6_prog_load,
    181		BPF_CGROUP_INET6_BIND,
    182		BPF_CGROUP_INET4_BIND,
    183		AF_INET,
    184		SOCK_STREAM,
    185		NULL,
    186		0,
    187		NULL,
    188		0,
    189		NULL,
    190		ATTACH_REJECT,
    191	},
    192	{
    193		"bind6: rewrite IP & TCP port in",
    194		bind6_prog_load,
    195		BPF_CGROUP_INET6_BIND,
    196		BPF_CGROUP_INET6_BIND,
    197		AF_INET6,
    198		SOCK_STREAM,
    199		SERV6_IP,
    200		SERV6_PORT,
    201		SERV6_REWRITE_IP,
    202		SERV6_REWRITE_PORT,
    203		NULL,
    204		SUCCESS,
    205	},
    206	{
    207		"bind6: rewrite IP & UDP port in",
    208		bind6_prog_load,
    209		BPF_CGROUP_INET6_BIND,
    210		BPF_CGROUP_INET6_BIND,
    211		AF_INET6,
    212		SOCK_DGRAM,
    213		SERV6_IP,
    214		SERV6_PORT,
    215		SERV6_REWRITE_IP,
    216		SERV6_REWRITE_PORT,
    217		NULL,
    218		SUCCESS,
    219	},
    220
    221	/* connect */
    222	{
    223		"connect4: load prog with wrong expected attach type",
    224		connect4_prog_load,
    225		BPF_CGROUP_INET6_CONNECT,
    226		BPF_CGROUP_INET4_CONNECT,
    227		AF_INET,
    228		SOCK_STREAM,
    229		NULL,
    230		0,
    231		NULL,
    232		0,
    233		NULL,
    234		LOAD_REJECT,
    235	},
    236	{
    237		"connect4: attach prog with wrong attach type",
    238		connect4_prog_load,
    239		BPF_CGROUP_INET4_CONNECT,
    240		BPF_CGROUP_INET6_CONNECT,
    241		AF_INET,
    242		SOCK_STREAM,
    243		NULL,
    244		0,
    245		NULL,
    246		0,
    247		NULL,
    248		ATTACH_REJECT,
    249	},
    250	{
    251		"connect4: rewrite IP & TCP port",
    252		connect4_prog_load,
    253		BPF_CGROUP_INET4_CONNECT,
    254		BPF_CGROUP_INET4_CONNECT,
    255		AF_INET,
    256		SOCK_STREAM,
    257		SERV4_IP,
    258		SERV4_PORT,
    259		SERV4_REWRITE_IP,
    260		SERV4_REWRITE_PORT,
    261		SRC4_REWRITE_IP,
    262		SUCCESS,
    263	},
    264	{
    265		"connect4: rewrite IP & UDP port",
    266		connect4_prog_load,
    267		BPF_CGROUP_INET4_CONNECT,
    268		BPF_CGROUP_INET4_CONNECT,
    269		AF_INET,
    270		SOCK_DGRAM,
    271		SERV4_IP,
    272		SERV4_PORT,
    273		SERV4_REWRITE_IP,
    274		SERV4_REWRITE_PORT,
    275		SRC4_REWRITE_IP,
    276		SUCCESS,
    277	},
    278	{
    279		"connect6: load prog with wrong expected attach type",
    280		connect6_prog_load,
    281		BPF_CGROUP_INET4_CONNECT,
    282		BPF_CGROUP_INET6_CONNECT,
    283		AF_INET6,
    284		SOCK_STREAM,
    285		NULL,
    286		0,
    287		NULL,
    288		0,
    289		NULL,
    290		LOAD_REJECT,
    291	},
    292	{
    293		"connect6: attach prog with wrong attach type",
    294		connect6_prog_load,
    295		BPF_CGROUP_INET6_CONNECT,
    296		BPF_CGROUP_INET4_CONNECT,
    297		AF_INET,
    298		SOCK_STREAM,
    299		NULL,
    300		0,
    301		NULL,
    302		0,
    303		NULL,
    304		ATTACH_REJECT,
    305	},
    306	{
    307		"connect6: rewrite IP & TCP port",
    308		connect6_prog_load,
    309		BPF_CGROUP_INET6_CONNECT,
    310		BPF_CGROUP_INET6_CONNECT,
    311		AF_INET6,
    312		SOCK_STREAM,
    313		SERV6_IP,
    314		SERV6_PORT,
    315		SERV6_REWRITE_IP,
    316		SERV6_REWRITE_PORT,
    317		SRC6_REWRITE_IP,
    318		SUCCESS,
    319	},
    320	{
    321		"connect6: rewrite IP & UDP port",
    322		connect6_prog_load,
    323		BPF_CGROUP_INET6_CONNECT,
    324		BPF_CGROUP_INET6_CONNECT,
    325		AF_INET6,
    326		SOCK_DGRAM,
    327		SERV6_IP,
    328		SERV6_PORT,
    329		SERV6_REWRITE_IP,
    330		SERV6_REWRITE_PORT,
    331		SRC6_REWRITE_IP,
    332		SUCCESS,
    333	},
    334
    335	/* sendmsg */
    336	{
    337		"sendmsg4: load prog with wrong expected attach type",
    338		sendmsg4_rw_asm_prog_load,
    339		BPF_CGROUP_UDP6_SENDMSG,
    340		BPF_CGROUP_UDP4_SENDMSG,
    341		AF_INET,
    342		SOCK_DGRAM,
    343		NULL,
    344		0,
    345		NULL,
    346		0,
    347		NULL,
    348		LOAD_REJECT,
    349	},
    350	{
    351		"sendmsg4: attach prog with wrong attach type",
    352		sendmsg4_rw_asm_prog_load,
    353		BPF_CGROUP_UDP4_SENDMSG,
    354		BPF_CGROUP_UDP6_SENDMSG,
    355		AF_INET,
    356		SOCK_DGRAM,
    357		NULL,
    358		0,
    359		NULL,
    360		0,
    361		NULL,
    362		ATTACH_REJECT,
    363	},
    364	{
    365		"sendmsg4: rewrite IP & port (asm)",
    366		sendmsg4_rw_asm_prog_load,
    367		BPF_CGROUP_UDP4_SENDMSG,
    368		BPF_CGROUP_UDP4_SENDMSG,
    369		AF_INET,
    370		SOCK_DGRAM,
    371		SERV4_IP,
    372		SERV4_PORT,
    373		SERV4_REWRITE_IP,
    374		SERV4_REWRITE_PORT,
    375		SRC4_REWRITE_IP,
    376		SUCCESS,
    377	},
    378	{
    379		"sendmsg4: rewrite IP & port (C)",
    380		sendmsg4_rw_c_prog_load,
    381		BPF_CGROUP_UDP4_SENDMSG,
    382		BPF_CGROUP_UDP4_SENDMSG,
    383		AF_INET,
    384		SOCK_DGRAM,
    385		SERV4_IP,
    386		SERV4_PORT,
    387		SERV4_REWRITE_IP,
    388		SERV4_REWRITE_PORT,
    389		SRC4_REWRITE_IP,
    390		SUCCESS,
    391	},
    392	{
    393		"sendmsg4: deny call",
    394		sendmsg_deny_prog_load,
    395		BPF_CGROUP_UDP4_SENDMSG,
    396		BPF_CGROUP_UDP4_SENDMSG,
    397		AF_INET,
    398		SOCK_DGRAM,
    399		SERV4_IP,
    400		SERV4_PORT,
    401		SERV4_REWRITE_IP,
    402		SERV4_REWRITE_PORT,
    403		SRC4_REWRITE_IP,
    404		SYSCALL_EPERM,
    405	},
    406	{
    407		"sendmsg6: load prog with wrong expected attach type",
    408		sendmsg6_rw_asm_prog_load,
    409		BPF_CGROUP_UDP4_SENDMSG,
    410		BPF_CGROUP_UDP6_SENDMSG,
    411		AF_INET6,
    412		SOCK_DGRAM,
    413		NULL,
    414		0,
    415		NULL,
    416		0,
    417		NULL,
    418		LOAD_REJECT,
    419	},
    420	{
    421		"sendmsg6: attach prog with wrong attach type",
    422		sendmsg6_rw_asm_prog_load,
    423		BPF_CGROUP_UDP6_SENDMSG,
    424		BPF_CGROUP_UDP4_SENDMSG,
    425		AF_INET6,
    426		SOCK_DGRAM,
    427		NULL,
    428		0,
    429		NULL,
    430		0,
    431		NULL,
    432		ATTACH_REJECT,
    433	},
    434	{
    435		"sendmsg6: rewrite IP & port (asm)",
    436		sendmsg6_rw_asm_prog_load,
    437		BPF_CGROUP_UDP6_SENDMSG,
    438		BPF_CGROUP_UDP6_SENDMSG,
    439		AF_INET6,
    440		SOCK_DGRAM,
    441		SERV6_IP,
    442		SERV6_PORT,
    443		SERV6_REWRITE_IP,
    444		SERV6_REWRITE_PORT,
    445		SRC6_REWRITE_IP,
    446		SUCCESS,
    447	},
    448	{
    449		"sendmsg6: rewrite IP & port (C)",
    450		sendmsg6_rw_c_prog_load,
    451		BPF_CGROUP_UDP6_SENDMSG,
    452		BPF_CGROUP_UDP6_SENDMSG,
    453		AF_INET6,
    454		SOCK_DGRAM,
    455		SERV6_IP,
    456		SERV6_PORT,
    457		SERV6_REWRITE_IP,
    458		SERV6_REWRITE_PORT,
    459		SRC6_REWRITE_IP,
    460		SUCCESS,
    461	},
    462	{
    463		"sendmsg6: IPv4-mapped IPv6",
    464		sendmsg6_rw_v4mapped_prog_load,
    465		BPF_CGROUP_UDP6_SENDMSG,
    466		BPF_CGROUP_UDP6_SENDMSG,
    467		AF_INET6,
    468		SOCK_DGRAM,
    469		SERV6_IP,
    470		SERV6_PORT,
    471		SERV6_REWRITE_IP,
    472		SERV6_REWRITE_PORT,
    473		SRC6_REWRITE_IP,
    474		SYSCALL_ENOTSUPP,
    475	},
    476	{
    477		"sendmsg6: set dst IP = [::] (BSD'ism)",
    478		sendmsg6_rw_wildcard_prog_load,
    479		BPF_CGROUP_UDP6_SENDMSG,
    480		BPF_CGROUP_UDP6_SENDMSG,
    481		AF_INET6,
    482		SOCK_DGRAM,
    483		SERV6_IP,
    484		SERV6_PORT,
    485		SERV6_REWRITE_IP,
    486		SERV6_REWRITE_PORT,
    487		SRC6_REWRITE_IP,
    488		SUCCESS,
    489	},
    490	{
    491		"sendmsg6: preserve dst IP = [::] (BSD'ism)",
    492		sendmsg_allow_prog_load,
    493		BPF_CGROUP_UDP6_SENDMSG,
    494		BPF_CGROUP_UDP6_SENDMSG,
    495		AF_INET6,
    496		SOCK_DGRAM,
    497		WILDCARD6_IP,
    498		SERV6_PORT,
    499		SERV6_REWRITE_IP,
    500		SERV6_PORT,
    501		SRC6_IP,
    502		SUCCESS,
    503	},
    504	{
    505		"sendmsg6: deny call",
    506		sendmsg_deny_prog_load,
    507		BPF_CGROUP_UDP6_SENDMSG,
    508		BPF_CGROUP_UDP6_SENDMSG,
    509		AF_INET6,
    510		SOCK_DGRAM,
    511		SERV6_IP,
    512		SERV6_PORT,
    513		SERV6_REWRITE_IP,
    514		SERV6_REWRITE_PORT,
    515		SRC6_REWRITE_IP,
    516		SYSCALL_EPERM,
    517	},
    518
    519	/* recvmsg */
    520	{
    521		"recvmsg4: return code ok",
    522		recvmsg_allow_prog_load,
    523		BPF_CGROUP_UDP4_RECVMSG,
    524		BPF_CGROUP_UDP4_RECVMSG,
    525		AF_INET,
    526		SOCK_DGRAM,
    527		NULL,
    528		0,
    529		NULL,
    530		0,
    531		NULL,
    532		ATTACH_OKAY,
    533	},
    534	{
    535		"recvmsg4: return code !ok",
    536		recvmsg_deny_prog_load,
    537		BPF_CGROUP_UDP4_RECVMSG,
    538		BPF_CGROUP_UDP4_RECVMSG,
    539		AF_INET,
    540		SOCK_DGRAM,
    541		NULL,
    542		0,
    543		NULL,
    544		0,
    545		NULL,
    546		LOAD_REJECT,
    547	},
    548	{
    549		"recvmsg6: return code ok",
    550		recvmsg_allow_prog_load,
    551		BPF_CGROUP_UDP6_RECVMSG,
    552		BPF_CGROUP_UDP6_RECVMSG,
    553		AF_INET6,
    554		SOCK_DGRAM,
    555		NULL,
    556		0,
    557		NULL,
    558		0,
    559		NULL,
    560		ATTACH_OKAY,
    561	},
    562	{
    563		"recvmsg6: return code !ok",
    564		recvmsg_deny_prog_load,
    565		BPF_CGROUP_UDP6_RECVMSG,
    566		BPF_CGROUP_UDP6_RECVMSG,
    567		AF_INET6,
    568		SOCK_DGRAM,
    569		NULL,
    570		0,
    571		NULL,
    572		0,
    573		NULL,
    574		LOAD_REJECT,
    575	},
    576	{
    577		"recvmsg4: rewrite IP & port (C)",
    578		recvmsg4_rw_c_prog_load,
    579		BPF_CGROUP_UDP4_RECVMSG,
    580		BPF_CGROUP_UDP4_RECVMSG,
    581		AF_INET,
    582		SOCK_DGRAM,
    583		SERV4_REWRITE_IP,
    584		SERV4_REWRITE_PORT,
    585		SERV4_REWRITE_IP,
    586		SERV4_REWRITE_PORT,
    587		SERV4_IP,
    588		SUCCESS,
    589	},
    590	{
    591		"recvmsg6: rewrite IP & port (C)",
    592		recvmsg6_rw_c_prog_load,
    593		BPF_CGROUP_UDP6_RECVMSG,
    594		BPF_CGROUP_UDP6_RECVMSG,
    595		AF_INET6,
    596		SOCK_DGRAM,
    597		SERV6_REWRITE_IP,
    598		SERV6_REWRITE_PORT,
    599		SERV6_REWRITE_IP,
    600		SERV6_REWRITE_PORT,
    601		SERV6_IP,
    602		SUCCESS,
    603	},
    604};
    605
    606static int mk_sockaddr(int domain, const char *ip, unsigned short port,
    607		       struct sockaddr *addr, socklen_t addr_len)
    608{
    609	struct sockaddr_in6 *addr6;
    610	struct sockaddr_in *addr4;
    611
    612	if (domain != AF_INET && domain != AF_INET6) {
    613		log_err("Unsupported address family");
    614		return -1;
    615	}
    616
    617	memset(addr, 0, addr_len);
    618
    619	if (domain == AF_INET) {
    620		if (addr_len < sizeof(struct sockaddr_in))
    621			return -1;
    622		addr4 = (struct sockaddr_in *)addr;
    623		addr4->sin_family = domain;
    624		addr4->sin_port = htons(port);
    625		if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
    626			log_err("Invalid IPv4: %s", ip);
    627			return -1;
    628		}
    629	} else if (domain == AF_INET6) {
    630		if (addr_len < sizeof(struct sockaddr_in6))
    631			return -1;
    632		addr6 = (struct sockaddr_in6 *)addr;
    633		addr6->sin6_family = domain;
    634		addr6->sin6_port = htons(port);
    635		if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
    636			log_err("Invalid IPv6: %s", ip);
    637			return -1;
    638		}
    639	}
    640
    641	return 0;
    642}
    643
    644static int load_insns(const struct sock_addr_test *test,
    645		      const struct bpf_insn *insns, size_t insns_cnt)
    646{
    647	LIBBPF_OPTS(bpf_prog_load_opts, opts);
    648	int ret;
    649
    650	opts.expected_attach_type = test->expected_attach_type;
    651	opts.log_buf = bpf_log_buf;
    652	opts.log_size = BPF_LOG_BUF_SIZE;
    653
    654	ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, NULL, "GPL", insns, insns_cnt, &opts);
    655	if (ret < 0 && test->expected_result != LOAD_REJECT) {
    656		log_err(">>> Loading program error.\n"
    657			">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
    658	}
    659
    660	return ret;
    661}
    662
    663static int load_path(const struct sock_addr_test *test, const char *path)
    664{
    665	struct bpf_object *obj;
    666	struct bpf_program *prog;
    667	int err;
    668
    669	obj = bpf_object__open_file(path, NULL);
    670	err = libbpf_get_error(obj);
    671	if (err) {
    672		log_err(">>> Opening BPF object (%s) error.\n", path);
    673		return -1;
    674	}
    675
    676	prog = bpf_object__next_program(obj, NULL);
    677	if (!prog)
    678		goto err_out;
    679
    680	bpf_program__set_type(prog, BPF_PROG_TYPE_CGROUP_SOCK_ADDR);
    681	bpf_program__set_expected_attach_type(prog, test->expected_attach_type);
    682	bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32);
    683
    684	err = bpf_object__load(obj);
    685	if (err) {
    686		if (test->expected_result != LOAD_REJECT)
    687			log_err(">>> Loading program (%s) error.\n", path);
    688		goto err_out;
    689	}
    690
    691	return bpf_program__fd(prog);
    692err_out:
    693	bpf_object__close(obj);
    694	return -1;
    695}
    696
    697static int bind4_prog_load(const struct sock_addr_test *test)
    698{
    699	return load_path(test, BIND4_PROG_PATH);
    700}
    701
    702static int bind6_prog_load(const struct sock_addr_test *test)
    703{
    704	return load_path(test, BIND6_PROG_PATH);
    705}
    706
    707static int connect4_prog_load(const struct sock_addr_test *test)
    708{
    709	return load_path(test, CONNECT4_PROG_PATH);
    710}
    711
    712static int connect6_prog_load(const struct sock_addr_test *test)
    713{
    714	return load_path(test, CONNECT6_PROG_PATH);
    715}
    716
    717static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
    718				   int32_t rc)
    719{
    720	struct bpf_insn insns[] = {
    721		/* return rc */
    722		BPF_MOV64_IMM(BPF_REG_0, rc),
    723		BPF_EXIT_INSN(),
    724	};
    725	return load_insns(test, insns, ARRAY_SIZE(insns));
    726}
    727
    728static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
    729{
    730	return xmsg_ret_only_prog_load(test, /*rc*/ 1);
    731}
    732
    733static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
    734{
    735	return xmsg_ret_only_prog_load(test, /*rc*/ 0);
    736}
    737
    738static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
    739{
    740	return xmsg_ret_only_prog_load(test, /*rc*/ 1);
    741}
    742
    743static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
    744{
    745	return xmsg_ret_only_prog_load(test, /*rc*/ 0);
    746}
    747
    748static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
    749{
    750	struct sockaddr_in dst4_rw_addr;
    751	struct in_addr src4_rw_ip;
    752
    753	if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
    754		log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
    755		return -1;
    756	}
    757
    758	if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
    759			(struct sockaddr *)&dst4_rw_addr,
    760			sizeof(dst4_rw_addr)) == -1)
    761		return -1;
    762
    763	struct bpf_insn insns[] = {
    764		BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
    765
    766		/* if (sk.family == AF_INET && */
    767		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
    768			    offsetof(struct bpf_sock_addr, family)),
    769		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8),
    770
    771		/*     sk.type == SOCK_DGRAM)  { */
    772		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
    773			    offsetof(struct bpf_sock_addr, type)),
    774		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6),
    775
    776		/*      msg_src_ip4 = src4_rw_ip */
    777		BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr),
    778		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
    779			    offsetof(struct bpf_sock_addr, msg_src_ip4)),
    780
    781		/*      user_ip4 = dst4_rw_addr.sin_addr */
    782		BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr),
    783		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
    784			    offsetof(struct bpf_sock_addr, user_ip4)),
    785
    786		/*      user_port = dst4_rw_addr.sin_port */
    787		BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port),
    788		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
    789			    offsetof(struct bpf_sock_addr, user_port)),
    790		/* } */
    791
    792		/* return 1 */
    793		BPF_MOV64_IMM(BPF_REG_0, 1),
    794		BPF_EXIT_INSN(),
    795	};
    796
    797	return load_insns(test, insns, ARRAY_SIZE(insns));
    798}
    799
    800static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test)
    801{
    802	return load_path(test, RECVMSG4_PROG_PATH);
    803}
    804
    805static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
    806{
    807	return load_path(test, SENDMSG4_PROG_PATH);
    808}
    809
    810static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
    811					 const char *rw_dst_ip)
    812{
    813	struct sockaddr_in6 dst6_rw_addr;
    814	struct in6_addr src6_rw_ip;
    815
    816	if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
    817		log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
    818		return -1;
    819	}
    820
    821	if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
    822			(struct sockaddr *)&dst6_rw_addr,
    823			sizeof(dst6_rw_addr)) == -1)
    824		return -1;
    825
    826	struct bpf_insn insns[] = {
    827		BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
    828
    829		/* if (sk.family == AF_INET6) { */
    830		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
    831			    offsetof(struct bpf_sock_addr, family)),
    832		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
    833
    834#define STORE_IPV6_WORD_N(DST, SRC, N)					       \
    835		BPF_MOV32_IMM(BPF_REG_7, SRC[N]),			       \
    836		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,		       \
    837			    offsetof(struct bpf_sock_addr, DST[N]))
    838
    839#define STORE_IPV6(DST, SRC)						       \
    840		STORE_IPV6_WORD_N(DST, SRC, 0),				       \
    841		STORE_IPV6_WORD_N(DST, SRC, 1),				       \
    842		STORE_IPV6_WORD_N(DST, SRC, 2),				       \
    843		STORE_IPV6_WORD_N(DST, SRC, 3)
    844
    845		STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32),
    846		STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32),
    847
    848		/*      user_port = dst6_rw_addr.sin6_port */
    849		BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port),
    850		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
    851			    offsetof(struct bpf_sock_addr, user_port)),
    852
    853		/* } */
    854
    855		/* return 1 */
    856		BPF_MOV64_IMM(BPF_REG_0, 1),
    857		BPF_EXIT_INSN(),
    858	};
    859
    860	return load_insns(test, insns, ARRAY_SIZE(insns));
    861}
    862
    863static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
    864{
    865	return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
    866}
    867
    868static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test)
    869{
    870	return load_path(test, RECVMSG6_PROG_PATH);
    871}
    872
    873static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
    874{
    875	return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
    876}
    877
    878static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
    879{
    880	return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
    881}
    882
    883static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
    884{
    885	return load_path(test, SENDMSG6_PROG_PATH);
    886}
    887
    888static int cmp_addr(const struct sockaddr_storage *addr1,
    889		    const struct sockaddr_storage *addr2, int cmp_port)
    890{
    891	const struct sockaddr_in *four1, *four2;
    892	const struct sockaddr_in6 *six1, *six2;
    893
    894	if (addr1->ss_family != addr2->ss_family)
    895		return -1;
    896
    897	if (addr1->ss_family == AF_INET) {
    898		four1 = (const struct sockaddr_in *)addr1;
    899		four2 = (const struct sockaddr_in *)addr2;
    900		return !((four1->sin_port == four2->sin_port || !cmp_port) &&
    901			 four1->sin_addr.s_addr == four2->sin_addr.s_addr);
    902	} else if (addr1->ss_family == AF_INET6) {
    903		six1 = (const struct sockaddr_in6 *)addr1;
    904		six2 = (const struct sockaddr_in6 *)addr2;
    905		return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
    906			 !memcmp(&six1->sin6_addr, &six2->sin6_addr,
    907				 sizeof(struct in6_addr)));
    908	}
    909
    910	return -1;
    911}
    912
    913static int cmp_sock_addr(info_fn fn, int sock1,
    914			 const struct sockaddr_storage *addr2, int cmp_port)
    915{
    916	struct sockaddr_storage addr1;
    917	socklen_t len1 = sizeof(addr1);
    918
    919	memset(&addr1, 0, len1);
    920	if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
    921		return -1;
    922
    923	return cmp_addr(&addr1, addr2, cmp_port);
    924}
    925
    926static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
    927{
    928	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
    929}
    930
    931static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
    932{
    933	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
    934}
    935
    936static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
    937{
    938	return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
    939}
    940
    941static int start_server(int type, const struct sockaddr_storage *addr,
    942			socklen_t addr_len)
    943{
    944	int fd;
    945
    946	fd = socket(addr->ss_family, type, 0);
    947	if (fd == -1) {
    948		log_err("Failed to create server socket");
    949		goto out;
    950	}
    951
    952	if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
    953		log_err("Failed to bind server socket");
    954		goto close_out;
    955	}
    956
    957	if (type == SOCK_STREAM) {
    958		if (listen(fd, 128) == -1) {
    959			log_err("Failed to listen on server socket");
    960			goto close_out;
    961		}
    962	}
    963
    964	goto out;
    965close_out:
    966	close(fd);
    967	fd = -1;
    968out:
    969	return fd;
    970}
    971
    972static int connect_to_server(int type, const struct sockaddr_storage *addr,
    973			     socklen_t addr_len)
    974{
    975	int domain;
    976	int fd = -1;
    977
    978	domain = addr->ss_family;
    979
    980	if (domain != AF_INET && domain != AF_INET6) {
    981		log_err("Unsupported address family");
    982		goto err;
    983	}
    984
    985	fd = socket(domain, type, 0);
    986	if (fd == -1) {
    987		log_err("Failed to create client socket");
    988		goto err;
    989	}
    990
    991	if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
    992		log_err("Fail to connect to server");
    993		goto err;
    994	}
    995
    996	goto out;
    997err:
    998	close(fd);
    999	fd = -1;
   1000out:
   1001	return fd;
   1002}
   1003
   1004int init_pktinfo(int domain, struct cmsghdr *cmsg)
   1005{
   1006	struct in6_pktinfo *pktinfo6;
   1007	struct in_pktinfo *pktinfo4;
   1008
   1009	if (domain == AF_INET) {
   1010		cmsg->cmsg_level = SOL_IP;
   1011		cmsg->cmsg_type = IP_PKTINFO;
   1012		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
   1013		pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg);
   1014		memset(pktinfo4, 0, sizeof(struct in_pktinfo));
   1015		if (inet_pton(domain, SRC4_IP,
   1016			      (void *)&pktinfo4->ipi_spec_dst) != 1)
   1017			return -1;
   1018	} else if (domain == AF_INET6) {
   1019		cmsg->cmsg_level = SOL_IPV6;
   1020		cmsg->cmsg_type = IPV6_PKTINFO;
   1021		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
   1022		pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
   1023		memset(pktinfo6, 0, sizeof(struct in6_pktinfo));
   1024		if (inet_pton(domain, SRC6_IP,
   1025			      (void *)&pktinfo6->ipi6_addr) != 1)
   1026			return -1;
   1027	} else {
   1028		return -1;
   1029	}
   1030
   1031	return 0;
   1032}
   1033
   1034static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
   1035			     socklen_t addr_len, int set_cmsg, int flags,
   1036			     int *syscall_err)
   1037{
   1038	union {
   1039		char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
   1040		struct cmsghdr align;
   1041	} control6;
   1042	union {
   1043		char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
   1044		struct cmsghdr align;
   1045	} control4;
   1046	struct msghdr hdr;
   1047	struct iovec iov;
   1048	char data = 'a';
   1049	int domain;
   1050	int fd = -1;
   1051
   1052	domain = addr->ss_family;
   1053
   1054	if (domain != AF_INET && domain != AF_INET6) {
   1055		log_err("Unsupported address family");
   1056		goto err;
   1057	}
   1058
   1059	fd = socket(domain, type, 0);
   1060	if (fd == -1) {
   1061		log_err("Failed to create client socket");
   1062		goto err;
   1063	}
   1064
   1065	memset(&iov, 0, sizeof(iov));
   1066	iov.iov_base = &data;
   1067	iov.iov_len = sizeof(data);
   1068
   1069	memset(&hdr, 0, sizeof(hdr));
   1070	hdr.msg_name = (void *)addr;
   1071	hdr.msg_namelen = addr_len;
   1072	hdr.msg_iov = &iov;
   1073	hdr.msg_iovlen = 1;
   1074
   1075	if (set_cmsg) {
   1076		if (domain == AF_INET) {
   1077			hdr.msg_control = &control4;
   1078			hdr.msg_controllen = sizeof(control4.buf);
   1079		} else if (domain == AF_INET6) {
   1080			hdr.msg_control = &control6;
   1081			hdr.msg_controllen = sizeof(control6.buf);
   1082		}
   1083		if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
   1084			log_err("Fail to init pktinfo");
   1085			goto err;
   1086		}
   1087	}
   1088
   1089	if (sendmsg(fd, &hdr, flags) != sizeof(data)) {
   1090		log_err("Fail to send message to server");
   1091		*syscall_err = errno;
   1092		goto err;
   1093	}
   1094
   1095	goto out;
   1096err:
   1097	close(fd);
   1098	fd = -1;
   1099out:
   1100	return fd;
   1101}
   1102
   1103static int fastconnect_to_server(const struct sockaddr_storage *addr,
   1104				 socklen_t addr_len)
   1105{
   1106	int sendmsg_err;
   1107
   1108	return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0,
   1109				 MSG_FASTOPEN, &sendmsg_err);
   1110}
   1111
   1112static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
   1113{
   1114	struct timeval tv;
   1115	struct msghdr hdr;
   1116	struct iovec iov;
   1117	char data[64];
   1118	fd_set rfds;
   1119
   1120	FD_ZERO(&rfds);
   1121	FD_SET(sockfd, &rfds);
   1122
   1123	tv.tv_sec = 2;
   1124	tv.tv_usec = 0;
   1125
   1126	if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 ||
   1127	    !FD_ISSET(sockfd, &rfds))
   1128		return -1;
   1129
   1130	memset(&iov, 0, sizeof(iov));
   1131	iov.iov_base = data;
   1132	iov.iov_len = sizeof(data);
   1133
   1134	memset(&hdr, 0, sizeof(hdr));
   1135	hdr.msg_name = src_addr;
   1136	hdr.msg_namelen = sizeof(struct sockaddr_storage);
   1137	hdr.msg_iov = &iov;
   1138	hdr.msg_iovlen = 1;
   1139
   1140	return recvmsg(sockfd, &hdr, 0);
   1141}
   1142
   1143static int init_addrs(const struct sock_addr_test *test,
   1144		      struct sockaddr_storage *requested_addr,
   1145		      struct sockaddr_storage *expected_addr,
   1146		      struct sockaddr_storage *expected_src_addr)
   1147{
   1148	socklen_t addr_len = sizeof(struct sockaddr_storage);
   1149
   1150	if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
   1151			(struct sockaddr *)expected_addr, addr_len) == -1)
   1152		goto err;
   1153
   1154	if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
   1155			(struct sockaddr *)requested_addr, addr_len) == -1)
   1156		goto err;
   1157
   1158	if (test->expected_src_ip &&
   1159	    mk_sockaddr(test->domain, test->expected_src_ip, 0,
   1160			(struct sockaddr *)expected_src_addr, addr_len) == -1)
   1161		goto err;
   1162
   1163	return 0;
   1164err:
   1165	return -1;
   1166}
   1167
   1168static int run_bind_test_case(const struct sock_addr_test *test)
   1169{
   1170	socklen_t addr_len = sizeof(struct sockaddr_storage);
   1171	struct sockaddr_storage requested_addr;
   1172	struct sockaddr_storage expected_addr;
   1173	int clientfd = -1;
   1174	int servfd = -1;
   1175	int err = 0;
   1176
   1177	if (init_addrs(test, &requested_addr, &expected_addr, NULL))
   1178		goto err;
   1179
   1180	servfd = start_server(test->type, &requested_addr, addr_len);
   1181	if (servfd == -1)
   1182		goto err;
   1183
   1184	if (cmp_local_addr(servfd, &expected_addr))
   1185		goto err;
   1186
   1187	/* Try to connect to server just in case */
   1188	clientfd = connect_to_server(test->type, &expected_addr, addr_len);
   1189	if (clientfd == -1)
   1190		goto err;
   1191
   1192	goto out;
   1193err:
   1194	err = -1;
   1195out:
   1196	close(clientfd);
   1197	close(servfd);
   1198	return err;
   1199}
   1200
   1201static int run_connect_test_case(const struct sock_addr_test *test)
   1202{
   1203	socklen_t addr_len = sizeof(struct sockaddr_storage);
   1204	struct sockaddr_storage expected_src_addr;
   1205	struct sockaddr_storage requested_addr;
   1206	struct sockaddr_storage expected_addr;
   1207	int clientfd = -1;
   1208	int servfd = -1;
   1209	int err = 0;
   1210
   1211	if (init_addrs(test, &requested_addr, &expected_addr,
   1212		       &expected_src_addr))
   1213		goto err;
   1214
   1215	/* Prepare server to connect to */
   1216	servfd = start_server(test->type, &expected_addr, addr_len);
   1217	if (servfd == -1)
   1218		goto err;
   1219
   1220	clientfd = connect_to_server(test->type, &requested_addr, addr_len);
   1221	if (clientfd == -1)
   1222		goto err;
   1223
   1224	/* Make sure src and dst addrs were overridden properly */
   1225	if (cmp_peer_addr(clientfd, &expected_addr))
   1226		goto err;
   1227
   1228	if (cmp_local_ip(clientfd, &expected_src_addr))
   1229		goto err;
   1230
   1231	if (test->type == SOCK_STREAM) {
   1232		/* Test TCP Fast Open scenario */
   1233		clientfd = fastconnect_to_server(&requested_addr, addr_len);
   1234		if (clientfd == -1)
   1235			goto err;
   1236
   1237		/* Make sure src and dst addrs were overridden properly */
   1238		if (cmp_peer_addr(clientfd, &expected_addr))
   1239			goto err;
   1240
   1241		if (cmp_local_ip(clientfd, &expected_src_addr))
   1242			goto err;
   1243	}
   1244
   1245	goto out;
   1246err:
   1247	err = -1;
   1248out:
   1249	close(clientfd);
   1250	close(servfd);
   1251	return err;
   1252}
   1253
   1254static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
   1255{
   1256	socklen_t addr_len = sizeof(struct sockaddr_storage);
   1257	struct sockaddr_storage expected_addr;
   1258	struct sockaddr_storage server_addr;
   1259	struct sockaddr_storage sendmsg_addr;
   1260	struct sockaddr_storage recvmsg_addr;
   1261	int clientfd = -1;
   1262	int servfd = -1;
   1263	int set_cmsg;
   1264	int err = 0;
   1265
   1266	if (test->type != SOCK_DGRAM)
   1267		goto err;
   1268
   1269	if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
   1270		goto err;
   1271
   1272	/* Prepare server to sendmsg to */
   1273	servfd = start_server(test->type, &server_addr, addr_len);
   1274	if (servfd == -1)
   1275		goto err;
   1276
   1277	for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
   1278		if (clientfd >= 0)
   1279			close(clientfd);
   1280
   1281		clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
   1282					     addr_len, set_cmsg, /*flags*/0,
   1283					     &err);
   1284		if (err)
   1285			goto out;
   1286		else if (clientfd == -1)
   1287			goto err;
   1288
   1289		/* Try to receive message on server instead of using
   1290		 * getpeername(2) on client socket, to check that client's
   1291		 * destination address was rewritten properly, since
   1292		 * getpeername(2) doesn't work with unconnected datagram
   1293		 * sockets.
   1294		 *
   1295		 * Get source address from recvmsg(2) as well to make sure
   1296		 * source was rewritten properly: getsockname(2) can't be used
   1297		 * since socket is unconnected and source defined for one
   1298		 * specific packet may differ from the one used by default and
   1299		 * returned by getsockname(2).
   1300		 */
   1301		if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
   1302			goto err;
   1303
   1304		if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
   1305			goto err;
   1306	}
   1307
   1308	goto out;
   1309err:
   1310	err = -1;
   1311out:
   1312	close(clientfd);
   1313	close(servfd);
   1314	return err;
   1315}
   1316
   1317static int run_test_case(int cgfd, const struct sock_addr_test *test)
   1318{
   1319	int progfd = -1;
   1320	int err = 0;
   1321
   1322	printf("Test case: %s .. ", test->descr);
   1323
   1324	progfd = test->loadfn(test);
   1325	if (test->expected_result == LOAD_REJECT && progfd < 0)
   1326		goto out;
   1327	else if (test->expected_result == LOAD_REJECT || progfd < 0)
   1328		goto err;
   1329
   1330	err = bpf_prog_attach(progfd, cgfd, test->attach_type,
   1331			      BPF_F_ALLOW_OVERRIDE);
   1332	if (test->expected_result == ATTACH_REJECT && err) {
   1333		err = 0; /* error was expected, reset it */
   1334		goto out;
   1335	} else if (test->expected_result == ATTACH_REJECT || err) {
   1336		goto err;
   1337	} else if (test->expected_result == ATTACH_OKAY) {
   1338		err = 0;
   1339		goto out;
   1340	}
   1341
   1342	switch (test->attach_type) {
   1343	case BPF_CGROUP_INET4_BIND:
   1344	case BPF_CGROUP_INET6_BIND:
   1345		err = run_bind_test_case(test);
   1346		break;
   1347	case BPF_CGROUP_INET4_CONNECT:
   1348	case BPF_CGROUP_INET6_CONNECT:
   1349		err = run_connect_test_case(test);
   1350		break;
   1351	case BPF_CGROUP_UDP4_SENDMSG:
   1352	case BPF_CGROUP_UDP6_SENDMSG:
   1353		err = run_xmsg_test_case(test, 1);
   1354		break;
   1355	case BPF_CGROUP_UDP4_RECVMSG:
   1356	case BPF_CGROUP_UDP6_RECVMSG:
   1357		err = run_xmsg_test_case(test, 0);
   1358		break;
   1359	default:
   1360		goto err;
   1361	}
   1362
   1363	if (test->expected_result == SYSCALL_EPERM && err == EPERM) {
   1364		err = 0; /* error was expected, reset it */
   1365		goto out;
   1366	}
   1367
   1368	if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) {
   1369		err = 0; /* error was expected, reset it */
   1370		goto out;
   1371	}
   1372
   1373	if (err || test->expected_result != SUCCESS)
   1374		goto err;
   1375
   1376	goto out;
   1377err:
   1378	err = -1;
   1379out:
   1380	/* Detaching w/o checking return code: best effort attempt. */
   1381	if (progfd != -1)
   1382		bpf_prog_detach(cgfd, test->attach_type);
   1383	close(progfd);
   1384	printf("[%s]\n", err ? "FAIL" : "PASS");
   1385	return err;
   1386}
   1387
   1388static int run_tests(int cgfd)
   1389{
   1390	int passes = 0;
   1391	int fails = 0;
   1392	int i;
   1393
   1394	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
   1395		if (run_test_case(cgfd, &tests[i]))
   1396			++fails;
   1397		else
   1398			++passes;
   1399	}
   1400	printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
   1401	return fails ? -1 : 0;
   1402}
   1403
   1404int main(int argc, char **argv)
   1405{
   1406	int cgfd = -1;
   1407	int err = 0;
   1408
   1409	if (argc < 2) {
   1410		fprintf(stderr,
   1411			"%s has to be run via %s.sh. Skip direct run.\n",
   1412			argv[0], argv[0]);
   1413		exit(err);
   1414	}
   1415
   1416	cgfd = cgroup_setup_and_join(CG_PATH);
   1417	if (cgfd < 0)
   1418		goto err;
   1419
   1420	/* Use libbpf 1.0 API mode */
   1421	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
   1422
   1423	if (run_tests(cgfd))
   1424		goto err;
   1425
   1426	goto out;
   1427err:
   1428	err = -1;
   1429out:
   1430	close(cgfd);
   1431	cleanup_cgroup_environment();
   1432	return err;
   1433}