Skip to content

Commit 2aba913

Browse files
edumazetdavem330
authored andcommitted
ipv6/addrconf: annotate data-races around devconf fields (I)
Annotate lockless reads and writes on following devconf fields: - regen_min_advance - regen_max_retry - dad_transmits - use_tempaddr - max_addresses - max_desync_factor - temp_valid_lft - rtr_solicits - rtr_solicit_max_interval - rtr_solicit_interval - rtr_solicit_delay - enhanced_dad - accept_redirects Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 45b90ec commit 2aba913

2 files changed

Lines changed: 39 additions & 31 deletions

File tree

net/ipv6/addrconf.c

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,11 +1359,12 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
13591359
in6_ifa_put(ifp);
13601360
}
13611361

1362-
static unsigned long ipv6_get_regen_advance(struct inet6_dev *idev)
1362+
static unsigned long ipv6_get_regen_advance(const struct inet6_dev *idev)
13631363
{
1364-
return idev->cnf.regen_min_advance + idev->cnf.regen_max_retry *
1365-
idev->cnf.dad_transmits *
1366-
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
1364+
return READ_ONCE(idev->cnf.regen_min_advance) +
1365+
READ_ONCE(idev->cnf.regen_max_retry) *
1366+
READ_ONCE(idev->cnf.dad_transmits) *
1367+
max(NEIGH_VAR(idev->nd_parms, RETRANS_TIME), HZ/100) / HZ;
13671368
}
13681369

13691370
static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
@@ -1384,16 +1385,16 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
13841385

13851386
retry:
13861387
in6_dev_hold(idev);
1387-
if (idev->cnf.use_tempaddr <= 0) {
1388+
if (READ_ONCE(idev->cnf.use_tempaddr) <= 0) {
13881389
write_unlock_bh(&idev->lock);
13891390
pr_info("%s: use_tempaddr is disabled\n", __func__);
13901391
in6_dev_put(idev);
13911392
ret = -1;
13921393
goto out;
13931394
}
13941395
spin_lock_bh(&ifp->lock);
1395-
if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
1396-
idev->cnf.use_tempaddr = -1; /*XXX*/
1396+
if (ifp->regen_count++ >= READ_ONCE(idev->cnf.regen_max_retry)) {
1397+
WRITE_ONCE(idev->cnf.use_tempaddr, -1); /*XXX*/
13971398
spin_unlock_bh(&ifp->lock);
13981399
write_unlock_bh(&idev->lock);
13991400
pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
@@ -1415,7 +1416,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
14151416
*/
14161417
cnf_temp_preferred_lft = READ_ONCE(idev->cnf.temp_prefered_lft);
14171418
max_desync_factor = min_t(long,
1418-
idev->cnf.max_desync_factor,
1419+
READ_ONCE(idev->cnf.max_desync_factor),
14191420
cnf_temp_preferred_lft - regen_advance);
14201421

14211422
if (unlikely(idev->desync_factor > max_desync_factor)) {
@@ -1432,7 +1433,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
14321433

14331434
memset(&cfg, 0, sizeof(cfg));
14341435
cfg.valid_lft = min_t(__u32, ifp->valid_lft,
1435-
idev->cnf.temp_valid_lft + age);
1436+
READ_ONCE(idev->cnf.temp_valid_lft) + age);
14361437
cfg.preferred_lft = cnf_temp_preferred_lft + age - idev->desync_factor;
14371438
cfg.preferred_lft = min_t(__u32, if_public_preferred_lft, cfg.preferred_lft);
14381439
cfg.preferred_lft = min_t(__u32, cfg.valid_lft, cfg.preferred_lft);
@@ -1685,7 +1686,7 @@ static int ipv6_get_saddr_eval(struct net *net,
16851686
*/
16861687
int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ?
16871688
!!(dst->prefs & IPV6_PREFER_SRC_TMP) :
1688-
score->ifa->idev->cnf.use_tempaddr >= 2;
1689+
READ_ONCE(score->ifa->idev->cnf.use_tempaddr) >= 2;
16891690
ret = (!(score->ifa->flags & IFA_F_TEMPORARY)) ^ preftmp;
16901691
break;
16911692
}
@@ -2168,6 +2169,7 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
21682169
{
21692170
struct inet6_dev *idev = ifp->idev;
21702171
struct net *net = dev_net(idev->dev);
2172+
int max_addresses;
21712173

21722174
if (addrconf_dad_end(ifp)) {
21732175
in6_ifa_put(ifp);
@@ -2205,9 +2207,9 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
22052207

22062208
spin_unlock_bh(&ifp->lock);
22072209

2208-
if (idev->cnf.max_addresses &&
2209-
ipv6_count_addresses(idev) >=
2210-
idev->cnf.max_addresses)
2210+
max_addresses = READ_ONCE(idev->cnf.max_addresses);
2211+
if (max_addresses &&
2212+
ipv6_count_addresses(idev) >= max_addresses)
22112213
goto lock_errdad;
22122214

22132215
net_info_ratelimited("%s: generating new stable privacy address because of DAD conflict\n",
@@ -2604,11 +2606,11 @@ static void manage_tempaddrs(struct inet6_dev *idev,
26042606
* (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
26052607
*/
26062608
age = (now - ift->cstamp) / HZ;
2607-
max_valid = idev->cnf.temp_valid_lft - age;
2609+
max_valid = READ_ONCE(idev->cnf.temp_valid_lft) - age;
26082610
if (max_valid < 0)
26092611
max_valid = 0;
26102612

2611-
max_prefered = idev->cnf.temp_prefered_lft -
2613+
max_prefered = READ_ONCE(idev->cnf.temp_prefered_lft) -
26122614
idev->desync_factor - age;
26132615
if (max_prefered < 0)
26142616
max_prefered = 0;
@@ -2641,7 +2643,7 @@ static void manage_tempaddrs(struct inet6_dev *idev,
26412643
if (list_empty(&idev->tempaddr_list) && (valid_lft || prefered_lft))
26422644
create = true;
26432645

2644-
if (create && idev->cnf.use_tempaddr > 0) {
2646+
if (create && READ_ONCE(idev->cnf.use_tempaddr) > 0) {
26452647
/* When a new public address is created as described
26462648
* in [ADDRCONF], also create a new temporary address.
26472649
*/
@@ -2669,7 +2671,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
26692671
int create = 0, update_lft = 0;
26702672

26712673
if (!ifp && valid_lft) {
2672-
int max_addresses = in6_dev->cnf.max_addresses;
2674+
int max_addresses = READ_ONCE(in6_dev->cnf.max_addresses);
26732675
struct ifa6_config cfg = {
26742676
.pfx = addr,
26752677
.plen = pinfo->prefix_len,
@@ -4028,6 +4030,7 @@ static void addrconf_rs_timer(struct timer_list *t)
40284030
struct inet6_dev *idev = from_timer(idev, t, rs_timer);
40294031
struct net_device *dev = idev->dev;
40304032
struct in6_addr lladdr;
4033+
int rtr_solicits;
40314034

40324035
write_lock(&idev->lock);
40334036
if (idev->dead || !(idev->if_flags & IF_READY))
@@ -4040,7 +4043,9 @@ static void addrconf_rs_timer(struct timer_list *t)
40404043
if (idev->if_flags & IF_RA_RCVD)
40414044
goto out;
40424045

4043-
if (idev->rs_probes++ < idev->cnf.rtr_solicits || idev->cnf.rtr_solicits < 0) {
4046+
rtr_solicits = READ_ONCE(idev->cnf.rtr_solicits);
4047+
4048+
if (idev->rs_probes++ < rtr_solicits || rtr_solicits < 0) {
40444049
write_unlock(&idev->lock);
40454050
if (!ipv6_get_lladdr(dev, &lladdr, IFA_F_TENTATIVE))
40464051
ndisc_send_rs(dev, &lladdr,
@@ -4050,11 +4055,12 @@ static void addrconf_rs_timer(struct timer_list *t)
40504055

40514056
write_lock(&idev->lock);
40524057
idev->rs_interval = rfc3315_s14_backoff_update(
4053-
idev->rs_interval, idev->cnf.rtr_solicit_max_interval);
4058+
idev->rs_interval,
4059+
READ_ONCE(idev->cnf.rtr_solicit_max_interval));
40544060
/* The wait after the last probe can be shorter */
40554061
addrconf_mod_rs_timer(idev, (idev->rs_probes ==
4056-
idev->cnf.rtr_solicits) ?
4057-
idev->cnf.rtr_solicit_delay :
4062+
READ_ONCE(idev->cnf.rtr_solicits)) ?
4063+
READ_ONCE(idev->cnf.rtr_solicit_delay) :
40584064
idev->rs_interval);
40594065
} else {
40604066
/*
@@ -4075,24 +4081,25 @@ static void addrconf_rs_timer(struct timer_list *t)
40754081
*/
40764082
static void addrconf_dad_kick(struct inet6_ifaddr *ifp)
40774083
{
4078-
unsigned long rand_num;
40794084
struct inet6_dev *idev = ifp->idev;
4085+
unsigned long rand_num;
40804086
u64 nonce;
40814087

40824088
if (ifp->flags & IFA_F_OPTIMISTIC)
40834089
rand_num = 0;
40844090
else
4085-
rand_num = get_random_u32_below(idev->cnf.rtr_solicit_delay ? : 1);
4091+
rand_num = get_random_u32_below(
4092+
READ_ONCE(idev->cnf.rtr_solicit_delay) ? : 1);
40864093

40874094
nonce = 0;
4088-
if (idev->cnf.enhanced_dad ||
4089-
dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad) {
4095+
if (READ_ONCE(idev->cnf.enhanced_dad) ||
4096+
READ_ONCE(dev_net(idev->dev)->ipv6.devconf_all->enhanced_dad)) {
40904097
do
40914098
get_random_bytes(&nonce, 6);
40924099
while (nonce == 0);
40934100
}
40944101
ifp->dad_nonce = nonce;
4095-
ifp->dad_probes = idev->cnf.dad_transmits;
4102+
ifp->dad_probes = READ_ONCE(idev->cnf.dad_transmits);
40964103
addrconf_mod_dad_work(ifp, rand_num);
40974104
}
40984105

@@ -4331,7 +4338,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
43314338
send_mld = ifp->scope == IFA_LINK && ipv6_lonely_lladdr(ifp);
43324339
send_rs = send_mld &&
43334340
ipv6_accept_ra(ifp->idev) &&
4334-
ifp->idev->cnf.rtr_solicits != 0 &&
4341+
READ_ONCE(ifp->idev->cnf.rtr_solicits) != 0 &&
43354342
(dev->flags & IFF_LOOPBACK) == 0 &&
43364343
(dev->type != ARPHRD_TUNNEL) &&
43374344
!netif_is_team_port(dev);
@@ -4366,7 +4373,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
43664373
write_lock_bh(&ifp->idev->lock);
43674374
spin_lock(&ifp->lock);
43684375
ifp->idev->rs_interval = rfc3315_s14_backoff_init(
4369-
ifp->idev->cnf.rtr_solicit_interval);
4376+
READ_ONCE(ifp->idev->cnf.rtr_solicit_interval));
43704377
ifp->idev->rs_probes = 1;
43714378
ifp->idev->if_flags |= IF_RS_SENT;
43724379
addrconf_mod_rs_timer(ifp->idev, ifp->idev->rs_interval);
@@ -5915,7 +5922,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token,
59155922
return -EINVAL;
59165923
}
59175924

5918-
if (idev->cnf.rtr_solicits == 0) {
5925+
if (READ_ONCE(idev->cnf.rtr_solicits) == 0) {
59195926
NL_SET_ERR_MSG(extack,
59205927
"Router solicitation is disabled on device");
59215928
return -EINVAL;
@@ -5948,7 +5955,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token,
59485955
if (update_rs) {
59495956
idev->if_flags |= IF_RS_SENT;
59505957
idev->rs_interval = rfc3315_s14_backoff_init(
5951-
idev->cnf.rtr_solicit_interval);
5958+
READ_ONCE(idev->cnf.rtr_solicit_interval));
59525959
idev->rs_probes = 1;
59535960
addrconf_mod_rs_timer(idev, idev->rs_interval);
59545961
}

net/ipv6/route.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4150,7 +4150,8 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
41504150
in6_dev = __in6_dev_get(skb->dev);
41514151
if (!in6_dev)
41524152
return;
4153-
if (READ_ONCE(in6_dev->cnf.forwarding) || !in6_dev->cnf.accept_redirects)
4153+
if (READ_ONCE(in6_dev->cnf.forwarding) ||
4154+
!READ_ONCE(in6_dev->cnf.accept_redirects))
41544155
return;
41554156

41564157
/* RFC2461 8.1:

0 commit comments

Comments
 (0)