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