linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing
@ 2017-01-26 22:49 Kevin Cernekee
  2017-01-26 22:49 ` [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing Kevin Cernekee
  2017-02-06 11:44 ` [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Pablo Neira Ayuso
  0 siblings, 2 replies; 4+ messages in thread
From: Kevin Cernekee @ 2017-01-26 22:49 UTC (permalink / raw)
  To: pablo; +Cc: dianders, davem, netfilter-devel, linux-kernel

The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
when building a CTA_STATUS attribute.  If this toggles the bit from
0->1, the parser will return an error.  On Linux 4.4+ this will cause any
NFQA_EXP attribute in the packet to be ignored.  This breaks conntrackd's
userland helpers because they operate on unconfirmed connections.

Instead of returning -EBUSY if the user program asks to modify an
unchangeable bit, simply ignore the change.

Also, fix the logic so that user programs are allowed to clear
the bits that they are allowed to change.

Signed-off-by: Kevin Cernekee <cernekee@chromium.org>
---


V1->V2:

 - Create a new ctnetlink_update_status() function, per code review feedback
 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next

(Note that the original patch 1/3, which fixed a related problem on
CTA_TIMEOUT, is only needed on old kernels like 4.4.)


 include/uapi/linux/netfilter/nf_conntrack_common.h |  4 ++++
 net/netfilter/nf_conntrack_netlink.c               | 27 +++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6d074d1..6a8e33d 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
 	IPS_DYING_BIT = 9,
 	IPS_DYING = (1 << IPS_DYING_BIT),
 
+	/* Bits that cannot be altered from userland. */
+	IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+				 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
+
 	/* Connection has fixed timeout. */
 	IPS_FIXED_TIMEOUT_BIT = 10,
 	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 2754045..e8f704a6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1446,6 +1446,31 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
 }
 
 static int
+ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
+{
+	unsigned long d;
+	unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
+	d = ct->status ^ status;
+
+	if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
+		/* SEEN_REPLY bit can only be set */
+		return -EBUSY;
+
+	if (d & IPS_ASSURED && !(status & IPS_ASSURED))
+		/* ASSURED bit can only be set */
+		return -EBUSY;
+
+	/* This check is less strict than ctnetlink_change_status()
+	 * because callers often flip IPS_EXPECTED bits when sending
+	 * an NFQA_CT attribute to the kernel.  So ignore the
+	 * unchangeable bits but do not error out.
+	 */
+	ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
+		     (ct->status & IPS_UNCHANGEABLE_MASK);
+	return 0;
+}
+
+static int
 ctnetlink_setup_nat(struct nf_conn *ct, const struct nlattr * const cda[])
 {
 #ifdef CONFIG_NF_NAT_NEEDED
@@ -2280,7 +2305,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
 			return err;
 	}
 	if (cda[CTA_STATUS]) {
-		err = ctnetlink_change_status(ct, cda);
+		err = ctnetlink_update_status(ct, cda);
 		if (err < 0)
 			return err;
 	}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing
  2017-01-26 22:49 [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Kevin Cernekee
@ 2017-01-26 22:49 ` Kevin Cernekee
  2017-02-06 11:44   ` Pablo Neira Ayuso
  2017-02-06 11:44 ` [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Pablo Neira Ayuso
  1 sibling, 1 reply; 4+ messages in thread
From: Kevin Cernekee @ 2017-01-26 22:49 UTC (permalink / raw)
  To: pablo; +Cc: dianders, davem, netfilter-devel, linux-kernel

Prior to Linux 4.4, it was usually harmless to send a CTA_HELP attribute
containing the name of the current helper.  That is no longer the case:
as of Linux 4.4, if ctnetlink_change_helper() returns an error from
the ct->master check, processing of the request will fail, skipping the
NFQA_EXP attribute (if present).

This patch changes the behavior to improve compatibility with user
programs that expect the kernel interface to work the way it did prior
to Linux 4.4.  If a user program specifies CTA_HELP but the argument
matches the current conntrack helper name, ignore it instead of generating
an error.

Signed-off-by: Kevin Cernekee <cernekee@chromium.org>
---


V1->V2:

 - Add comment and update changelog, per code review feedback
 - Rebase + retest on net-next


 net/netfilter/nf_conntrack_netlink.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index e8f704a6..891f02a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1503,14 +1503,23 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 	struct nlattr *helpinfo = NULL;
 	int err;
 
-	/* don't change helper of sibling connections */
-	if (ct->master)
-		return -EBUSY;
-
 	err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
 	if (err < 0)
 		return err;
 
+	/* don't change helper of sibling connections */
+	if (ct->master) {
+		/* If we try to change the helper to the same thing twice,
+		 * treat the second attempt as a no-op instead of returning
+		 * an error.
+		 */
+		if (help && help->helper &&
+		    !strcmp(help->helper->name, helpname))
+			return 0;
+		else
+			return -EBUSY;
+	}
+
 	if (!strcmp(helpname, "")) {
 		if (help && help->helper) {
 			/* we had a helper before ... */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing
  2017-01-26 22:49 [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Kevin Cernekee
  2017-01-26 22:49 ` [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing Kevin Cernekee
@ 2017-02-06 11:44 ` Pablo Neira Ayuso
  1 sibling, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2017-02-06 11:44 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: dianders, davem, netfilter-devel, linux-kernel

On Thu, Jan 26, 2017 at 02:49:43PM -0800, Kevin Cernekee wrote:
> The libnetfilter_conntrack userland library always sets IPS_CONFIRMED
> when building a CTA_STATUS attribute.  If this toggles the bit from
> 0->1, the parser will return an error.  On Linux 4.4+ this will cause any
> NFQA_EXP attribute in the packet to be ignored.  This breaks conntrackd's
> userland helpers because they operate on unconfirmed connections.
> 
> Instead of returning -EBUSY if the user program asks to modify an
> unchangeable bit, simply ignore the change.
> 
> Also, fix the logic so that user programs are allowed to clear
> the bits that they are allowed to change.

Applied, thanks Kevin.

I have manually fixed here this compilation warning, btw:

net/netfilter/nf_conntrack_netlink.c:1449:1: warning:
‘ctnetlink_update_status’ defined but not used [-Wunused-function] ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
 ^

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing
  2017-01-26 22:49 ` [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing Kevin Cernekee
@ 2017-02-06 11:44   ` Pablo Neira Ayuso
  0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2017-02-06 11:44 UTC (permalink / raw)
  To: Kevin Cernekee; +Cc: dianders, davem, netfilter-devel, linux-kernel

On Thu, Jan 26, 2017 at 02:49:44PM -0800, Kevin Cernekee wrote:
> Prior to Linux 4.4, it was usually harmless to send a CTA_HELP attribute
> containing the name of the current helper.  That is no longer the case:
> as of Linux 4.4, if ctnetlink_change_helper() returns an error from
> the ct->master check, processing of the request will fail, skipping the
> NFQA_EXP attribute (if present).
> 
> This patch changes the behavior to improve compatibility with user
> programs that expect the kernel interface to work the way it did prior
> to Linux 4.4.  If a user program specifies CTA_HELP but the argument
> matches the current conntrack helper name, ignore it instead of generating
> an error.

Also applied, thanks Kevin.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2017-02-06 11:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-26 22:49 [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Kevin Cernekee
2017-01-26 22:49 ` [PATCH V2 2/2] netfilter: ctnetlink: Fix regression in CTA_HELP processing Kevin Cernekee
2017-02-06 11:44   ` Pablo Neira Ayuso
2017-02-06 11:44 ` [PATCH V2 1/2] netfilter: ctnetlink: Fix regression in CTA_STATUS processing Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).