2018-03-30 15:08:08 -07:00
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018 Facebook
# include <stdio.h>
# include <unistd.h>
# include <arpa/inet.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <linux/filter.h>
# include <bpf/bpf.h>
# include "cgroup_helpers.h"
2020-01-20 14:06:45 +01:00
# include <bpf/bpf_endian.h>
2018-04-18 10:49:12 -07:00
# include "bpf_rlimit.h"
2018-08-08 01:01:27 -07:00
# include "bpf_util.h"
2018-03-30 15:08:08 -07:00
# define CG_PATH " / foo"
# define MAX_INSNS 512
char bpf_log_buf [ BPF_LOG_BUF_SIZE ] ;
tools/bpf: add log_level to bpf_load_program_attr
The kernel verifier has three levels of logs:
0: no logs
1: logs mostly useful
> 1: verbose
Current libbpf API functions bpf_load_program_xattr() and
bpf_load_program() cannot specify log_level.
The bcc, however, provides an interface for user to
specify log_level 2 for verbose output.
This patch added log_level into structure
bpf_load_program_attr, so users, including bcc, can use
bpf_load_program_xattr() to change log_level. The
supported log_level is 0, 1, and 2.
The bpf selftest test_sock.c is modified to enable log_level = 2.
If the "verbose" in test_sock.c is changed to true,
the test will output logs like below:
$ ./test_sock
func#0 @0
0: R1=ctx(id=0,off=0,imm=0) R10=fp0,call_-1
0: (bf) r6 = r1
1: R1=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0) R10=fp0,call_-1
1: (61) r7 = *(u32 *)(r6 +28)
invalid bpf_context access off=28 size=4
Test case: bind4 load with invalid access: src_ip6 .. [PASS]
...
Test case: bind6 allow all .. [PASS]
Summary: 16 PASSED, 0 FAILED
Some test_sock tests are negative tests and verbose verifier
log will be printed out as shown in the above.
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-02-07 09:34:51 -08:00
static bool verbose = false ;
2018-03-30 15:08:08 -07:00
struct sock_test {
const char * descr ;
/* BPF prog properties */
struct bpf_insn insns [ MAX_INSNS ] ;
enum bpf_attach_type expected_attach_type ;
enum bpf_attach_type attach_type ;
/* Socket properties */
int domain ;
int type ;
/* Endpoint to bind() to */
const char * ip ;
unsigned short port ;
2022-01-06 21:20:22 +08:00
unsigned short port_retry ;
2018-03-30 15:08:08 -07:00
/* Expected test result */
enum {
LOAD_REJECT ,
ATTACH_REJECT ,
BIND_REJECT ,
SUCCESS ,
2022-01-06 21:20:22 +08:00
RETRY_SUCCESS ,
RETRY_REJECT
2018-03-30 15:08:08 -07:00
} result ;
} ;
static struct sock_test tests [ ] = {
{
2022-01-06 21:20:21 +08:00
. descr = " bind4 load with invalid access: src_ip6 " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip6 [ 0 ] ) ) ,
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. result = LOAD_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind4 load with invalid access: mark " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , mark ) ) ,
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. result = LOAD_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind6 load with invalid access: src_ip4 " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip4 ) ) ,
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. result = LOAD_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " sock_create load with invalid access: src_port " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. result = LOAD_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " sock_create load w/o expected_attach_type (compat mode) " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = 0 ,
. attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 127.0.0.1 " ,
. port = 8097 ,
. result = SUCCESS ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " sock_create load w/ expected_attach_type " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 127.0.0.1 " ,
. port = 8097 ,
. result = SUCCESS ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " attach type mismatch bind4 vs bind6 " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. result = ATTACH_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " attach type mismatch bind6 vs bind4 " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. result = ATTACH_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " attach type mismatch default vs bind4 " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = 0 ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. result = ATTACH_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " attach type mismatch bind6 vs sock_create " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET_SOCK_CREATE ,
. result = ATTACH_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind4 reject all " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 0.0.0.0 " ,
. result = BIND_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind6 reject all " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. domain = AF_INET6 ,
. type = SOCK_STREAM ,
. ip = " :: " ,
. result = BIND_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind6 deny specific IP & port " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
/* if (ip == expected && port == expected) */
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip6 [ 3 ] ) ) ,
2019-08-14 12:41:09 +02:00
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 ,
__bpf_constant_ntohl ( 0x00000001 ) , 4 ) ,
2018-03-30 15:08:08 -07:00
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 , 0x2001 , 2 ) ,
/* return DENY; */
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_JMP_A ( 1 ) ,
/* else return ALLOW; */
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. domain = AF_INET6 ,
. type = SOCK_STREAM ,
. ip = " ::1 " ,
. port = 8193 ,
. result = BIND_REJECT ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind4 allow specific IP & port " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
/* if (ip == expected && port == expected) */
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip4 ) ) ,
2019-08-14 12:41:09 +02:00
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 ,
__bpf_constant_ntohl ( 0x7F000001 ) , 4 ) ,
2018-03-30 15:08:08 -07:00
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 , 0x1002 , 2 ) ,
/* return ALLOW; */
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_JMP_A ( 1 ) ,
/* else return DENY; */
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 127.0.0.1 " ,
. port = 4098 ,
. result = SUCCESS ,
2018-03-30 15:08:08 -07:00
} ,
2022-01-06 21:20:22 +08:00
{
. descr = " bind4 deny specific IP & port of TCP, and retry " ,
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
/* if (ip == expected && port == expected) */
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip4 ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 ,
__bpf_constant_ntohl ( 0x7F000001 ) , 4 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 , 0x1002 , 2 ) ,
/* return DENY; */
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_JMP_A ( 1 ) ,
/* else return ALLOW; */
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 127.0.0.1 " ,
. port = 4098 ,
. port_retry = 5000 ,
. result = RETRY_SUCCESS ,
} ,
{
. descr = " bind4 deny specific IP & port of UDP, and retry " ,
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
/* if (ip == expected && port == expected) */
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip4 ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 ,
__bpf_constant_ntohl ( 0x7F000001 ) , 4 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 , 0x1002 , 2 ) ,
/* return DENY; */
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_JMP_A ( 1 ) ,
/* else return ALLOW; */
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. domain = AF_INET ,
. type = SOCK_DGRAM ,
. ip = " 127.0.0.1 " ,
. port = 4098 ,
. port_retry = 5000 ,
. result = RETRY_SUCCESS ,
} ,
{
. descr = " bind6 deny specific IP & port, and retry " ,
. insns = {
BPF_MOV64_REG ( BPF_REG_6 , BPF_REG_1 ) ,
/* if (ip == expected && port == expected) */
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_ip6 [ 3 ] ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 ,
__bpf_constant_ntohl ( 0x00000001 ) , 4 ) ,
BPF_LDX_MEM ( BPF_W , BPF_REG_7 , BPF_REG_6 ,
offsetof ( struct bpf_sock , src_port ) ) ,
BPF_JMP_IMM ( BPF_JNE , BPF_REG_7 , 0x2001 , 2 ) ,
/* return DENY; */
BPF_MOV64_IMM ( BPF_REG_0 , 0 ) ,
BPF_JMP_A ( 1 ) ,
/* else return ALLOW; */
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. domain = AF_INET6 ,
. type = SOCK_STREAM ,
. ip = " ::1 " ,
. port = 8193 ,
. port_retry = 9000 ,
. result = RETRY_SUCCESS ,
} ,
2018-03-30 15:08:08 -07:00
{
2022-01-06 21:20:21 +08:00
. descr = " bind4 allow all " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET4_POST_BIND ,
. attach_type = BPF_CGROUP_INET4_POST_BIND ,
. domain = AF_INET ,
. type = SOCK_STREAM ,
. ip = " 0.0.0.0 " ,
. result = SUCCESS ,
2018-03-30 15:08:08 -07:00
} ,
{
2022-01-06 21:20:21 +08:00
. descr = " bind6 allow all " ,
2018-03-30 15:08:08 -07:00
. insns = {
BPF_MOV64_IMM ( BPF_REG_0 , 1 ) ,
BPF_EXIT_INSN ( ) ,
} ,
2022-01-06 21:20:21 +08:00
. expected_attach_type = BPF_CGROUP_INET6_POST_BIND ,
. attach_type = BPF_CGROUP_INET6_POST_BIND ,
. domain = AF_INET6 ,
. type = SOCK_STREAM ,
. ip = " :: " ,
. result = SUCCESS ,
2018-03-30 15:08:08 -07:00
} ,
} ;
static size_t probe_prog_length ( const struct bpf_insn * fp )
{
size_t len ;
for ( len = MAX_INSNS - 1 ; len > 0 ; - - len )
if ( fp [ len ] . code ! = 0 | | fp [ len ] . imm ! = 0 )
break ;
return len + 1 ;
}
static int load_sock_prog ( const struct bpf_insn * prog ,
enum bpf_attach_type attach_type )
{
2021-11-03 15:08:42 -07:00
LIBBPF_OPTS ( bpf_prog_load_opts , opts ) ;
int ret , insn_cnt ;
2018-03-30 15:08:08 -07:00
2021-11-03 15:08:42 -07:00
insn_cnt = probe_prog_length ( prog ) ;
2018-03-30 15:08:08 -07:00
2021-11-03 15:08:42 -07:00
opts . expected_attach_type = attach_type ;
opts . log_buf = bpf_log_buf ;
opts . log_size = BPF_LOG_BUF_SIZE ;
opts . log_level = 2 ;
ret = bpf_prog_load ( BPF_PROG_TYPE_CGROUP_SOCK , NULL , " GPL " , prog , insn_cnt , & opts ) ;
tools/bpf: add log_level to bpf_load_program_attr
The kernel verifier has three levels of logs:
0: no logs
1: logs mostly useful
> 1: verbose
Current libbpf API functions bpf_load_program_xattr() and
bpf_load_program() cannot specify log_level.
The bcc, however, provides an interface for user to
specify log_level 2 for verbose output.
This patch added log_level into structure
bpf_load_program_attr, so users, including bcc, can use
bpf_load_program_xattr() to change log_level. The
supported log_level is 0, 1, and 2.
The bpf selftest test_sock.c is modified to enable log_level = 2.
If the "verbose" in test_sock.c is changed to true,
the test will output logs like below:
$ ./test_sock
func#0 @0
0: R1=ctx(id=0,off=0,imm=0) R10=fp0,call_-1
0: (bf) r6 = r1
1: R1=ctx(id=0,off=0,imm=0) R6_w=ctx(id=0,off=0,imm=0) R10=fp0,call_-1
1: (61) r7 = *(u32 *)(r6 +28)
invalid bpf_context access off=28 size=4
Test case: bind4 load with invalid access: src_ip6 .. [PASS]
...
Test case: bind6 allow all .. [PASS]
Summary: 16 PASSED, 0 FAILED
Some test_sock tests are negative tests and verbose verifier
log will be printed out as shown in the above.
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-02-07 09:34:51 -08:00
if ( verbose & & ret < 0 )
fprintf ( stderr , " %s \n " , bpf_log_buf ) ;
return ret ;
2018-03-30 15:08:08 -07:00
}
static int attach_sock_prog ( int cgfd , int progfd ,
enum bpf_attach_type attach_type )
{
return bpf_prog_attach ( progfd , cgfd , attach_type , BPF_F_ALLOW_OVERRIDE ) ;
}
2022-01-06 21:20:22 +08:00
static int bind_sock ( int domain , int type , const char * ip ,
unsigned short port , unsigned short port_retry )
2018-03-30 15:08:08 -07:00
{
struct sockaddr_storage addr ;
struct sockaddr_in6 * addr6 ;
struct sockaddr_in * addr4 ;
int sockfd = - 1 ;
socklen_t len ;
2022-01-06 21:20:22 +08:00
int res = SUCCESS ;
2018-03-30 15:08:08 -07:00
sockfd = socket ( domain , type , 0 ) ;
if ( sockfd < 0 )
goto err ;
memset ( & addr , 0 , sizeof ( addr ) ) ;
if ( domain = = AF_INET ) {
len = sizeof ( struct sockaddr_in ) ;
addr4 = ( struct sockaddr_in * ) & addr ;
addr4 - > sin_family = domain ;
addr4 - > sin_port = htons ( port ) ;
if ( inet_pton ( domain , ip , ( void * ) & addr4 - > sin_addr ) ! = 1 )
goto err ;
} else if ( domain = = AF_INET6 ) {
len = sizeof ( struct sockaddr_in6 ) ;
addr6 = ( struct sockaddr_in6 * ) & addr ;
addr6 - > sin6_family = domain ;
addr6 - > sin6_port = htons ( port ) ;
if ( inet_pton ( domain , ip , ( void * ) & addr6 - > sin6_addr ) ! = 1 )
goto err ;
} else {
goto err ;
}
2022-01-06 21:20:22 +08:00
if ( bind ( sockfd , ( const struct sockaddr * ) & addr , len ) = = - 1 ) {
/* sys_bind() may fail for different reasons, errno has to be
* checked to confirm that BPF program rejected it .
*/
if ( errno ! = EPERM )
goto err ;
if ( port_retry )
goto retry ;
res = BIND_REJECT ;
goto out ;
}
2018-03-30 15:08:08 -07:00
2022-01-06 21:20:22 +08:00
goto out ;
retry :
if ( domain = = AF_INET )
addr4 - > sin_port = htons ( port_retry ) ;
else
addr6 - > sin6_port = htons ( port_retry ) ;
if ( bind ( sockfd , ( const struct sockaddr * ) & addr , len ) = = - 1 ) {
if ( errno ! = EPERM )
goto err ;
res = RETRY_REJECT ;
} else {
res = RETRY_SUCCESS ;
}
2018-03-30 15:08:08 -07:00
goto out ;
err :
2022-01-06 21:20:22 +08:00
res = - 1 ;
2018-03-30 15:08:08 -07:00
out :
close ( sockfd ) ;
2022-01-06 21:20:22 +08:00
return res ;
2018-03-30 15:08:08 -07:00
}
static int run_test_case ( int cgfd , const struct sock_test * test )
{
int progfd = - 1 ;
int err = 0 ;
2022-01-06 21:20:22 +08:00
int res ;
2018-03-30 15:08:08 -07:00
printf ( " Test case: %s .. " , test - > descr ) ;
progfd = load_sock_prog ( test - > insns , test - > expected_attach_type ) ;
if ( progfd < 0 ) {
if ( test - > result = = LOAD_REJECT )
goto out ;
else
goto err ;
}
if ( attach_sock_prog ( cgfd , progfd , test - > attach_type ) = = - 1 ) {
if ( test - > result = = ATTACH_REJECT )
goto out ;
else
goto err ;
}
2022-01-06 21:20:22 +08:00
res = bind_sock ( test - > domain , test - > type , test - > ip , test - > port ,
test - > port_retry ) ;
if ( res > 0 & & test - > result = = res )
goto out ;
2018-03-30 15:08:08 -07:00
err :
err = - 1 ;
out :
/* Detaching w/o checking return code: best effort attempt. */
if ( progfd ! = - 1 )
bpf_prog_detach ( cgfd , test - > attach_type ) ;
close ( progfd ) ;
printf ( " [%s] \n " , err ? " FAIL " : " PASS " ) ;
return err ;
}
static int run_tests ( int cgfd )
{
int passes = 0 ;
int fails = 0 ;
int i ;
for ( i = 0 ; i < ARRAY_SIZE ( tests ) ; + + i ) {
if ( run_test_case ( cgfd , & tests [ i ] ) )
+ + fails ;
else
+ + passes ;
}
printf ( " Summary: %d PASSED, %d FAILED \n " , passes , fails ) ;
return fails ? - 1 : 0 ;
}
int main ( int argc , char * * argv )
{
int cgfd = - 1 ;
int err = 0 ;
2020-07-31 15:09:14 -07:00
cgfd = cgroup_setup_and_join ( CG_PATH ) ;
2019-01-07 09:46:46 -08:00
if ( cgfd < 0 )
2018-03-30 15:08:08 -07:00
goto err ;
if ( run_tests ( cgfd ) )
goto err ;
goto out ;
err :
err = - 1 ;
out :
close ( cgfd ) ;
cleanup_cgroup_environment ( ) ;
return err ;
}