From 9df1a36a98aaf167993501c32ff7a10a38913f50 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 10 Feb 2018 13:23:03 +0100 Subject: sys/linux: add bridge netfilter support --- executor/common_linux.h | 97 +++++++++++++++++++++++++++++++++++++++++++++++ executor/syscalls_linux.h | 25 +++++++----- 2 files changed, 112 insertions(+), 10 deletions(-) (limited to 'executor') diff --git a/executor/common_linux.h b/executor/common_linux.h index 5128009dd..37cc9c5ea 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -1232,8 +1232,104 @@ static void reset_arptables() close(fd); } +#include + +struct ebt_table_desc { + const char* name; + struct ebt_replace replace; + char entrytable[XT_TABLE_SIZE]; +}; + +static struct ebt_table_desc ebt_tables[] = { + {.name = "filter"}, + {.name = "nat"}, + {.name = "broute"}, +}; + +static void checkpoint_ebtables(void) +{ + socklen_t optlen; + unsigned i; + int fd; + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + fail("socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)"); + for (i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) { + struct ebt_table_desc* table = &ebt_tables[i]; + strcpy(table->replace.name, table->name); + optlen = sizeof(table->replace); + if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_INFO, &table->replace, &optlen)) { + switch (errno) { + case EPERM: + case ENOENT: + case ENOPROTOOPT: + continue; + } + fail("getsockopt(EBT_SO_GET_INIT_INFO)"); + } + debug("checkpoint ebtable %s: entries=%d hooks=%x size=%d\n", table->name, table->replace.nentries, table->replace.valid_hooks, table->replace.entries_size); + if (table->replace.entries_size > sizeof(table->entrytable)) + fail("table size is too large: %u", table->replace.entries_size); + table->replace.num_counters = 0; + table->replace.entries = table->entrytable; + optlen = sizeof(table->replace) + table->replace.entries_size; + if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_ENTRIES, &table->replace, &optlen)) + fail("getsockopt(EBT_SO_GET_INIT_ENTRIES)"); + } + close(fd); +} + +static void reset_ebtables() +{ + struct ebt_replace replace; + char entrytable[XT_TABLE_SIZE]; + socklen_t optlen; + unsigned i, j, h; + int fd; + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) + fail("socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)"); + for (i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) { + struct ebt_table_desc* table = &ebt_tables[i]; + if (table->replace.valid_hooks == 0) + continue; + memset(&replace, 0, sizeof(replace)); + strcpy(replace.name, table->name); + optlen = sizeof(replace); + if (getsockopt(fd, SOL_IP, EBT_SO_GET_INFO, &replace, &optlen)) + fail("getsockopt(EBT_SO_GET_INFO)"); + replace.num_counters = 0; + for (h = 0; h < NF_BR_NUMHOOKS; h++) + table->replace.hook_entry[h] = 0; + if (memcmp(&table->replace, &replace, sizeof(table->replace)) == 0) { + memset(&entrytable, 0, sizeof(entrytable)); + replace.entries = entrytable; + optlen = sizeof(replace) + replace.entries_size; + if (getsockopt(fd, SOL_IP, EBT_SO_GET_ENTRIES, &replace, &optlen)) + fail("getsockopt(EBT_SO_GET_ENTRIES)"); + if (memcmp(table->entrytable, entrytable, replace.entries_size) == 0) + continue; + } + debug("resetting ebtable %s\n", table->name); + // Kernel does not seem to return actual entry points (wat?). + for (j = 0, h = 0; h < NF_BR_NUMHOOKS; h++) { + if (table->replace.valid_hooks & (1 << h)) { + table->replace.hook_entry[h] = (struct ebt_entries*)table->entrytable + j; + j++; + } + } + optlen = sizeof(table->replace) + table->replace.entries_size; + if (setsockopt(fd, SOL_IP, EBT_SO_SET_ENTRIES, &table->replace, optlen)) + fail("setsockopt(EBT_SO_SET_ENTRIES)"); + } + close(fd); +} + static void checkpoint_net_namespace(void) { + checkpoint_ebtables(); checkpoint_arptables(); checkpoint_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP); checkpoint_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6); @@ -1241,6 +1337,7 @@ static void checkpoint_net_namespace(void) static void reset_net_namespace(void) { + reset_ebtables(); reset_arptables(); reset_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP); reset_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6); diff --git a/executor/syscalls_linux.h b/executor/syscalls_linux.h index edbf9a79c..0bbab652a 100644 --- a/executor/syscalls_linux.h +++ b/executor/syscalls_linux.h @@ -2,8 +2,8 @@ #if defined(__i386__) || 0 #define GOARCH "386" -#define SYZ_REVISION "d82c642c1409d036404216acd5d0886572f581f6" -unsigned syscall_count = 1582; +#define SYZ_REVISION "1d92abf94e3a94a587c23e34ff517226557eb39b" +unsigned syscall_count = 1583; call_t syscalls[] = { {"accept4", 364}, {"accept4$alg", 364}, @@ -1200,6 +1200,7 @@ call_t syscalls[] = { {"setsockopt$ALG_SET_AEAD_AUTHSIZE", 366}, {"setsockopt$ALG_SET_KEY", 366}, {"setsockopt$ARPT_SO_SET_REPLACE", 366}, + {"setsockopt$EBT_SO_SET_ENTRIES", 366}, {"setsockopt$IP6T_SO_SET_REPLACE", 366}, {"setsockopt$IPT_SO_SET_REPLACE", 366}, {"setsockopt$RDS_CANCEL_SENT_TO", 366}, @@ -1593,8 +1594,8 @@ call_t syscalls[] = { #if defined(__x86_64__) || 0 #define GOARCH "amd64" -#define SYZ_REVISION "54bb54ead4b62281da500ec1751ca2932e1441f4" -unsigned syscall_count = 1635; +#define SYZ_REVISION "c063297cc1f7a742899148ea3e480a503975e1a3" +unsigned syscall_count = 1636; call_t syscalls[] = { {"accept", 43}, {"accept$alg", 43}, @@ -2832,6 +2833,7 @@ call_t syscalls[] = { {"setsockopt$ALG_SET_AEAD_AUTHSIZE", 54}, {"setsockopt$ALG_SET_KEY", 54}, {"setsockopt$ARPT_SO_SET_REPLACE", 54}, + {"setsockopt$EBT_SO_SET_ENTRIES", 54}, {"setsockopt$IP6T_SO_SET_REPLACE", 54}, {"setsockopt$IPT_SO_SET_REPLACE", 54}, {"setsockopt$RDS_CANCEL_SENT_TO", 54}, @@ -3237,8 +3239,8 @@ call_t syscalls[] = { #if defined(__arm__) || 0 #define GOARCH "arm" -#define SYZ_REVISION "fe2bd7c6f616382bfcaf3834e90cbba612c30578" -unsigned syscall_count = 1592; +#define SYZ_REVISION "2a035864a56374d1ef4eafcffb968f43fd5b075c" +unsigned syscall_count = 1593; call_t syscalls[] = { {"accept", 285}, {"accept$alg", 285}, @@ -4436,6 +4438,7 @@ call_t syscalls[] = { {"setsockopt$ALG_SET_AEAD_AUTHSIZE", 294}, {"setsockopt$ALG_SET_KEY", 294}, {"setsockopt$ARPT_SO_SET_REPLACE", 294}, + {"setsockopt$EBT_SO_SET_ENTRIES", 294}, {"setsockopt$IP6T_SO_SET_REPLACE", 294}, {"setsockopt$IPT_SO_SET_REPLACE", 294}, {"setsockopt$RDS_CANCEL_SENT_TO", 294}, @@ -4838,8 +4841,8 @@ call_t syscalls[] = { #if defined(__aarch64__) || 0 #define GOARCH "arm64" -#define SYZ_REVISION "a647e74461d106215be994c7e4a030e46be581f4" -unsigned syscall_count = 1564; +#define SYZ_REVISION "033a3d40f0ba2f8c5ebeb2a344a44e89db17e105" +unsigned syscall_count = 1565; call_t syscalls[] = { {"accept", 202}, {"accept$alg", 202}, @@ -6018,6 +6021,7 @@ call_t syscalls[] = { {"setsockopt$ALG_SET_AEAD_AUTHSIZE", 208}, {"setsockopt$ALG_SET_KEY", 208}, {"setsockopt$ARPT_SO_SET_REPLACE", 208}, + {"setsockopt$EBT_SO_SET_ENTRIES", 208}, {"setsockopt$IP6T_SO_SET_REPLACE", 208}, {"setsockopt$IPT_SO_SET_REPLACE", 208}, {"setsockopt$RDS_CANCEL_SENT_TO", 208}, @@ -6411,8 +6415,8 @@ call_t syscalls[] = { #if defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || 0 #define GOARCH "ppc64le" -#define SYZ_REVISION "76a3156b1ae121f74fe5b00f7d0a88b139d13cd6" -unsigned syscall_count = 1554; +#define SYZ_REVISION "c996439d4a7c1dc76b269b6869f8bb2b505550b3" +unsigned syscall_count = 1555; call_t syscalls[] = { {"accept", 330}, {"accept$alg", 330}, @@ -7582,6 +7586,7 @@ call_t syscalls[] = { {"setsockopt$ALG_SET_AEAD_AUTHSIZE", 339}, {"setsockopt$ALG_SET_KEY", 339}, {"setsockopt$ARPT_SO_SET_REPLACE", 339}, + {"setsockopt$EBT_SO_SET_ENTRIES", 339}, {"setsockopt$IP6T_SO_SET_REPLACE", 339}, {"setsockopt$IPT_SO_SET_REPLACE", 339}, {"setsockopt$RDS_CANCEL_SENT_TO", 339}, -- cgit mrf-deployment