From f3988dd0a1884f7b569d64dd44b57b6d840bd4fe Mon Sep 17 00:00:00 2001 From: chengyechun Date: Mon, 26 Dec 2022 21:06:13 +0800 Subject: [PATCH] iptables:fix iptables docker daemon error --- ...-messages-for-unsupported-extensions.patch | 90 +++++++ ...xtensions-register-in-revision-order.patch | 126 +++++++++ ...ltiple-extensions-in-ascending-order.patch | 50 ++++ ...-only-the-highest-revision-extension.patch | 70 +++++ ...plify-pending-extension-registration.patch | 241 ++++++++++++++++++ ...andling-for-extensions-without-rev-0.patch | 69 +++++ ...d-Fix-response-to-unprivileged-users.patch | 130 ++++++++++ iptables.spec | 17 +- 8 files changed, 792 insertions(+), 1 deletion(-) create mode 100644 backport-Improve-error-messages-for-unsupported-extensions.patch create mode 100644 backport-libxtables-Make-sure-extensions-register-in-revision-order.patch create mode 100644 backport-libxtables-Register-multiple-extensions-in-ascending-order.patch create mode 100644 backport-libxtables-Register-only-the-highest-revision-extension.patch create mode 100644 backport-libxtables-Simplify-pending-extension-registration.patch create mode 100644 backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch create mode 100644 backport-xshared-Fix-response-to-unprivileged-users.patch diff --git a/backport-Improve-error-messages-for-unsupported-extensions.patch b/backport-Improve-error-messages-for-unsupported-extensions.patch new file mode 100644 index 0000000..778d103 --- /dev/null +++ b/backport-Improve-error-messages-for-unsupported-extensions.patch @@ -0,0 +1,90 @@ +From 17534cb18ed0a5052dc45c117401251359dba6aa Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 11 Feb 2022 17:47:22 +0100 +Subject: Improve error messages for unsupported extensions + +If a given extension was not supported by the kernel, iptables would +print a rather confusing error message if extension parameters were +given: + +| # rm /lib/modules/$(uname -r)/kernel/net/netfilter/xt_LOG.ko +| # iptables -A FORWARD -j LOG --log-prefix foo +| iptables v1.8.7 (legacy): unknown option "--log-prefix" + +Avoid this by pretending extension revision 0 is always supported. It is +the same hack as used to successfully print extension help texts as +unprivileged user, extended to all error codes to serve privileged ones +as well. + +In addition, print a warning if kernel rejected revision 0 and it's not +a permissions problem. This helps users find out which extension in a +rule the kernel didn't like. + +Finally, the above commands result in these messages: + +| Warning: Extension LOG revision 0 not supported, missing kernel +module? +| iptables: No chain/target/match by that name. + +Or, for iptables-nft: + +| Warning: Extension LOG revision 0 not supported, missing kernel +module? +| iptables v1.8.7 (nf_tables): RULE_APPEND failed (No such file or +directory): rule in chain FORWARD + +Conflict: NA +Reference: +https://git.netfilter.org/iptables/commit/?id=17534cb18ed0a5052dc45c117401251359dba6aa +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 13 +++++++++---- + libxtables/xtables.c | 7 ++++++- + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index c9a4940..18bf21c 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3245,11 +3245,16 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt) + err: + mnl_socket_close(nl); + +- /* pretend revision 0 is valid if not permitted to check - +- * this is required for printing extension help texts as user */ +- if (ret < 0 && errno == EPERM && rev == 0) ++ /* pretend revision 0 is valid - ++ * this is required for printing extension help texts as user, also ++ * helps error messaging on unavailable kernel extension */ ++ if (ret < 0 && rev == 0) { ++ if (errno != EPERM) ++ fprintf(stderr, ++ "Warning: Extension %s revision 0 not supported, missing kernel module?\n", ++ name); + return 1; +- ++ } + return ret < 0 ? 0 : 1; + } + +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index bc42ba8..1f585e5 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -923,7 +923,12 @@ int xtables_compatible_revision(const char *name, uint8_t revision, int opt) + /* Definitely don't support this? */ + if (errno == ENOENT || errno == EPROTONOSUPPORT) { + close(sockfd); +- return 0; ++ /* Pretend revision 0 support for better error messaging */ ++ if (revision == 0) ++ fprintf(stderr, ++ "Warning: Extension %s revision 0 not supported, missing kernel module?\n", ++ name); ++ return (revision == 0); + } else if (errno == ENOPROTOOPT) { + close(sockfd); + /* Assume only revision 0 support (old kernel) */ +-- +2.23.0 + diff --git a/backport-libxtables-Make-sure-extensions-register-in-revision-order.patch b/backport-libxtables-Make-sure-extensions-register-in-revision-order.patch new file mode 100644 index 0000000..0d4b995 --- /dev/null +++ b/backport-libxtables-Make-sure-extensions-register-in-revision-order.patch @@ -0,0 +1,126 @@ +From b3ac87038f4e45141831d9ab485a2f627daba3f1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 21 Sep 2020 13:42:06 +0200 +Subject: libxtables: Make sure extensions register in revision order + +Insert extensions into pending lists in ordered fashion: Group by +extension name (and, for matches, family) and order groups by descending +revision number. + +This allows to simplify the later full registration considerably. Since +that involves kernel compatibility checks, the extra cycles here pay off +eventually. + +Signed-off-by: Phil Sutter +--- + libxtables/xtables.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 64 insertions(+), 7 deletions(-) + +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index 8907ba20..de52e3e2 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -948,8 +948,14 @@ static void xtables_check_options(const char *name, const struct option *opt) + } + } + ++static int xtables_match_prefer(const struct xtables_match *a, ++ const struct xtables_match *b); ++ + void xtables_register_match(struct xtables_match *me) + { ++ struct xtables_match **pos; ++ bool seen_myself = false; ++ + if (me->next) { + fprintf(stderr, "%s: match \"%s\" already registered\n", + xt_params->program_name, me->name); +@@ -1001,10 +1007,34 @@ void xtables_register_match(struct xtables_match *me) + if (me->extra_opts != NULL) + xtables_check_options(me->name, me->extra_opts); + +- +- /* place on linked list of matches pending full registration */ +- me->next = xtables_pending_matches; +- xtables_pending_matches = me; ++ /* order into linked list of matches pending full registration */ ++ for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) { ++ /* group by name and family */ ++ if (strcmp(me->name, (*pos)->name) || ++ me->family != (*pos)->family) { ++ if (seen_myself) ++ break; /* end of own group, append to it */ ++ continue; ++ } ++ /* found own group */ ++ seen_myself = true; ++ if (xtables_match_prefer(me, *pos) >= 0) ++ break; /* put preferred items first in group */ ++ } ++ /* if own group was not found, prepend item */ ++ if (!*pos && !seen_myself) ++ pos = &xtables_pending_matches; ++ ++ me->next = *pos; ++ *pos = me; ++#ifdef DEBUG ++ printf("%s: inserted match %s (family %d, revision %d):\n", ++ __func__, me->name, me->family, me->revision); ++ for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) { ++ printf("%s:\tmatch %s (family %d, revision %d)\n", __func__, ++ (*pos)->name, (*pos)->family, (*pos)->revision); ++ } ++#endif + } + + /** +@@ -1143,6 +1173,9 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n) + + void xtables_register_target(struct xtables_target *me) + { ++ struct xtables_target **pos; ++ bool seen_myself = false; ++ + if (me->next) { + fprintf(stderr, "%s: target \"%s\" already registered\n", + xt_params->program_name, me->name); +@@ -1198,9 +1231,33 @@ void xtables_register_target(struct xtables_target *me) + if (me->family != afinfo->family && me->family != AF_UNSPEC) + return; + +- /* place on linked list of targets pending full registration */ +- me->next = xtables_pending_targets; +- xtables_pending_targets = me; ++ /* order into linked list of targets pending full registration */ ++ for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) { ++ /* group by name */ ++ if (!extension_cmp(me->name, (*pos)->name, (*pos)->family)) { ++ if (seen_myself) ++ break; /* end of own group, append to it */ ++ continue; ++ } ++ /* found own group */ ++ seen_myself = true; ++ if (xtables_target_prefer(me, *pos) >= 0) ++ break; /* put preferred items first in group */ ++ } ++ /* if own group was not found, prepend item */ ++ if (!*pos && !seen_myself) ++ pos = &xtables_pending_targets; ++ ++ me->next = *pos; ++ *pos = me; ++#ifdef DEBUG ++ printf("%s: inserted target %s (family %d, revision %d):\n", ++ __func__, me->name, me->family, me->revision); ++ for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) { ++ printf("%s:\ttarget %s (family %d, revision %d)\n", __func__, ++ (*pos)->name, (*pos)->family, (*pos)->revision); ++ } ++#endif + } + + static bool xtables_fully_register_pending_target(struct xtables_target *me) +-- +cgit v1.2.3 + diff --git a/backport-libxtables-Register-multiple-extensions-in-ascending-order.patch b/backport-libxtables-Register-multiple-extensions-in-ascending-order.patch new file mode 100644 index 0000000..79cd772 --- /dev/null +++ b/backport-libxtables-Register-multiple-extensions-in-ascending-order.patch @@ -0,0 +1,50 @@ +From b5f1a3beac1d1f2b96c8be8ebec450f5ea758090 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 22 Sep 2020 20:01:15 +0200 +Subject: libxtables: Register multiple extensions in ascending order + +The newly introduced ordered insert algorithm in +xtables_register_{match,target}() works best if extensions of same name +are passed in ascending revisions. Since this is the case in about all +extensions' arrays, iterate over them from beginning to end. + +Signed-off-by: Phil Sutter +--- + libxtables/xtables.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index 10d4e703..7152c657 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -1141,9 +1141,10 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me, + + void xtables_register_matches(struct xtables_match *match, unsigned int n) + { +- do { +- xtables_register_match(&match[--n]); +- } while (n > 0); ++ int i; ++ ++ for (i = 0; i < n; i++) ++ xtables_register_match(&match[i]); + } + + void xtables_register_target(struct xtables_target *me) +@@ -1269,9 +1270,10 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me, + + void xtables_register_targets(struct xtables_target *target, unsigned int n) + { +- do { +- xtables_register_target(&target[--n]); +- } while (n > 0); ++ int i; ++ ++ for (i = 0; i < n; i++) ++ xtables_register_target(&target[i]); + } + + /* receives a list of xtables_rule_match, release them */ +-- +cgit v1.2.3 + diff --git a/backport-libxtables-Register-only-the-highest-revision-extension.patch b/backport-libxtables-Register-only-the-highest-revision-extension.patch new file mode 100644 index 0000000..37a2ed9 --- /dev/null +++ b/backport-libxtables-Register-only-the-highest-revision-extension.patch @@ -0,0 +1,70 @@ +From 2dbb49d15fb44ddd521a734eca3be3f940b7c1ba Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 11 Feb 2022 17:39:24 +0100 +Subject: libxtables: Register only the highest revision extension + +When fully registering extensions, ignore all consecutive ones with same +name and family value. Since commit b3ac87038f4e4 ("libxtables: Make +sure extensions register in revision order"), one may safely assume the +list of pending extensions has highest revision numbers first. Since +iptables is only interested in the highest revision the kernel supports, +registration and compatibility checks may be skipped once the first +matching extension in pending list has validated. + +Conflict: NA +Reference: +https://git.netfilter.org/iptables/commit/?id=2dbb49d15fb44ddd521a734eca3be3f940b7c1ba +Signed-off-by: Phil Sutter +--- + libxtables/xtables.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index a3d0609..bba7fbb 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -664,6 +664,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, + struct xtables_match **dptr; + struct xtables_match *ptr; + const char *icmp6 = "icmp6"; ++ bool found = false; + + if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) + xtables_error(PARAMETER_PROBLEM, +@@ -682,8 +683,10 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, + if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { + ptr = *dptr; + *dptr = (*dptr)->next; +- if (xtables_fully_register_pending_match(ptr, prev)) { +- prev = ptr; ++ if (!found && ++ xtables_fully_register_pending_match(ptr, prev)) { ++ found = true; ++ prev = ptr; + continue; + } else if (prev) { + continue; +@@ -784,6 +787,7 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) + struct xtables_target *prev = NULL; + struct xtables_target **dptr; + struct xtables_target *ptr; ++ bool found = false; + + /* Standard target? */ + if (strcmp(name, "") == 0 +@@ -798,8 +802,10 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) + if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { + ptr = *dptr; + *dptr = (*dptr)->next; +- if (xtables_fully_register_pending_target(ptr, prev)) { +- prev = ptr; ++ if (!found && ++ xtables_fully_register_pending_target(ptr, prev)) { ++ found = true; ++ prev = ptr; + continue; + } else if (prev) { + continue; +-- +2.23.0 + diff --git a/backport-libxtables-Simplify-pending-extension-registration.patch b/backport-libxtables-Simplify-pending-extension-registration.patch new file mode 100644 index 0000000..4e19b51 --- /dev/null +++ b/backport-libxtables-Simplify-pending-extension-registration.patch @@ -0,0 +1,241 @@ + +From a1eaaceb0460b338294e40bdd5bc5186320a478c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 18 Sep 2020 18:48:14 +0200 +Subject: libxtables: Simplify pending extension registration + +Assuming that pending extensions are sorted by first name and family, +then descending revision, the decision where to insert a newly +registered extension may be simplified by memorizing the previous +registration (which obviously is of same name and family and higher +revision). + +As a side-effect, fix for unsupported old extension revisions lingering +in pending extension list forever and being retried with every use of +the given extension. Any revision being rejected by the kernel may +safely be dropped iff a previous (read: higher) revision was accepted +already. + +Yet another side-effect of this change is the removal of an unwanted +recursion by xtables_fully_register_pending_*() into itself via +xtables_find_*(). + +Signed-off-by: Phil Sutter +--- + libxtables/xtables.c | 130 +++++++++++-------------------------------- + 1 file changed, 34 insertions(+), 96 deletions(-) + +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index 9a8f8fb..988a0c7 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -203,8 +203,10 @@ struct xtables_match *xtables_matches; + struct xtables_target *xtables_targets; + + /* Fully register a match/target which was previously partially registered. */ +-static bool xtables_fully_register_pending_match(struct xtables_match *me); +-static bool xtables_fully_register_pending_target(struct xtables_target *me); ++static bool xtables_fully_register_pending_match(struct xtables_match *me, ++ struct xtables_match *prev); ++static bool xtables_fully_register_pending_target(struct xtables_target *me, ++ struct xtables_target *prev); + + /* registry for loaded shared objects to close later */ + struct dlreg { +@@ -658,6 +660,7 @@ struct xtables_match * + xtables_find_match(const char *name, enum xtables_tryload tryload, + struct xtables_rule_match **matches) + { ++ struct xtables_match *prev = NULL; + struct xtables_match **dptr; + struct xtables_match *ptr; + const char *icmp6 = "icmp6"; +@@ -679,8 +682,12 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, + if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { + ptr = *dptr; + *dptr = (*dptr)->next; +- if (xtables_fully_register_pending_match(ptr)) +- continue; ++ if (xtables_fully_register_pending_match(ptr, prev)) { ++ prev = ptr; ++ continue; ++ } else if (prev) { ++ continue; ++ } + *dptr = ptr; + } + dptr = &((*dptr)->next); +@@ -774,6 +781,7 @@ xtables_find_match_revision(const char *name, enum xtables_tryload tryload, + struct xtables_target * + xtables_find_target(const char *name, enum xtables_tryload tryload) + { ++ struct xtables_target *prev = NULL; + struct xtables_target **dptr; + struct xtables_target *ptr; + +@@ -790,8 +798,12 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) + if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { + ptr = *dptr; + *dptr = (*dptr)->next; +- if (xtables_fully_register_pending_target(ptr)) ++ if (xtables_fully_register_pending_target(ptr, prev)) { ++ prev = ptr; + continue; ++ } else if (prev) { ++ continue; ++ } + *dptr = ptr; + } + dptr = &((*dptr)->next); +@@ -1099,64 +1111,27 @@ static int xtables_target_prefer(const struct xtables_target *a, + b->revision, b->family); + } + +-static bool xtables_fully_register_pending_match(struct xtables_match *me) ++static bool xtables_fully_register_pending_match(struct xtables_match *me, ++ struct xtables_match *prev) + { +- struct xtables_match **i, *old, *pos = NULL; ++ struct xtables_match **i; + const char *rn; +- int compare; + + /* See if new match can be used. */ + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_match_revision(rn, me->revision)) + return false; + +- old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); +- while (old) { +- compare = xtables_match_prefer(old, me); +- if (compare == 0) { +- fprintf(stderr, +- "%s: match `%s' already registered.\n", +- xt_params->program_name, me->name); +- exit(1); +- } +- +- /* Now we have two (or more) options, check compatibility. */ +- rn = (old->real_name != NULL) ? old->real_name : old->name; +- if (compare > 0) { +- /* Kernel tells old isn't compatible anymore??? */ +- if (!compatible_match_revision(rn, old->revision)) { +- /* Delete old one. */ +- for (i = &xtables_matches; *i != old;) +- i = &(*i)->next; +- *i = old->next; +- } +- pos = old; +- old = old->next; +- if (!old) +- break; +- if (!extension_cmp(me->name, old->name, old->family)) +- break; +- continue; +- } +- +- /* Found right old */ +- pos = old; +- break; +- } +- +- if (!pos) { ++ if (!prev) { + /* Append to list. */ + for (i = &xtables_matches; *i; i = &(*i)->next); +- } else if (compare < 0) { +- /* Prepend it */ +- for (i = &xtables_matches; *i != pos; i = &(*i)->next); +- } else if (compare > 0) { ++ } else { + /* Append it */ +- i = &pos->next; +- pos = pos->next; ++ i = &prev->next; ++ prev = prev->next; + } + +- me->next = pos; ++ me->next = prev; + *i = me; + + me->m = NULL; +@@ -1262,11 +1237,11 @@ void xtables_register_target(struct xtables_target *me) + #endif + } + +-static bool xtables_fully_register_pending_target(struct xtables_target *me) ++static bool xtables_fully_register_pending_target(struct xtables_target *me, ++ struct xtables_target *prev) + { +- struct xtables_target **i, *old, *pos = NULL; ++ struct xtables_target **i; + const char *rn; +- int compare; + + if (strcmp(me->name, "standard") != 0) { + /* See if new target can be used. */ +@@ -1275,54 +1250,17 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me) + return false; + } + +- old = xtables_find_target(me->name, XTF_DURING_LOAD); +- while (old) { +- compare = xtables_target_prefer(old, me); +- if (compare == 0) { +- fprintf(stderr, +- "%s: target `%s' already registered.\n", +- xt_params->program_name, me->name); +- exit(1); +- } +- +- /* Now we have two (or more) options, check compatibility. */ +- rn = (old->real_name != NULL) ? old->real_name : old->name; +- if (compare > 0) { +- /* Kernel tells old isn't compatible anymore??? */ +- if (!compatible_target_revision(rn, old->revision)) { +- /* Delete old one. */ +- for (i = &xtables_targets; *i != old;) +- i = &(*i)->next; +- *i = old->next; +- } +- pos = old; +- old = old->next; +- if (!old) +- break; +- if (!extension_cmp(me->name, old->name, old->family)) +- break; +- continue; +- } +- +- /* Found right old */ +- pos = old; +- break; +- } +- +- if (!pos) { ++ if (!prev) { + /* Prepend to list. */ + i = &xtables_targets; +- pos = xtables_targets; +- } else if (compare < 0) { +- /* Prepend it */ +- for (i = &xtables_targets; *i != pos; i = &(*i)->next); +- } else if (compare > 0) { ++ prev = xtables_targets; ++ } else { + /* Append it */ +- i = &pos->next; +- pos = pos->next; ++ i = &prev->next; ++ prev = prev->next; + } + +- me->next = pos; ++ me->next = prev; + *i = me; + + me->t = NULL; +-- +2.23.0 + diff --git a/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch b/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch new file mode 100644 index 0000000..6bfb868 --- /dev/null +++ b/backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch @@ -0,0 +1,69 @@ +From 8468fd4f7c85c21ab375402bc80d0188412b6cbf Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 4 May 2022 11:19:16 +0200 +Subject: nft: Fix EPERM handling for extensions without rev 0 + +Treating revision 0 as compatible in EPERM case works fine as long as +there is a revision 0 of that extension defined in DSO. Fix the code for +others: Extend the EPERM handling to all revisions and keep the existing +warning for revision 0. + +Conflict: NA +Reference: +https://git.netfilter.org/iptables/commit/?id=8468fd4f7c85c21ab375402bc80d0188412b6cbf +Fixes: 17534cb18ed0a ("Improve error messages for unsupported +extensions") +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 11 +++++++---- + .../shell/testcases/iptables/0008-unprivileged_0 | 7 +++++++ + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 18bf21c..ebab3cc 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3245,15 +3245,18 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt) + err: + mnl_socket_close(nl); + +- /* pretend revision 0 is valid - ++ /* ignore EPERM and errors for revision 0 - + * this is required for printing extension help texts as user, also + * helps error messaging on unavailable kernel extension */ +- if (ret < 0 && rev == 0) { +- if (errno != EPERM) ++ if (ret < 0) { ++ if (errno == EPERM) ++ return 1; ++ if (rev == 0) { + fprintf(stderr, + "Warning: Extension %s revision 0 not supported, missing kernel module?\n", + name); +- return 1; ++ return 1; ++ } + } + return ret < 0 ? 0 : 1; + } +diff --git a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 +index 0914c88..1f1d342 100644 +--- a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 ++++ b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 +@@ -34,6 +34,13 @@ let "rc+=$?" + grep_or_rc "DNAT target options:" <<< "$out" + let "rc+=$?" + ++# TEE has no revision 0 ++out=$(run $XT_MULTI iptables -j TEE --help) ++let "rc+=$?" ++grep_or_rc "TEE target options:" <<< "$out" ++let "rc+=$?" ++ ++ + out=$(run $XT_MULTI iptables -p tcp -j DNAT --help) + let "rc+=$?" + grep_or_rc "tcp match options:" <<< "$out" +-- +2.23.0 + diff --git a/backport-xshared-Fix-response-to-unprivileged-users.patch b/backport-xshared-Fix-response-to-unprivileged-users.patch new file mode 100644 index 0000000..e5f574b --- /dev/null +++ b/backport-xshared-Fix-response-to-unprivileged-users.patch @@ -0,0 +1,130 @@ +From 26ecdf53960658771c0fc582f72a4025e2887f75 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 18 Jan 2022 22:39:08 +0100 +Subject: xshared: Fix response to unprivileged users + +Expected behaviour in both variants is: + +* Print help without error, append extension help if -m and/or -j + options are present +* Indicate lack of permissions in an error message for anything else + +With iptables-nft, this was broken basically from day 1. Shared use of +do_parse() then somewhat broke legacy: it started complaining about +inability to create a lock file. + +Fix this by making iptables-nft assume extension revision 0 is present +if permissions don't allow to verify. This is consistent with legacy. + +Second part is to exit directly after printing help - this avoids having +to make the following code "nop-aware" to prevent privileged actions. + +Conflict: NA +Reference: +https://git.netfilter.org/iptables/commit/?id=26ecdf53960658771c0fc582f72a4025e2887f75 +Signed-off-by: Phil Sutter +Reviewed-by: Florian Westphal +--- + iptables/nft.c | 5 ++ + .../testcases/iptables/0008-unprivileged_0 | 59 +++++++++++++++++++ + iptables/xtables.c | 2 +- + 3 files changed, 65 insertions(+), 1 deletion(-) + create mode 100644 iptables/tests/shell/testcases/iptables/0008-unprivileged_0 + +diff --git a/iptables/nft.c b/iptables/nft.c +index bde4ca7..c9a4940 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3245,6 +3245,11 @@ int nft_compatible_revision(const char *name, uint8_t rev, int opt) + err: + mnl_socket_close(nl); + ++ /* pretend revision 0 is valid if not permitted to check - ++ * this is required for printing extension help texts as user */ ++ if (ret < 0 && errno == EPERM && rev == 0) ++ return 1; ++ + return ret < 0 ? 0 : 1; + } + +diff --git a/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 +new file mode 100644 +index 0000000..0914c88 +--- /dev/null ++++ b/iptables/tests/shell/testcases/iptables/0008-unprivileged_0 +@@ -0,0 +1,59 @@ ++#!/bin/bash ++# iptables may print match/target specific help texts ++# help output should work for unprivileged users ++ ++run() { ++ echo "running: $*" >&2 ++ runuser -u nobody -- "$@" ++} ++ ++grep_or_rc() { ++ declare -g rc ++ grep -q "$*" && return 0 ++ echo "missing in output: $*" >&2 ++ return 1 ++} ++ ++out=$(run $XT_MULTI iptables --help) ++let "rc+=$?" ++grep_or_rc "iptables -h (print this help information)" <<< "$out" ++let "rc+=$?" ++ ++out=$(run $XT_MULTI iptables -m limit --help) ++let "rc+=$?" ++grep_or_rc "limit match options:" <<< "$out" ++let "rc+=$?" ++ ++out=$(run $XT_MULTI iptables -p tcp --help) ++let "rc+=$?" ++grep_or_rc "tcp match options:" <<< "$out" ++let "rc+=$?" ++ ++out=$(run $XT_MULTI iptables -j DNAT --help) ++let "rc+=$?" ++grep_or_rc "DNAT target options:" <<< "$out" ++let "rc+=$?" ++ ++out=$(run $XT_MULTI iptables -p tcp -j DNAT --help) ++let "rc+=$?" ++grep_or_rc "tcp match options:" <<< "$out" ++let "rc+=$?" ++out=$(run $XT_MULTI iptables -p tcp -j DNAT --help) ++let "rc+=$?" ++grep_or_rc "DNAT target options:" <<< "$out" ++let "rc+=$?" ++ ++ ++run $XT_MULTI iptables -L 2>&1 | \ ++ grep_or_rc "Permission denied" ++let "rc+=$?" ++ ++run $XT_MULTI iptables -A FORWARD -p tcp --dport 123 2>&1 | \ ++ grep_or_rc "Permission denied" ++let "rc+=$?" ++ ++run $XT_MULTI iptables -A FORWARD -j DNAT --to-destination 1.2.3.4 2>&1 | \ ++ grep_or_rc "Permission denied" ++let "rc+=$?" ++ ++exit $rc +diff --git a/iptables/xtables.c b/iptables/xtables.c +index 9779bd8..a16bba7 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -645,7 +645,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], + + printhelp(cs->matches); + p->command = CMD_NONE; +- return; ++ exit(0); + + /* + * Option selection +-- +2.23.0 + diff --git a/iptables.spec b/iptables.spec index 972a8c6..84d8f9a 100644 --- a/iptables.spec +++ b/iptables.spec @@ -2,7 +2,7 @@ %global legacy_actions %{_libexecdir}/initscripts/legacy-actions Name: iptables Version: 1.8.5 -Release: 4 +Release: 5 Summary: IP packet filter administration utilities License: GPLv2 and Artistic Licence 2.0 and ISC URL: https://www.netfilter.org/ @@ -13,6 +13,15 @@ Source3: iptables.service Source4: sysconfig_iptables Source5: sysconfig_ip6tables +Patch6001: backport-xshared-Fix-response-to-unprivileged-users.patch +Patch6002: backport-Improve-error-messages-for-unsupported-extensions.patch +Patch6003: backport-nft-Fix-EPERM-handling-for-extensions-without-rev-0.patch +Patch6004: backport-libxtables-Make-sure-extensions-register-in-revision-order.patch +Patch6005: backport-libxtables-Register-multiple-extensions-in-ascending-order.patch +Patch6006: backport-libxtables-Simplify-pending-extension-registration.patch +Patch6007: backport-libxtables-Register-only-the-highest-revision-extension.patch + + BuildRequires: bison flex gcc kernel-headers libpcap-devel libselinux-devel systemd git BuildRequires: libmnl-devel libnetfilter_conntrack-devel libnfnetlink-devel libnftnl-devel BuildRequires: autogen autoconf automake libtool @@ -317,6 +326,12 @@ fi %{_mandir}/man8/xtables-legacy* %changelog +* Thu Mar 09 2023 zhanghao - 1.8.5-5 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: add some patches + * Tue Sep 06 2022 huangyu - 1.8.5-4 - Type: bugfix - ID: NA -- Gitee