iptables:fix iptables docker daemon error
This commit is contained in:
parent
8e4b92e1d6
commit
f3988dd0a1
@ -0,0 +1,90 @@
|
||||
From 17534cb18ed0a5052dc45c117401251359dba6aa Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
@ -0,0 +1,126 @@
|
||||
From b3ac87038f4e45141831d9ab485a2f627daba3f1 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
From b5f1a3beac1d1f2b96c8be8ebec450f5ea758090 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
From 2dbb49d15fb44ddd521a734eca3be3f940b7c1ba Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
@ -0,0 +1,241 @@
|
||||
|
||||
From a1eaaceb0460b338294e40bdd5bc5186320a478c Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
From 8468fd4f7c85c21ab375402bc80d0188412b6cbf Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
---
|
||||
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
|
||||
|
||||
130
backport-xshared-Fix-response-to-unprivileged-users.patch
Normal file
130
backport-xshared-Fix-response-to-unprivileged-users.patch
Normal file
@ -0,0 +1,130 @@
|
||||
From 26ecdf53960658771c0fc582f72a4025e2887f75 Mon Sep 17 00:00:00 2001
|
||||
From: Phil Sutter <phil@nwl.cc>
|
||||
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 <phil@nwl.cc>
|
||||
Reviewed-by: Florian Westphal <fw@strlen.de>
|
||||
---
|
||||
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
|
||||
|
||||
@ -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 <zhanghao383@huawei.com> - 1.8.5-5
|
||||
- Type: bugfix
|
||||
- ID: NA
|
||||
- SUG: NA
|
||||
- DESC: add some patches
|
||||
|
||||
* Tue Sep 06 2022 huangyu <huangyu106@huawei.com> - 1.8.5-4
|
||||
- Type: bugfix
|
||||
- ID: NA
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user