netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update
@ 2017-04-17 13:18 Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 1/4] netfilter: ctnetlink: drop the incorrect cthelper module request Liping Zhang
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Liping Zhang @ 2017-04-17 13:18 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, Liping Zhang

From: Liping Zhang <zlpnobody@gmail.com>

This patch set aims to fix some bugs related to ctnetlink_change_conntrack.

First, we may invoke request_module with rcu_read_lock held, this is wrong,
as the request_module invocation may sleep. Fixed by PATCH #1.

Second, the unnecessary nf_conntrack_expect_lock will cause dead lock, which
was introduced by commit ca7433df3a67 ("netfilter: conntrack: seperate expect
locking from nf_conntrack_lock"). This is fixed by PATCH #2.

Third, Pablo pointed out that packets may be updating a conntrack at the
same time that we're mangling via ctnetlink, it's better to fix the
possible race together. So I audited the related source codes as follows:
1. CTA_HELP: for the userspace cthelper, no problem; for the inkernel
             cthelper, there's only one user: nf_ct_ftp_from_nlattr,
             but it only sets two flags, so no problem too.
2. CTA_TIMEOUT: only modify the ct->timeout, so no problem
3. CTA_STATUS: possible race will happen, fixed by PATCH #3
4. CTA_PROTOINFO: protected by ct->lock, no problem
5. CTA_MARK: only modify the ct->mark, no problem
6. CTA_SEQ_ADJ_X: should be protectd by ct->lock, fixed by PATCH #4
7. CTA_LABELS: use cmpxchg to update labels, so no problem

Liping Zhang (4):
  netfilter: ctnetlink: drop the incorrect cthelper module request
  netfilter: ctnetlink: fix deadlock due to acquire _expect_lock twice
  netfilter: ctnetlink: make it safer when updating ct->status
  netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj

 include/uapi/linux/netfilter/nf_conntrack_common.h | 13 +++-
 net/netfilter/nf_conntrack_netlink.c               | 89 ++++++++++++----------
 2 files changed, 58 insertions(+), 44 deletions(-)

-- 
2.5.5



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

* [PATCH nf 1/4] netfilter: ctnetlink: drop the incorrect cthelper module request
  2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
@ 2017-04-17 13:18 ` Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 2/4] netfilter: ctnetlink: fix deadlock due to acquire _expect_lock twice Liping Zhang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Liping Zhang @ 2017-04-17 13:18 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, Liping Zhang

From: Liping Zhang <zlpnobody@gmail.com>

First, when creating a new ct, we will invoke request_module to try to
load the related inkernel cthelper. So there's no need to call the
request_module again when updating the ct helpinfo.

Second, ctnetlink_change_helper may be called with rcu_read_lock held,
i.e. rcu_read_lock -> nfqnl_recv_verdict -> nfqnl_ct_parse ->
ctnetlink_glue_parse -> ctnetlink_glue_parse_ct ->
ctnetlink_change_helper. But the request_module invocation may sleep,
so we can't call it with the rcu_read_lock held.

Remove it now.

Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
---
 net/netfilter/nf_conntrack_netlink.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index dc7dfd6..48c1845 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1512,23 +1512,8 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 
 	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
 					    nf_ct_protonum(ct));
-	if (helper == NULL) {
-#ifdef CONFIG_MODULES
-		spin_unlock_bh(&nf_conntrack_expect_lock);
-
-		if (request_module("nfct-helper-%s", helpname) < 0) {
-			spin_lock_bh(&nf_conntrack_expect_lock);
-			return -EOPNOTSUPP;
-		}
-
-		spin_lock_bh(&nf_conntrack_expect_lock);
-		helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
-						    nf_ct_protonum(ct));
-		if (helper)
-			return -EAGAIN;
-#endif
+	if (helper == NULL)
 		return -EOPNOTSUPP;
-	}
 
 	if (help) {
 		if (help->helper == helper) {
-- 
2.5.5



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

* [PATCH nf 2/4] netfilter: ctnetlink: fix deadlock due to acquire _expect_lock twice
  2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 1/4] netfilter: ctnetlink: drop the incorrect cthelper module request Liping Zhang
@ 2017-04-17 13:18 ` Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 3/4] netfilter: ctnetlink: make it safer when updating ct->status Liping Zhang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Liping Zhang @ 2017-04-17 13:18 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, Liping Zhang

From: Liping Zhang <zlpnobody@gmail.com>

Currently, ctnetlink_change_conntrack is always protected by _expect_lock,
but this will cause a deadlock when deleting the helper from a conntrack,
as the _expect_lock will be acquired again by nf_ct_remove_expectations:

         CPU0
        ----
  lock(nf_conntrack_expect_lock);
  lock(nf_conntrack_expect_lock);

  *** DEADLOCK ***
  May be due to missing lock nesting notation

  2 locks held by lt-conntrack_gr/12853:
  #0:  (&table[i].mutex){+.+.+.}, at: [<ffffffffa05e2009>]
       nfnetlink_rcv_msg+0x399/0x6a9 [nfnetlink]
  #1:  (nf_conntrack_expect_lock){+.....}, at: [<ffffffffa05f2c1f>]
       ctnetlink_new_conntrack+0x17f/0x408 [nf_conntrack_netlink]

  Call Trace:
   dump_stack+0x85/0xc2
   __lock_acquire+0x1608/0x1680
   ? ctnetlink_parse_tuple_proto+0x10f/0x1c0 [nf_conntrack_netlink]
   lock_acquire+0x100/0x1f0
   ? nf_ct_remove_expectations+0x32/0x90 [nf_conntrack]
   _raw_spin_lock_bh+0x3f/0x50
   ? nf_ct_remove_expectations+0x32/0x90 [nf_conntrack]
   nf_ct_remove_expectations+0x32/0x90 [nf_conntrack]
   ctnetlink_change_helper+0xc6/0x190 [nf_conntrack_netlink]
   ctnetlink_new_conntrack+0x1b2/0x408 [nf_conntrack_netlink]
   nfnetlink_rcv_msg+0x60a/0x6a9 [nfnetlink]
   ? nfnetlink_rcv_msg+0x1b9/0x6a9 [nfnetlink]
   ? nfnetlink_bind+0x1a0/0x1a0 [nfnetlink]
   netlink_rcv_skb+0xa4/0xc0
   nfnetlink_rcv+0x87/0x770 [nfnetlink]

Since the operations are unrelated to nf_ct_expect, so we can drop the
_expect_lock. Also note, after removing the _expect_lock protection,
another CPU may invoke nf_conntrack_helper_unregister, so we should
use rcu_read_lock to protect __nf_conntrack_helper_find invoked by
ctnetlink_change_helper.

Fixes: ca7433df3a67 ("netfilter: conntrack: seperate expect locking from nf_conntrack_lock")
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
---
 net/netfilter/nf_conntrack_netlink.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 48c1845..e5f9777 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1510,23 +1510,29 @@ static int ctnetlink_change_helper(struct nf_conn *ct,
 		return 0;
 	}
 
+	rcu_read_lock();
 	helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
 					    nf_ct_protonum(ct));
-	if (helper == NULL)
+	if (helper == NULL) {
+		rcu_read_unlock();
 		return -EOPNOTSUPP;
+	}
 
 	if (help) {
 		if (help->helper == helper) {
 			/* update private helper data if allowed. */
 			if (helper->from_nlattr)
 				helper->from_nlattr(helpinfo, ct);
-			return 0;
+			err = 0;
 		} else
-			return -EBUSY;
+			err = -EBUSY;
+	} else {
+		/* we cannot set a helper for an existing conntrack */
+		err = -EOPNOTSUPP;
 	}
 
-	/* we cannot set a helper for an existing conntrack */
-	return -EOPNOTSUPP;
+	rcu_read_unlock();
+	return err;
 }
 
 static int ctnetlink_change_timeout(struct nf_conn *ct,
@@ -1945,9 +1951,7 @@ static int ctnetlink_new_conntrack(struct net *net, struct sock *ctnl,
 	err = -EEXIST;
 	ct = nf_ct_tuplehash_to_ctrack(h);
 	if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {
-		spin_lock_bh(&nf_conntrack_expect_lock);
 		err = ctnetlink_change_conntrack(ct, cda);
-		spin_unlock_bh(&nf_conntrack_expect_lock);
 		if (err == 0) {
 			nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
 						      (1 << IPCT_ASSURED) |
@@ -2342,11 +2346,7 @@ ctnetlink_glue_parse(const struct nlattr *attr, struct nf_conn *ct)
 	if (ret < 0)
 		return ret;
 
-	spin_lock_bh(&nf_conntrack_expect_lock);
-	ret = ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct);
-	spin_unlock_bh(&nf_conntrack_expect_lock);
-
-	return ret;
+	return ctnetlink_glue_parse_ct((const struct nlattr **)cda, ct);
 }
 
 static int ctnetlink_glue_exp_parse(const struct nlattr * const *cda,
-- 
2.5.5



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

* [PATCH nf 3/4] netfilter: ctnetlink: make it safer when updating ct->status
  2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 1/4] netfilter: ctnetlink: drop the incorrect cthelper module request Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 2/4] netfilter: ctnetlink: fix deadlock due to acquire _expect_lock twice Liping Zhang
@ 2017-04-17 13:18 ` Liping Zhang
  2017-04-17 13:18 ` [PATCH nf 4/4] netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj Liping Zhang
  2017-04-25  9:07 ` [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Pablo Neira Ayuso
  4 siblings, 0 replies; 6+ messages in thread
From: Liping Zhang @ 2017-04-17 13:18 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, Liping Zhang

From: Liping Zhang <zlpnobody@gmail.com>

After converting to use rcu for conntrack hash, one CPU may update
the ct->status via ctnetlink, while another CPU may process the
packets and update the ct->status.

So the non-atomic operation "ct->status |= status;" via ctnetlink
becomes unsafe, and this may clear the IPS_DYING_BIT bit set by
another CPU unexpectedly. For example:
         CPU0                            CPU1
  ctnetlink_change_status        __nf_conntrack_find_get
      old = ct->status              nf_ct_gc_expired
          -                         nf_ct_kill
          -                      test_and_set_bit(IPS_DYING_BIT
      new = old | status;                 -
  ct->status = new; <-- oops, _DYING_ is cleared!

Now using a series of atomic bit operation to solve the above issue.

Also note, user shouldn't set IPS_TEMPLATE, IPS_SEQ_ADJUST directly,
so make these two bits be unchangable too.

If we set the IPS_TEMPLATE_BIT, ct will be freed by nf_ct_tmpl_free,
but actually it is alloced by nf_conntrack_alloc.
If we set the IPS_SEQ_ADJUST_BIT, this may cause the NULL pointer
deference, as the nfct_seqadj(ct) maybe NULL.

Last, add some comments to describe the logic change due to the
commit a963d710f367 ("netfilter: ctnetlink: Fix regression in CTA_STATUS
processing"), which makes me feel a little confusing.

Fixes: 76507f69c44e ("[NETFILTER]: nf_conntrack: use RCU for conntrack hash")
Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
---
 include/uapi/linux/netfilter/nf_conntrack_common.h | 13 ++++++---
 net/netfilter/nf_conntrack_netlink.c               | 33 ++++++++++++++++------
 2 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6a8e33d..38fc383 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,10 +82,6 @@ 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),
@@ -101,6 +97,15 @@ enum ip_conntrack_status {
 	/* Conntrack got a helper explicitly attached via CT target. */
 	IPS_HELPER_BIT = 13,
 	IPS_HELPER = (1 << IPS_HELPER_BIT),
+
+	/* Be careful here, modifying these bits can make things messy,
+	 * so don't let users modify them directly.
+	 */
+	IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
+				 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
+				 IPS_SEQ_ADJUST | IPS_TEMPLATE),
+
+	__IPS_MAX_BIT = 14,
 };
 
 /* Connection tracking event types */
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index e5f9777..86deed6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1419,6 +1419,24 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
 }
 #endif
 
+static void
+__ctnetlink_change_status(struct nf_conn *ct, unsigned long on,
+			  unsigned long off)
+{
+	unsigned int bit;
+
+	/* Ignore these unchangable bits */
+	on &= ~IPS_UNCHANGEABLE_MASK;
+	off &= ~IPS_UNCHANGEABLE_MASK;
+
+	for (bit = 0; bit < __IPS_MAX_BIT; bit++) {
+		if (on & (1 << bit))
+			set_bit(bit, &ct->status);
+		else if (off & (1 << bit))
+			clear_bit(bit, &ct->status);
+	}
+}
+
 static int
 ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
 {
@@ -1438,10 +1456,7 @@ ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[])
 		/* ASSURED bit can only be set */
 		return -EBUSY;
 
-	/* Be careful here, modifying NAT bits can screw up things,
-	 * so don't let users modify them directly if they don't pass
-	 * nf_nat_range. */
-	ct->status |= status & ~(IPS_NAT_DONE_MASK | IPS_NAT_MASK);
+	__ctnetlink_change_status(ct, status, 0);
 	return 0;
 }
 
@@ -1628,7 +1643,7 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
 		if (ret < 0)
 			return ret;
 
-		ct->status |= IPS_SEQ_ADJUST;
+		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 	}
 
 	if (cda[CTA_SEQ_ADJ_REPLY]) {
@@ -1637,7 +1652,7 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
 		if (ret < 0)
 			return ret;
 
-		ct->status |= IPS_SEQ_ADJUST;
+		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 	}
 
 	return 0;
@@ -2289,10 +2304,10 @@ ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
 	/* 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.
+	 * unchangeable bits but do not error out. Also user programs
+	 * are allowed to clear the bits that they are allowed to change.
 	 */
-	ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
-		     (ct->status & IPS_UNCHANGEABLE_MASK);
+	__ctnetlink_change_status(ct, status, ~status);
 	return 0;
 }
 
-- 
2.5.5



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

* [PATCH nf 4/4] netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj
  2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
                   ` (2 preceding siblings ...)
  2017-04-17 13:18 ` [PATCH nf 3/4] netfilter: ctnetlink: make it safer when updating ct->status Liping Zhang
@ 2017-04-17 13:18 ` Liping Zhang
  2017-04-25  9:07 ` [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Pablo Neira Ayuso
  4 siblings, 0 replies; 6+ messages in thread
From: Liping Zhang @ 2017-04-17 13:18 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel, Liping Zhang

From: Liping Zhang <zlpnobody@gmail.com>

We should acquire the ct->lock before accessing or modifying the
nf_ct_seqadj, as another CPU may modify the nf_ct_seqadj at the same
time during its packet proccessing.

Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
---
 net/netfilter/nf_conntrack_netlink.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 86deed6..78f8c9a 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -417,8 +417,7 @@ dump_ct_seq_adj(struct sk_buff *skb, const struct nf_ct_seqadj *seq, int type)
 	return -1;
 }
 
-static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb,
-				     const struct nf_conn *ct)
+static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, struct nf_conn *ct)
 {
 	struct nf_conn_seqadj *seqadj = nfct_seqadj(ct);
 	struct nf_ct_seqadj *seq;
@@ -426,15 +425,20 @@ static int ctnetlink_dump_ct_seq_adj(struct sk_buff *skb,
 	if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj)
 		return 0;
 
+	spin_lock_bh(&ct->lock);
 	seq = &seqadj->seq[IP_CT_DIR_ORIGINAL];
 	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1)
-		return -1;
+		goto err;
 
 	seq = &seqadj->seq[IP_CT_DIR_REPLY];
 	if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1)
-		return -1;
+		goto err;
 
+	spin_unlock_bh(&ct->lock);
 	return 0;
+err:
+	spin_unlock_bh(&ct->lock);
+	return -1;
 }
 
 static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
@@ -1637,11 +1641,12 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
 	if (!seqadj)
 		return 0;
 
+	spin_lock_bh(&ct->lock);
 	if (cda[CTA_SEQ_ADJ_ORIG]) {
 		ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL],
 				     cda[CTA_SEQ_ADJ_ORIG]);
 		if (ret < 0)
-			return ret;
+			goto err;
 
 		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 	}
@@ -1650,12 +1655,16 @@ ctnetlink_change_seq_adj(struct nf_conn *ct,
 		ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY],
 				     cda[CTA_SEQ_ADJ_REPLY]);
 		if (ret < 0)
-			return ret;
+			goto err;
 
 		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
 	}
 
+	spin_unlock_bh(&ct->lock);
 	return 0;
+err:
+	spin_unlock_bh(&ct->lock);
+	return ret;
 }
 
 static int
-- 
2.5.5



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

* Re: [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update
  2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
                   ` (3 preceding siblings ...)
  2017-04-17 13:18 ` [PATCH nf 4/4] netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj Liping Zhang
@ 2017-04-25  9:07 ` Pablo Neira Ayuso
  4 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira Ayuso @ 2017-04-25  9:07 UTC (permalink / raw)
  To: Liping Zhang; +Cc: netfilter-devel, Liping Zhang

On Mon, Apr 17, 2017 at 09:18:54PM +0800, Liping Zhang wrote:
> From: Liping Zhang <zlpnobody@gmail.com>
> 
> This patch set aims to fix some bugs related to ctnetlink_change_conntrack.
> 
> First, we may invoke request_module with rcu_read_lock held, this is wrong,
> as the request_module invocation may sleep. Fixed by PATCH #1.
> 
> Second, the unnecessary nf_conntrack_expect_lock will cause dead lock, which
> was introduced by commit ca7433df3a67 ("netfilter: conntrack: seperate expect
> locking from nf_conntrack_lock"). This is fixed by PATCH #2.
> 
> Third, Pablo pointed out that packets may be updating a conntrack at the
> same time that we're mangling via ctnetlink, it's better to fix the
> possible race together. So I audited the related source codes as follows:
> 1. CTA_HELP: for the userspace cthelper, no problem; for the inkernel
>              cthelper, there's only one user: nf_ct_ftp_from_nlattr,
>              but it only sets two flags, so no problem too.
> 2. CTA_TIMEOUT: only modify the ct->timeout, so no problem
> 3. CTA_STATUS: possible race will happen, fixed by PATCH #3
> 4. CTA_PROTOINFO: protected by ct->lock, no problem
> 5. CTA_MARK: only modify the ct->mark, no problem
> 6. CTA_SEQ_ADJ_X: should be protectd by ct->lock, fixed by PATCH #4
> 7. CTA_LABELS: use cmpxchg to update labels, so no problem

Series applied, thanks.

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

end of thread, other threads:[~2017-04-25  9:07 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-17 13:18 [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update Liping Zhang
2017-04-17 13:18 ` [PATCH nf 1/4] netfilter: ctnetlink: drop the incorrect cthelper module request Liping Zhang
2017-04-17 13:18 ` [PATCH nf 2/4] netfilter: ctnetlink: fix deadlock due to acquire _expect_lock twice Liping Zhang
2017-04-17 13:18 ` [PATCH nf 3/4] netfilter: ctnetlink: make it safer when updating ct->status Liping Zhang
2017-04-17 13:18 ` [PATCH nf 4/4] netfilter: ctnetlink: acquire ct->lock before operating nf_ct_seqadj Liping Zhang
2017-04-25  9:07 ` [PATCH nf 0/4] netfilter: ctnetlink: fix some bugs related to ct update 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).