0001-nft-fix-interface-comparisons-in-C-commands.patch 6.7 KB

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