diff options
author | Nicolas Douma <nicolas@serveur.io> | 2020-04-28 16:40:15 +0200 |
---|---|---|
committer | Nicolas Douma <nicolas@serveur.io> | 2020-04-28 16:40:15 +0200 |
commit | a6880abb439e0fa48ea8c1cbd90f51919cba33da (patch) | |
tree | c1b0749772911491508892347726ffe88f31467b | |
parent | Pad struct bpf_load_program_attr with zeroes in case new fields are added (diff) | |
download | netifexec-a6880abb439e0fa48ea8c1cbd90f51919cba33da.tar.xz netifexec-a6880abb439e0fa48ea8c1cbd90f51919cba33da.zip |
Make SO_BINDTODEVICE return -EPERM instead of nothing
-rw-r--r-- | netifexec.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/netifexec.c b/netifexec.c index c2f014d..f488678 100644 --- a/netifexec.c +++ b/netifexec.c @@ -1,4 +1,3 @@ -#include <linux/version.h> #include <sys/eventfd.h> #include <sys/prctl.h> #include <sys/types.h> @@ -12,9 +11,7 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> -#include <limits.h> #include <fcntl.h> -#include <stdio.h> #include <time.h> #include <mntent.h> #include <errno.h> @@ -237,11 +234,11 @@ static int ifindex(const char *ifname) * @param bpf_name The expect name of the eBPF program * @return A boolean that tells whether the eBPF program is effective. */ -static bool bpf_already_effective(int cgroupfd, const char *bpf_name) +static bool bpf_already_effective(int cgroupfd, int attach_type, const char *bpf_name) { uint32_t bpf_prog_ids[1024]; uint32_t attach_flags, prog_cnt = sizeof(bpf_prog_ids) / sizeof(*bpf_prog_ids); - CHK(bpf_prog_query(cgroupfd, BPF_CGROUP_INET_SOCK_CREATE, BPF_F_QUERY_EFFECTIVE, + CHK(bpf_prog_query(cgroupfd, attach_type, BPF_F_QUERY_EFFECTIVE, &attach_flags, bpf_prog_ids, &prog_cnt), "Unable to query bpf programs on cgroup"); bool has_bpf = false; if (prog_cnt > 0) { @@ -383,7 +380,7 @@ static void hook_sock_create(int cgroupfd, char *iface) if (snprintf(bpf_name, sizeof(bpf_name), "netifexec_%s", iface) >= sizeof(bpf_name)) errx(1, "Interface name too long"); - if (bpf_already_effective(cgroupfd, bpf_name)) + if (bpf_already_effective(cgroupfd, BPF_CGROUP_INET_SOCK_CREATE, bpf_name)) return; int index = ifindex(iface); @@ -436,28 +433,26 @@ static void hook_setsockopt(int cgroupfd, char *iface) if (snprintf(bpf_name, sizeof(bpf_name), "sopt_%s", iface) >= sizeof(bpf_name)) errx(1, "Interface name too long"); - if (bpf_already_effective(cgroupfd, bpf_name)) + if (bpf_already_effective(cgroupfd, BPF_CGROUP_SETSOCKOPT, bpf_name)) return; /* - * 0: (61) r2 = *(u32 *)(r1 +24) - * 1: (55) if r2 != 0x1 goto pc+5 - * 2: (61) r2 = *(u32 *)(r1 +28) - * 3: (55) if r2 != 0x19 goto pc+3 - * 4: (18) r2 = 0xffffffff - * 6: (63) *(u32 *)(r1 +32) = r2 - * 7: (b7) r0 = 1 - * 8: (95) exit + * 0: (b7) r0 = 1 + * 1: (61) r2 = *(u32 *)(r1 +24) + * 2: (55) if r2 != 0x1 goto pc+3 + * 3: (61) r2 = *(u32 *)(r1 +28) + * 4: (55) if r2 != 0x19 goto pc+1 + * 5: (b7) r0 = 0 + * 6: (95) exit */ struct bpf_insn bpf_program[] = { + BPF_MOV64_IMM(BPF_REG_0, SK_PASS), BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct bpf_sockopt, level)), - BPF_JMP_IMM(BPF_AND, BPF_REG_2, SOL_SOCKET, 5), + BPF_JMP_IMM(BPF_AND, BPF_REG_2, SOL_SOCKET, 3), BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct bpf_sockopt, optname)), - BPF_JMP_IMM(BPF_AND, BPF_REG_2, SO_BINDTODEVICE, 3), - BPF_LD_IMM64(BPF_REG_2, 0xFFFFFFFFUL), - BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_2, offsetof(struct bpf_sockopt, optlen)), - BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_JMP_IMM(BPF_AND, BPF_REG_2, SO_BINDTODEVICE, 1), + BPF_MOV64_IMM(BPF_REG_0, SK_DROP), BPF_EXIT_INSN() }; |