netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
@ 2017-06-09  8:13 Hangbin Liu
  2017-06-09  8:23 ` Hangbin Liu
  2017-06-09 13:09 ` [PATCHv2 " Hangbin Liu
  0 siblings, 2 replies; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09  8:13 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Xin Long, Steffen Klassert, Hangbin Liu

Now we will force to do garbage collection if any policy removed in
xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
-> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
dereference when check percpu_empty. The code path looks like:

flow_cache_fini()
  - fc->percpu = NULL
xfrm_policy_fini()
  - xfrm_policy_flush()
    - xfrm_garbage_collect()
      - flow_cache_flush()
        - flow_cache_percpu_empty()
	  - fcp = per_cpu_ptr(fc->percpu, cpu)

To reproduce, just add ipsec in netns and then remove the netns.

Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 net/core/flow.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/net/core/flow.c b/net/core/flow.c
index f7f5d19..321fc53 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -332,10 +332,13 @@ static int flow_cache_percpu_empty(struct flow_cache *fc, int cpu)
 	struct flow_cache_percpu *fcp;
 	unsigned int i;
 
-	fcp = per_cpu_ptr(fc->percpu, cpu);
-	for (i = 0; i < flow_cache_hash_size(fc); i++)
-		if (!hlist_empty(&fcp->hash_table[i]))
-			return 0;
+	if (fc->percpu) {
+		fcp = per_cpu_ptr(fc->percpu, cpu);
+		for (i = 0; i < flow_cache_hash_size(fc); i++)
+			if (!hlist_empty(&fcp->hash_table[i]))
+				return 0;
+	}
+
 	return 1;
 }
 
-- 
2.5.5

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  8:13 [PATCH net] net/flow: fix fc->percpu NULL pointer dereference Hangbin Liu
@ 2017-06-09  8:23 ` Hangbin Liu
  2017-06-09  8:32   ` Steffen Klassert
  2017-06-09 13:09 ` [PATCHv2 " Hangbin Liu
  1 sibling, 1 reply; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09  8:23 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: David Miller, Xin Long, Hangbin Liu, network dev

Hi Steffen,

BTW, If we put the check in xfrm_policy_flush(), we can prevent it earlier.
But If we put the check in flow_cache_percpu_empty(), we can prevent
other functions set fc->percpu to NULL, although not much possible : )

So I'm not quite sure whether we should put the check in
flow_cache_percpu_empty() or in xfrm_policy_flush().

Do you have any suggestion?

Thanks
Hangbin

2017-06-09 16:13 GMT+08:00 Hangbin Liu <liuhangbin@gmail.com>:
> Now we will force to do garbage collection if any policy removed in
> xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
> first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
> -> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
> dereference when check percpu_empty. The code path looks like:
>
> flow_cache_fini()
>   - fc->percpu = NULL
> xfrm_policy_fini()
>   - xfrm_policy_flush()
>     - xfrm_garbage_collect()
>       - flow_cache_flush()
>         - flow_cache_percpu_empty()
>           - fcp = per_cpu_ptr(fc->percpu, cpu)
>
> To reproduce, just add ipsec in netns and then remove the netns.
>
> Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  net/core/flow.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/net/core/flow.c b/net/core/flow.c
> index f7f5d19..321fc53 100644
> --- a/net/core/flow.c
> +++ b/net/core/flow.c
> @@ -332,10 +332,13 @@ static int flow_cache_percpu_empty(struct flow_cache *fc, int cpu)
>         struct flow_cache_percpu *fcp;
>         unsigned int i;
>
> -       fcp = per_cpu_ptr(fc->percpu, cpu);
> -       for (i = 0; i < flow_cache_hash_size(fc); i++)
> -               if (!hlist_empty(&fcp->hash_table[i]))
> -                       return 0;
> +       if (fc->percpu) {
> +               fcp = per_cpu_ptr(fc->percpu, cpu);
> +               for (i = 0; i < flow_cache_hash_size(fc); i++)
> +                       if (!hlist_empty(&fcp->hash_table[i]))
> +                               return 0;
> +       }
> +
>         return 1;
>  }
>
> --
> 2.5.5
>

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  8:23 ` Hangbin Liu
@ 2017-06-09  8:32   ` Steffen Klassert
  2017-06-09  8:43     ` Xin Long
  0 siblings, 1 reply; 14+ messages in thread
From: Steffen Klassert @ 2017-06-09  8:32 UTC (permalink / raw)
  To: Hangbin Liu; +Cc: David Miller, Xin Long, network dev

On Fri, Jun 09, 2017 at 04:23:01PM +0800, Hangbin Liu wrote:
> Hi Steffen,
> 
> BTW, If we put the check in xfrm_policy_flush(), we can prevent it earlier.
> But If we put the check in flow_cache_percpu_empty(), we can prevent
> other functions set fc->percpu to NULL, although not much possible : )
> 
> So I'm not quite sure whether we should put the check in
> flow_cache_percpu_empty() or in xfrm_policy_flush().

Can't we just call xfrm_policy_fini() first and then flow_cache_fini()?

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  8:32   ` Steffen Klassert
@ 2017-06-09  8:43     ` Xin Long
  2017-06-09  9:06       ` Hangbin Liu
  0 siblings, 1 reply; 14+ messages in thread
From: Xin Long @ 2017-06-09  8:43 UTC (permalink / raw)
  To: Steffen Klassert; +Cc: Hangbin Liu, David Miller, network dev

On Fri, Jun 9, 2017 at 4:32 PM, Steffen Klassert
<steffen.klassert@secunet.com> wrote:
> On Fri, Jun 09, 2017 at 04:23:01PM +0800, Hangbin Liu wrote:
>> Hi Steffen,
>>
>> BTW, If we put the check in xfrm_policy_flush(), we can prevent it earlier.
>> But If we put the check in flow_cache_percpu_empty(), we can prevent
>> other functions set fc->percpu to NULL, although not much possible : )
>>
>> So I'm not quite sure whether we should put the check in
>> flow_cache_percpu_empty() or in xfrm_policy_flush().
>
> Can't we just call xfrm_policy_fini() first and then flow_cache_fini()?
>
That would be a better fix. seems safe as what flow_cache_fini does
is only to free fcp->hash_table and stop timer, I didn't see  it has
any dependence on xfrm_policy stuff.

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  8:43     ` Xin Long
@ 2017-06-09  9:06       ` Hangbin Liu
  2017-06-09  9:49         ` Xin Long
  0 siblings, 1 reply; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09  9:06 UTC (permalink / raw)
  To: Xin Long; +Cc: Steffen Klassert, David Miller, network dev

2017-06-09 16:43 GMT+08:00 Xin Long <lucien.xin@gmail.com>:
> On Fri, Jun 9, 2017 at 4:32 PM, Steffen Klassert
> <steffen.klassert@secunet.com> wrote:
>> On Fri, Jun 09, 2017 at 04:23:01PM +0800, Hangbin Liu wrote:
>>> Hi Steffen,
>>>
>>> BTW, If we put the check in xfrm_policy_flush(), we can prevent it earlier.
>>> But If we put the check in flow_cache_percpu_empty(), we can prevent
>>> other functions set fc->percpu to NULL, although not much possible : )
>>>
>>> So I'm not quite sure whether we should put the check in
>>> flow_cache_percpu_empty() or in xfrm_policy_flush().
>>
>> Can't we just call xfrm_policy_fini() first and then flow_cache_fini()?

Yes, that would be easy fix. I have been thinking about that.  But if we change
 the order in xfrm_net_exit(), do we also need to change the order in
 xfrm_net_init()? That would change a lot.

If no need, that would be good.

>>
> That would be a better fix. seems safe as what flow_cache_fini does
> is only to free fcp->hash_table and stop timer, I didn't see  it has
> any dependence on xfrm_policy stuff.

I'm not familiar about this part. So not sure about the influence if we free
the flow cache after xfrm_policy_fini(). I need do some test first.

I would also be appreciate if you or some one could make sure if it doesn't
influence anything.

Thanks
Hangbin

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  9:06       ` Hangbin Liu
@ 2017-06-09  9:49         ` Xin Long
  2017-06-09 12:29           ` Hangbin Liu
  0 siblings, 1 reply; 14+ messages in thread
From: Xin Long @ 2017-06-09  9:49 UTC (permalink / raw)
  To: Hangbin Liu; +Cc: Steffen Klassert, David Miller, network dev

On Fri, Jun 9, 2017 at 5:06 PM, Hangbin Liu <liuhangbin@gmail.com> wrote:
> 2017-06-09 16:43 GMT+08:00 Xin Long <lucien.xin@gmail.com>:
>> On Fri, Jun 9, 2017 at 4:32 PM, Steffen Klassert
>> <steffen.klassert@secunet.com> wrote:
>>> On Fri, Jun 09, 2017 at 04:23:01PM +0800, Hangbin Liu wrote:
>>>> Hi Steffen,
>>>>
>>>> BTW, If we put the check in xfrm_policy_flush(), we can prevent it earlier.
>>>> But If we put the check in flow_cache_percpu_empty(), we can prevent
>>>> other functions set fc->percpu to NULL, although not much possible : )
>>>>
>>>> So I'm not quite sure whether we should put the check in
>>>> flow_cache_percpu_empty() or in xfrm_policy_flush().
>>>
>>> Can't we just call xfrm_policy_fini() first and then flow_cache_fini()?
>
> Yes, that would be easy fix. I have been thinking about that.  But if we change
>  the order in xfrm_net_exit(), do we also need to change the order in
>  xfrm_net_init()? That would change a lot.
>
> If no need, that would be good.
>
>>>
>> That would be a better fix. seems safe as what flow_cache_fini does
>> is only to free fcp->hash_table and stop timer, I didn't see  it has
>> any dependence on xfrm_policy stuff.
>
> I'm not familiar about this part. So not sure about the influence if we free
> the flow cache after xfrm_policy_fini(). I need do some test first.
>
> I would also be appreciate if you or some one could make sure if it doesn't
> influence anything.
>
another fix is to move xfrm_garbage_collect out of xfrm_policy_flush.
I could only see two places need to call it.
something like:

--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk,
struct sk_buff *skb, const struct sad
        int err, err2;

        err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
+       if (!err)
+               xfrm_garbage_collect(net);
        err2 = unicast_flush_resp(sk, hdr);
        if (err || err2) {
                if (err == -ESRCH) /* empty table - old silent behavior */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ed4e52d..89343a3 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1007,9 +1007,6 @@ int xfrm_policy_flush(struct net *net, u8 type,
bool task_valid)
 out:
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);

-       if (cnt)
-               xfrm_garbage_collect(net);
-
        return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38614df..86116e9 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff
*skb, struct nlmsghdr *nlh,
                        return 0;
                return err;
        }
+       xfrm_garbage_collect(net);

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  9:49         ` Xin Long
@ 2017-06-09 12:29           ` Hangbin Liu
  2017-06-09 12:43             ` Hangbin Liu
  0 siblings, 1 reply; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09 12:29 UTC (permalink / raw)
  To: Xin Long; +Cc: Steffen Klassert, David Miller, network dev

On Fri, Jun 09, 2017 at 05:49:50PM +0800, Xin Long wrote:
> another fix is to move xfrm_garbage_collect out of xfrm_policy_flush.
> I could only see two places need to call it.
> something like:
> 
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk,
> struct sk_buff *skb, const struct sad
>         int err, err2;
> 
>         err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
> +       if (!err)
> +               xfrm_garbage_collect(net);
>         err2 = unicast_flush_resp(sk, hdr);
>         if (err || err2) {
>                 if (err == -ESRCH) /* empty table - old silent behavior */

Hmm, that would be better, just the xfrm_garbage_collect() need to be after
err || err2 check

+          xfrm_garbage_collect(net);

I will send v2 patch.

Thanks
Hangbin

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

* Re: [PATCH net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09 12:29           ` Hangbin Liu
@ 2017-06-09 12:43             ` Hangbin Liu
  0 siblings, 0 replies; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09 12:43 UTC (permalink / raw)
  To: Xin Long; +Cc: Steffen Klassert, David Miller, network dev

2017-06-09 20:29 GMT+08:00 Hangbin Liu <liuhangbin@gmail.com>:
> On Fri, Jun 09, 2017 at 05:49:50PM +0800, Xin Long wrote:
>> another fix is to move xfrm_garbage_collect out of xfrm_policy_flush.
>> I could only see two places need to call it.
>> something like:
>>
>> --- a/net/key/af_key.c
>> +++ b/net/key/af_key.c
>> @@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk,
>> struct sk_buff *skb, const struct sad
>>         int err, err2;
>>
>>         err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
>> +       if (!err)
>> +               xfrm_garbage_collect(net);
>>         err2 = unicast_flush_resp(sk, hdr);
>>         if (err || err2) {
>>                 if (err == -ESRCH) /* empty table - old silent behavior */
>
> Hmm, that would be better, just the xfrm_garbage_collect() need to be after
> err || err2 check
>
> +          xfrm_garbage_collect(net);

Ah, my mistake.  we should check err first. Sorry.

>
> I will send v2 patch.
>
> Thanks
> Hangbin

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

* [PATCHv2 net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09  8:13 [PATCH net] net/flow: fix fc->percpu NULL pointer dereference Hangbin Liu
  2017-06-09  8:23 ` Hangbin Liu
@ 2017-06-09 13:09 ` Hangbin Liu
  2017-06-10  8:29   ` Xin Long
  2017-06-11  1:44   ` [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush Hangbin Liu
  1 sibling, 2 replies; 14+ messages in thread
From: Hangbin Liu @ 2017-06-09 13:09 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Xin Long, Steffen Klassert, Hangbin Liu

Now we will force to do garbage collection if any policy removed in
xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
-> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
dereference when check percpu_empty. The code path looks like:

flow_cache_fini()
  - fc->percpu = NULL
xfrm_policy_fini()
  - xfrm_policy_flush()
    - xfrm_garbage_collect()
      - flow_cache_flush()
        - flow_cache_percpu_empty()
	  - fcp = per_cpu_ptr(fc->percpu, cpu)

To reproduce, just add ipsec in netns and then remove the netns.

v2:
As Xin Long suggested, since only two other places need to call it. move
xfrm_garbage_collect() outside xfrm_policy_flush().

Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 net/key/af_key.c       | 2 ++
 net/xfrm/xfrm_policy.c | 4 ----
 net/xfrm/xfrm_user.c   | 1 +
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/net/key/af_key.c b/net/key/af_key.c
index 512dc43..5103f92 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
 	int err, err2;
 
 	err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
+	if (!err)
+		xfrm_garbage_collect(net);
 	err2 = unicast_flush_resp(sk, hdr);
 	if (err || err2) {
 		if (err == -ESRCH) /* empty table - old silent behavior */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ed4e52d..643a18f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
 		err = -ESRCH;
 out:
 	spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
-
-	if (cnt)
-		xfrm_garbage_collect(net);
-
 	return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38614df..86116e9 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 			return 0;
 		return err;
 	}
+	xfrm_garbage_collect(net);
 
 	c.data.type = type;
 	c.event = nlh->nlmsg_type;
-- 
2.5.5

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

* Re: [PATCHv2 net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-09 13:09 ` [PATCHv2 " Hangbin Liu
@ 2017-06-10  8:29   ` Xin Long
  2017-06-11  1:39     ` Hangbin Liu
  2017-06-11  1:44   ` [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush Hangbin Liu
  1 sibling, 1 reply; 14+ messages in thread
From: Xin Long @ 2017-06-10  8:29 UTC (permalink / raw)
  To: Hangbin Liu; +Cc: network dev, David Miller, Steffen Klassert

On Fri, Jun 9, 2017 at 9:09 PM, Hangbin Liu <liuhangbin@gmail.com> wrote:
> Now we will force to do garbage collection if any policy removed in
> xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
> first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
> -> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
> dereference when check percpu_empty. The code path looks like:
>
> flow_cache_fini()
>   - fc->percpu = NULL
> xfrm_policy_fini()
>   - xfrm_policy_flush()
>     - xfrm_garbage_collect()
>       - flow_cache_flush()
>         - flow_cache_percpu_empty()
>           - fcp = per_cpu_ptr(fc->percpu, cpu)
>
> To reproduce, just add ipsec in netns and then remove the netns.
>
> v2:
> As Xin Long suggested, since only two other places need to call it. move
> xfrm_garbage_collect() outside xfrm_policy_flush().
>
> Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  net/key/af_key.c       | 2 ++
>  net/xfrm/xfrm_policy.c | 4 ----
>  net/xfrm/xfrm_user.c   | 1 +
>  3 files changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index 512dc43..5103f92 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
>         int err, err2;
>
>         err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
> +       if (!err)
> +               xfrm_garbage_collect(net);
>         err2 = unicast_flush_resp(sk, hdr);
>         if (err || err2) {
>                 if (err == -ESRCH) /* empty table - old silent behavior */
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index ed4e52d..643a18f 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
>                 err = -ESRCH;
>  out:
>         spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
> -
> -       if (cnt)
> -               xfrm_garbage_collect(net);
> -
>         return err;
>  }
>  EXPORT_SYMBOL(xfrm_policy_flush);
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index 38614df..86116e9 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
>                         return 0;
>                 return err;
>         }
> +       xfrm_garbage_collect(net);
>
>         c.data.type = type;
>         c.event = nlh->nlmsg_type;
> --
> 2.5.5
>
 It's a xfrm fix, pls also fix the title, like:
   xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
or
   xfrm: fix ...

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

* Re: [PATCHv2 net] net/flow: fix fc->percpu NULL pointer dereference
  2017-06-10  8:29   ` Xin Long
@ 2017-06-11  1:39     ` Hangbin Liu
  0 siblings, 0 replies; 14+ messages in thread
From: Hangbin Liu @ 2017-06-11  1:39 UTC (permalink / raw)
  To: Xin Long; +Cc: network dev

On Sat, Jun 10, 2017 at 04:29:23PM +0800, Xin Long wrote:
>  It's a xfrm fix, pls also fix the title, like:
>    xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
> or
>    xfrm: fix ...
Opps, sorry forgot that.

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

* [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
  2017-06-09 13:09 ` [PATCHv2 " Hangbin Liu
  2017-06-10  8:29   ` Xin Long
@ 2017-06-11  1:44   ` Hangbin Liu
  2017-06-11 10:51     ` Xin Long
  2017-06-12 12:13     ` Steffen Klassert
  1 sibling, 2 replies; 14+ messages in thread
From: Hangbin Liu @ 2017-06-11  1:44 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Xin Long, Steffen Klassert, Hangbin Liu

Now we will force to do garbage collection if any policy removed in
xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
-> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
dereference when check percpu_empty. The code path looks like:

flow_cache_fini()
  - fc->percpu = NULL
xfrm_policy_fini()
  - xfrm_policy_flush()
    - xfrm_garbage_collect()
      - flow_cache_flush()
        - flow_cache_percpu_empty()
	  - fcp = per_cpu_ptr(fc->percpu, cpu)

To reproduce, just add ipsec in netns and then remove the netns.

v2:
As Xin Long suggested, since only two other places need to call it. move
xfrm_garbage_collect() outside xfrm_policy_flush().

v3:
Fix subject mismatch after v2 fix.

Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 net/key/af_key.c       | 2 ++
 net/xfrm/xfrm_policy.c | 4 ----
 net/xfrm/xfrm_user.c   | 1 +
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/net/key/af_key.c b/net/key/af_key.c
index 512dc43..5103f92 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
 	int err, err2;
 
 	err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
+	if (!err)
+		xfrm_garbage_collect(net);
 	err2 = unicast_flush_resp(sk, hdr);
 	if (err || err2) {
 		if (err == -ESRCH) /* empty table - old silent behavior */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ed4e52d..643a18f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
 		err = -ESRCH;
 out:
 	spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
-
-	if (cnt)
-		xfrm_garbage_collect(net);
-
 	return err;
 }
 EXPORT_SYMBOL(xfrm_policy_flush);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 38614df..86116e9 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 			return 0;
 		return err;
 	}
+	xfrm_garbage_collect(net);
 
 	c.data.type = type;
 	c.event = nlh->nlmsg_type;
-- 
2.5.5

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

* Re: [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
  2017-06-11  1:44   ` [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush Hangbin Liu
@ 2017-06-11 10:51     ` Xin Long
  2017-06-12 12:13     ` Steffen Klassert
  1 sibling, 0 replies; 14+ messages in thread
From: Xin Long @ 2017-06-11 10:51 UTC (permalink / raw)
  To: Hangbin Liu; +Cc: network dev, David Miller, Steffen Klassert

On Sun, Jun 11, 2017 at 9:44 AM, Hangbin Liu <liuhangbin@gmail.com> wrote:
> Now we will force to do garbage collection if any policy removed in
> xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
> first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
> -> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
> dereference when check percpu_empty. The code path looks like:
>
> flow_cache_fini()
>   - fc->percpu = NULL
> xfrm_policy_fini()
>   - xfrm_policy_flush()
>     - xfrm_garbage_collect()
>       - flow_cache_flush()
>         - flow_cache_percpu_empty()
>           - fcp = per_cpu_ptr(fc->percpu, cpu)
>
> To reproduce, just add ipsec in netns and then remove the netns.
>
> v2:
> As Xin Long suggested, since only two other places need to call it. move
> xfrm_garbage_collect() outside xfrm_policy_flush().
>
> v3:
> Fix subject mismatch after v2 fix.
>
> Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
> ---
>  net/key/af_key.c       | 2 ++
>  net/xfrm/xfrm_policy.c | 4 ----
>  net/xfrm/xfrm_user.c   | 1 +
>  3 files changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/net/key/af_key.c b/net/key/af_key.c
> index 512dc43..5103f92 100644
> --- a/net/key/af_key.c
> +++ b/net/key/af_key.c
> @@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
>         int err, err2;
>
>         err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
> +       if (!err)
> +               xfrm_garbage_collect(net);
>         err2 = unicast_flush_resp(sk, hdr);
>         if (err || err2) {
>                 if (err == -ESRCH) /* empty table - old silent behavior */
> diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> index ed4e52d..643a18f 100644
> --- a/net/xfrm/xfrm_policy.c
> +++ b/net/xfrm/xfrm_policy.c
> @@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
>                 err = -ESRCH;
>  out:
>         spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
> -
> -       if (cnt)
> -               xfrm_garbage_collect(net);
> -
>         return err;
>  }
>  EXPORT_SYMBOL(xfrm_policy_flush);
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index 38614df..86116e9 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
>                         return 0;
>                 return err;
>         }
> +       xfrm_garbage_collect(net);
>
>         c.data.type = type;
>         c.event = nlh->nlmsg_type;
> --
> 2.5.5
>
Reviewed-by: Xin Long <lucien.xin@gmail.com>

though I could still see some typo err in changelog.

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

* Re: [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
  2017-06-11  1:44   ` [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush Hangbin Liu
  2017-06-11 10:51     ` Xin Long
@ 2017-06-12 12:13     ` Steffen Klassert
  1 sibling, 0 replies; 14+ messages in thread
From: Steffen Klassert @ 2017-06-12 12:13 UTC (permalink / raw)
  To: Hangbin Liu; +Cc: netdev, David Miller, Xin Long

On Sun, Jun 11, 2017 at 09:44:20AM +0800, Hangbin Liu wrote:
> Now we will force to do garbage collection if any policy removed in
> xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
> first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
> -> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
> dereference when check percpu_empty. The code path looks like:
> 
> flow_cache_fini()
>   - fc->percpu = NULL
> xfrm_policy_fini()
>   - xfrm_policy_flush()
>     - xfrm_garbage_collect()
>       - flow_cache_flush()
>         - flow_cache_percpu_empty()
> 	  - fcp = per_cpu_ptr(fc->percpu, cpu)
> 
> To reproduce, just add ipsec in netns and then remove the netns.
> 
> v2:
> As Xin Long suggested, since only two other places need to call it. move
> xfrm_garbage_collect() outside xfrm_policy_flush().
> 
> v3:
> Fix subject mismatch after v2 fix.
> 
> Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>

Patch applied, thanks eveyone!

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

end of thread, other threads:[~2017-06-12 12:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-09  8:13 [PATCH net] net/flow: fix fc->percpu NULL pointer dereference Hangbin Liu
2017-06-09  8:23 ` Hangbin Liu
2017-06-09  8:32   ` Steffen Klassert
2017-06-09  8:43     ` Xin Long
2017-06-09  9:06       ` Hangbin Liu
2017-06-09  9:49         ` Xin Long
2017-06-09 12:29           ` Hangbin Liu
2017-06-09 12:43             ` Hangbin Liu
2017-06-09 13:09 ` [PATCHv2 " Hangbin Liu
2017-06-10  8:29   ` Xin Long
2017-06-11  1:39     ` Hangbin Liu
2017-06-11  1:44   ` [PATCHv3 net] xfrm: move xfrm_garbage_collect out of xfrm_policy_flush Hangbin Liu
2017-06-11 10:51     ` Xin Long
2017-06-12 12:13     ` Steffen Klassert

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).