[PATCH] net/ipv6: Convert from atomic_t to refcount_t on ip6_flowlabel->users
Xiyu Yang
xiyuyang19 at fudan.edu.cn
Mon Jul 19 01:35:06 PDT 2021
refcount_t type and corresponding API can protect refcounters from
accidental underflow and overflow and further use-after-free situations.
Signed-off-by: Xiyu Yang <xiyuyang19 at fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf at gmail.com>
---
include/net/ipv6.h | 5 +++--
net/ipv6/ip6_flowlabel.c | 18 +++++++++---------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index f2d0ecc257bb..de9ba310c7be 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -9,6 +9,7 @@
#ifndef _NET_IPV6_H
#define _NET_IPV6_H
+#include <linux/refcount.h>
#include <linux/ipv6.h>
#include <linux/hardirq.h>
#include <linux/jhash.h>
@@ -313,7 +314,7 @@ enum flowlabel_reflect {
struct ip6_flowlabel {
struct ip6_flowlabel __rcu *next;
__be32 label;
- atomic_t users;
+ refcount_t users;
struct in6_addr dst;
struct ipv6_txoptions *opt;
unsigned long linger;
@@ -417,7 +418,7 @@ bool ip6_autoflowlabel(struct net *net, const struct ipv6_pinfo *np);
static inline void fl6_sock_release(struct ip6_flowlabel *fl)
{
if (fl)
- atomic_dec(&fl->users);
+ refcount_dec(&fl->users);
}
void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index aa673a6a7e43..d0a7f099fedb 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -88,7 +88,7 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label)
rcu_read_lock_bh();
fl = __fl_lookup(net, label);
- if (fl && !atomic_inc_not_zero(&fl->users))
+ if (fl && !refcount_inc_not_zero(&fl->users))
fl = NULL;
rcu_read_unlock_bh();
return fl;
@@ -128,7 +128,7 @@ static void fl_release(struct ip6_flowlabel *fl)
spin_lock_bh(&ip6_fl_lock);
fl->lastuse = jiffies;
- if (atomic_dec_and_test(&fl->users)) {
+ if (refcount_dec_and_test(&fl->users)) {
unsigned long ttd = fl->lastuse + fl->linger;
if (time_after(ttd, fl->expires))
fl->expires = ttd;
@@ -160,7 +160,7 @@ static void ip6_fl_gc(struct timer_list *unused)
flp = &fl_ht[i];
while ((fl = rcu_dereference_protected(*flp,
lockdep_is_held(&ip6_fl_lock))) != NULL) {
- if (atomic_read(&fl->users) == 0) {
+ if (refcount_read(&fl->users) == 0) {
unsigned long ttd = fl->lastuse + fl->linger;
if (time_after(ttd, fl->expires))
fl->expires = ttd;
@@ -198,7 +198,7 @@ static void __net_exit ip6_fl_purge(struct net *net)
while ((fl = rcu_dereference_protected(*flp,
lockdep_is_held(&ip6_fl_lock))) != NULL) {
if (net_eq(fl->fl_net, net) &&
- atomic_read(&fl->users) == 0) {
+ refcount_read(&fl->users) == 0) {
*flp = fl->next;
fl_free(fl);
atomic_dec(&fl_size);
@@ -238,7 +238,7 @@ static struct ip6_flowlabel *fl_intern(struct net *net,
*/
lfl = __fl_lookup(net, fl->label);
if (lfl) {
- atomic_inc(&lfl->users);
+ refcount_inc(&lfl->users);
spin_unlock_bh(&ip6_fl_lock);
return lfl;
}
@@ -267,7 +267,7 @@ struct ip6_flowlabel *__fl6_sock_lookup(struct sock *sk, __be32 label)
for_each_sk_fl_rcu(np, sfl) {
struct ip6_flowlabel *fl = sfl->fl;
- if (fl->label == label && atomic_inc_not_zero(&fl->users)) {
+ if (fl->label == label && refcount_inc_not_zero(&fl->users)) {
fl->lastuse = jiffies;
rcu_read_unlock_bh();
return fl;
@@ -435,7 +435,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
goto done;
}
fl->dst = freq->flr_dst;
- atomic_set(&fl->users, 1);
+ refcount_set(&fl->users, 1);
switch (fl->share) {
case IPV6_FL_S_EXCL:
case IPV6_FL_S_ANY:
@@ -647,7 +647,7 @@ static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq,
goto done;
}
fl1 = sfl->fl;
- if (!atomic_inc_not_zero(&fl1->users))
+ if (!refcount_inc_not_zero(&fl1->users))
fl1 = NULL;
break;
}
@@ -845,7 +845,7 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
((fl->share == IPV6_FL_S_USER) ?
from_kuid_munged(seq_user_ns(seq), fl->owner.uid) :
0)),
- atomic_read(&fl->users),
+ refcount_read(&fl->users),
fl->linger/HZ,
(long)(fl->expires - jiffies)/HZ,
&fl->dst,
--
2.7.4
More information about the linux-arm-kernel
mailing list