Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: convert fib_treeref from int to refcount_t

refcount_t type should be used instead of int when fib_treeref is used as
a reference counter,and avoid use-after-free risks.

Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://lore.kernel.org/r/20210729071350.28919-1-yajun.deng@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Yajun Deng and committed by
Jakub Kicinski
79976892 3e12361b

+9 -9
+1 -1
include/net/dn_fib.h
··· 29 29 struct dn_fib_info { 30 30 struct dn_fib_info *fib_next; 31 31 struct dn_fib_info *fib_prev; 32 - int fib_treeref; 32 + refcount_t fib_treeref; 33 33 refcount_t fib_clntref; 34 34 int fib_dead; 35 35 unsigned int fib_flags;
+1 -1
include/net/ip_fib.h
··· 133 133 struct hlist_node fib_lhash; 134 134 struct list_head nh_list; 135 135 struct net *fib_net; 136 - int fib_treeref; 136 + refcount_t fib_treeref; 137 137 refcount_t fib_clntref; 138 138 unsigned int fib_flags; 139 139 unsigned char fib_dead;
+3 -3
net/decnet/dn_fib.c
··· 102 102 void dn_fib_release_info(struct dn_fib_info *fi) 103 103 { 104 104 spin_lock(&dn_fib_info_lock); 105 - if (fi && --fi->fib_treeref == 0) { 105 + if (fi && refcount_dec_and_test(&fi->fib_treeref)) { 106 106 if (fi->fib_next) 107 107 fi->fib_next->fib_prev = fi->fib_prev; 108 108 if (fi->fib_prev) ··· 385 385 if ((ofi = dn_fib_find_info(fi)) != NULL) { 386 386 fi->fib_dead = 1; 387 387 dn_fib_free_info(fi); 388 - ofi->fib_treeref++; 388 + refcount_inc(&ofi->fib_treeref); 389 389 return ofi; 390 390 } 391 391 392 - fi->fib_treeref++; 392 + refcount_inc(&fi->fib_treeref); 393 393 refcount_set(&fi->fib_clntref, 1); 394 394 spin_lock(&dn_fib_info_lock); 395 395 fi->fib_next = dn_fib_info_list;
+4 -4
net/ipv4/fib_semantics.c
··· 260 260 void fib_release_info(struct fib_info *fi) 261 261 { 262 262 spin_lock_bh(&fib_info_lock); 263 - if (fi && --fi->fib_treeref == 0) { 263 + if (fi && refcount_dec_and_test(&fi->fib_treeref)) { 264 264 hlist_del(&fi->fib_hash); 265 265 if (fi->fib_prefsrc) 266 266 hlist_del(&fi->fib_lhash); ··· 1373 1373 if (!cfg->fc_mx) { 1374 1374 fi = fib_find_info_nh(net, cfg); 1375 1375 if (fi) { 1376 - fi->fib_treeref++; 1376 + refcount_inc(&fi->fib_treeref); 1377 1377 return fi; 1378 1378 } 1379 1379 } ··· 1547 1547 if (ofi) { 1548 1548 fi->fib_dead = 1; 1549 1549 free_fib_info(fi); 1550 - ofi->fib_treeref++; 1550 + refcount_inc(&ofi->fib_treeref); 1551 1551 return ofi; 1552 1552 } 1553 1553 1554 - fi->fib_treeref++; 1554 + refcount_inc(&fi->fib_treeref); 1555 1555 refcount_set(&fi->fib_clntref, 1); 1556 1556 spin_lock_bh(&fib_info_lock); 1557 1557 hlist_add_head(&fi->fib_hash,