ipv6: flowlabel: fl6_sock_lookup() must use atomic_inc_not_zero [Linux 4.14.129]

ipv6: flowlabel: fl6_sock_lookup() must use atomic_inc_not_zero [Linux 4.14.129]

This Linux kernel change "ipv6: flowlabel: fl6_sock_lookup() must use atomic_inc_not_zero" is included in the Linux 4.14.129 release. This change is authored by Eric Dumazet <edumazet [at] google.com> on Thu Jun 6 14:32:34 2019 -0700. The commit for this change in Linux stable tree is 3cc4e63 (patch) which is from upstream commit 65a3c49. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 65a3c49.

ipv6: flowlabel: fl6_sock_lookup() must use atomic_inc_not_zero

[ Upstream commit 65a3c497c0e965a552008db8bc2653f62bc925a1 ]

Before taking a refcount, make sure the object is not already
scheduled for deletion.

Same fix is needed in ipv6_flowlabel_opt()

Fixes: 18367681a10b ("ipv6 flowlabel: Convert np->ipv6_fl_list to RCU.")
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Willem de Bruijn <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 7 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/ipv6/ip6_flowlabel.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 6fa2bc2..c7458a6 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -254,9 +254,9 @@ struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label)
    rcu_read_lock_bh();
    for_each_sk_fl_rcu(np, sfl) {
        struct ip6_flowlabel *fl = sfl->fl;
-       if (fl->label == label) {
+
+       if (fl->label == label && atomic_inc_not_zero(&fl->users)) {
            fl->lastuse = jiffies;
-           atomic_inc(&fl->users);
            rcu_read_unlock_bh();
            return fl;
        }
@@ -623,7 +623,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                        goto done;
                    }
                    fl1 = sfl->fl;
-                   atomic_inc(&fl1->users);
+                   if (!atomic_inc_not_zero(&fl1->users))
+                       fl1 = NULL;
                    break;
                }
            }

Leave a Reply

Your email address will not be published. Required fields are marked *