fix-interface-comparissons-in-dash-C-commands.patch (6736B)
1 Url: https://git.netfilter.org/iptables/patch/?id=40406dbfaefbc204134452b2747bae4f6a122848 2 From 40406dbfaefbc204134452b2747bae4f6a122848 Mon Sep 17 00:00:00 2001 3 From: Jeremy Sowden <jeremy@azazel.net> 4 Date: Mon, 18 Nov 2024 13:56:50 +0000 5 Subject: nft: fix interface comparisons in `-C` commands 6 7 Commit 9ccae6397475 ("nft: Leave interface masks alone when parsing from 8 kernel") removed code which explicitly set interface masks to all ones. The 9 result of this is that they are zero. However, they are used to mask interfaces 10 in `is_same_interfaces`. Consequently, the masked values are alway zero, the 11 comparisons are always true, and check commands which ought to fail succeed: 12 13 # iptables -N test 14 # iptables -A test -i lo \! -o lo -j REJECT 15 # iptables -v -L test 16 Chain test (0 references) 17 pkts bytes target prot opt in out source destination 18 0 0 REJECT all -- lo !lo anywhere anywhere reject-with icmp-port-unreachable 19 # iptables -v -C test -i abcdefgh \! -o abcdefgh -j REJECT 20 REJECT all opt -- in lo out !lo 0.0.0.0/0 -> 0.0.0.0/0 reject-with icmp-port-unreachable 21 22 Remove the mask parameters from `is_same_interfaces`. Add a test-case. 23 24 Fixes: 9ccae6397475 ("nft: Leave interface masks alone when parsing from kernel") 25 Signed-off-by: Jeremy Sowden <jeremy@azazel.net> 26 Signed-off-by: Phil Sutter <phil@nwl.cc> 27 --- 28 iptables/nft-arp.c | 10 ++---- 29 iptables/nft-ipv4.c | 4 +-- 30 iptables/nft-ipv6.c | 6 +--- 31 iptables/nft-shared.c | 36 +++++----------------- 32 iptables/nft-shared.h | 6 +--- 33 .../testcases/nft-only/0020-compare-interfaces_0 | 9 ++++++ 34 6 files changed, 22 insertions(+), 49 deletions(-) 35 create mode 100755 iptables/tests/shell/testcases/nft-only/0020-compare-interfaces_0 36 37 diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c 38 index 264864c3..c11d64c3 100644 39 --- a/iptables/nft-arp.c 40 +++ b/iptables/nft-arp.c 41 @@ -385,14 +385,8 @@ static bool nft_arp_is_same(const struct iptables_command_state *cs_a, 42 return false; 43 } 44 45 - return is_same_interfaces(a->arp.iniface, 46 - a->arp.outiface, 47 - (unsigned char *)a->arp.iniface_mask, 48 - (unsigned char *)a->arp.outiface_mask, 49 - b->arp.iniface, 50 - b->arp.outiface, 51 - (unsigned char *)b->arp.iniface_mask, 52 - (unsigned char *)b->arp.outiface_mask); 53 + return is_same_interfaces(a->arp.iniface, a->arp.outiface, 54 + b->arp.iniface, b->arp.outiface); 55 } 56 57 static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy) 58 diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c 59 index 74092875..0c8bd291 100644 60 --- a/iptables/nft-ipv4.c 61 +++ b/iptables/nft-ipv4.c 62 @@ -113,9 +113,7 @@ static bool nft_ipv4_is_same(const struct iptables_command_state *a, 63 } 64 65 return is_same_interfaces(a->fw.ip.iniface, a->fw.ip.outiface, 66 - a->fw.ip.iniface_mask, a->fw.ip.outiface_mask, 67 - b->fw.ip.iniface, b->fw.ip.outiface, 68 - b->fw.ip.iniface_mask, b->fw.ip.outiface_mask); 69 + b->fw.ip.iniface, b->fw.ip.outiface); 70 } 71 72 static void nft_ipv4_set_goto_flag(struct iptables_command_state *cs) 73 diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c 74 index b184f8af..4dbb2af2 100644 75 --- a/iptables/nft-ipv6.c 76 +++ b/iptables/nft-ipv6.c 77 @@ -99,11 +99,7 @@ static bool nft_ipv6_is_same(const struct iptables_command_state *a, 78 } 79 80 return is_same_interfaces(a->fw6.ipv6.iniface, a->fw6.ipv6.outiface, 81 - a->fw6.ipv6.iniface_mask, 82 - a->fw6.ipv6.outiface_mask, 83 - b->fw6.ipv6.iniface, b->fw6.ipv6.outiface, 84 - b->fw6.ipv6.iniface_mask, 85 - b->fw6.ipv6.outiface_mask); 86 + b->fw6.ipv6.iniface, b->fw6.ipv6.outiface); 87 } 88 89 static void nft_ipv6_set_goto_flag(struct iptables_command_state *cs) 90 diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c 91 index 6775578b..2c29e68f 100644 92 --- a/iptables/nft-shared.c 93 +++ b/iptables/nft-shared.c 94 @@ -220,36 +220,16 @@ void add_l4proto(struct nft_handle *h, struct nftnl_rule *r, 95 } 96 97 bool is_same_interfaces(const char *a_iniface, const char *a_outiface, 98 - unsigned const char *a_iniface_mask, 99 - unsigned const char *a_outiface_mask, 100 - const char *b_iniface, const char *b_outiface, 101 - unsigned const char *b_iniface_mask, 102 - unsigned const char *b_outiface_mask) 103 + const char *b_iniface, const char *b_outiface) 104 { 105 - int i; 106 - 107 - for (i = 0; i < IFNAMSIZ; i++) { 108 - if (a_iniface_mask[i] != b_iniface_mask[i]) { 109 - DEBUGP("different iniface mask %x, %x (%d)\n", 110 - a_iniface_mask[i] & 0xff, b_iniface_mask[i] & 0xff, i); 111 - return false; 112 - } 113 - if ((a_iniface[i] & a_iniface_mask[i]) 114 - != (b_iniface[i] & b_iniface_mask[i])) { 115 - DEBUGP("different iniface\n"); 116 - return false; 117 - } 118 - if (a_outiface_mask[i] != b_outiface_mask[i]) { 119 - DEBUGP("different outiface mask\n"); 120 - return false; 121 - } 122 - if ((a_outiface[i] & a_outiface_mask[i]) 123 - != (b_outiface[i] & b_outiface_mask[i])) { 124 - DEBUGP("different outiface\n"); 125 - return false; 126 - } 127 + if (strncmp(a_iniface, b_iniface, IFNAMSIZ)) { 128 + DEBUGP("different iniface\n"); 129 + return false; 130 + } 131 + if (strncmp(a_outiface, b_outiface, IFNAMSIZ)) { 132 + DEBUGP("different outiface\n"); 133 + return false; 134 } 135 - 136 return true; 137 } 138 139 diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h 140 index 51d1e460..b57aee1f 100644 141 --- a/iptables/nft-shared.h 142 +++ b/iptables/nft-shared.h 143 @@ -105,11 +105,7 @@ void add_l4proto(struct nft_handle *h, struct nftnl_rule *r, uint8_t proto, uint 144 void add_compat(struct nftnl_rule *r, uint32_t proto, bool inv); 145 146 bool is_same_interfaces(const char *a_iniface, const char *a_outiface, 147 - unsigned const char *a_iniface_mask, 148 - unsigned const char *a_outiface_mask, 149 - const char *b_iniface, const char *b_outiface, 150 - unsigned const char *b_iniface_mask, 151 - unsigned const char *b_outiface_mask); 152 + const char *b_iniface, const char *b_outiface); 153 154 void __get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, uint8_t *op); 155 void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv); 156 diff --git a/iptables/tests/shell/testcases/nft-only/0020-compare-interfaces_0 b/iptables/tests/shell/testcases/nft-only/0020-compare-interfaces_0 157 new file mode 100755 158 index 00000000..278cd648 159 --- /dev/null 160 +++ b/iptables/tests/shell/testcases/nft-only/0020-compare-interfaces_0 161 @@ -0,0 +1,9 @@ 162 +#!/bin/bash 163 + 164 +[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } 165 + 166 +$XT_MULTI iptables -N test 167 +$XT_MULTI iptables -A test -i lo \! -o lo -j REJECT 168 +$XT_MULTI iptables -C test -i abcdefgh \! -o abcdefgh -j REJECT 2>/dev/null && exit 1 169 + 170 +exit 0 171 -- 172 cgit v1.2.3 173