Commit 2f0ff05a authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv6/addrconf: annotate data-races around devconf fields (II)

Final (?) round of this series.

Annotate lockless reads on following devconf fields,
because they be changed concurrently from /proc/net/ipv6/conf.

- accept_dad
- optimistic_dad
- use_optimistic
- use_oif_addrs_only
- ra_honor_pio_life
- keep_addr_on_down
- ndisc_notify
- ndisc_evict_nocarrier
- suppress_frag_ndisc
- addr_gen_mode
- seg6_enabled
- ioam6_enabled
- ioam6_id
- ioam6_id_wide
- drop_unicast_in_l2_multicast
- mldv[12]_unsolicited_report_interval
- force_mld_version
- force_tllao
- accept_untracked_na
- drop_unsolicited_na
- accept_source_route
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2aba913f
...@@ -1557,15 +1557,17 @@ static inline int ipv6_saddr_preferred(int type) ...@@ -1557,15 +1557,17 @@ static inline int ipv6_saddr_preferred(int type)
return 0; return 0;
} }
static bool ipv6_use_optimistic_addr(struct net *net, static bool ipv6_use_optimistic_addr(const struct net *net,
struct inet6_dev *idev) const struct inet6_dev *idev)
{ {
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if (!idev) if (!idev)
return false; return false;
if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad) if (!READ_ONCE(net->ipv6.devconf_all->optimistic_dad) &&
!READ_ONCE(idev->cnf.optimistic_dad))
return false; return false;
if (!net->ipv6.devconf_all->use_optimistic && !idev->cnf.use_optimistic) if (!READ_ONCE(net->ipv6.devconf_all->use_optimistic) &&
!READ_ONCE(idev->cnf.use_optimistic))
return false; return false;
return true; return true;
...@@ -1574,13 +1576,14 @@ static bool ipv6_use_optimistic_addr(struct net *net, ...@@ -1574,13 +1576,14 @@ static bool ipv6_use_optimistic_addr(struct net *net,
#endif #endif
} }
static bool ipv6_allow_optimistic_dad(struct net *net, static bool ipv6_allow_optimistic_dad(const struct net *net,
struct inet6_dev *idev) const struct inet6_dev *idev)
{ {
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if (!idev) if (!idev)
return false; return false;
if (!net->ipv6.devconf_all->optimistic_dad && !idev->cnf.optimistic_dad) if (!READ_ONCE(net->ipv6.devconf_all->optimistic_dad) &&
!READ_ONCE(idev->cnf.optimistic_dad))
return false; return false;
return true; return true;
...@@ -1862,7 +1865,7 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, ...@@ -1862,7 +1865,7 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
idev = __in6_dev_get(dst_dev); idev = __in6_dev_get(dst_dev);
if ((dst_type & IPV6_ADDR_MULTICAST) || if ((dst_type & IPV6_ADDR_MULTICAST) ||
dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL || dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL ||
(idev && idev->cnf.use_oif_addrs_only)) { (idev && READ_ONCE(idev->cnf.use_oif_addrs_only))) {
use_oif_addr = true; use_oif_addr = true;
} }
} }
...@@ -2683,8 +2686,8 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, ...@@ -2683,8 +2686,8 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
}; };
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if ((net->ipv6.devconf_all->optimistic_dad || if ((READ_ONCE(net->ipv6.devconf_all->optimistic_dad) ||
in6_dev->cnf.optimistic_dad) && READ_ONCE(in6_dev->cnf.optimistic_dad)) &&
!net->ipv6.devconf_all->forwarding && sllao) !net->ipv6.devconf_all->forwarding && sllao)
cfg.ifa_flags |= IFA_F_OPTIMISTIC; cfg.ifa_flags |= IFA_F_OPTIMISTIC;
#endif #endif
...@@ -2733,7 +2736,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, ...@@ -2733,7 +2736,7 @@ int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev,
*/ */
update_lft = !create && stored_lft; update_lft = !create && stored_lft;
if (update_lft && !in6_dev->cnf.ra_honor_pio_life) { if (update_lft && !READ_ONCE(in6_dev->cnf.ra_honor_pio_life)) {
const u32 minimum_lft = min_t(u32, const u32 minimum_lft = min_t(u32,
stored_lft, MIN_VALID_LIFETIME); stored_lft, MIN_VALID_LIFETIME);
valid_lft = max(valid_lft, minimum_lft); valid_lft = max(valid_lft, minimum_lft);
...@@ -3317,8 +3320,8 @@ void addrconf_add_linklocal(struct inet6_dev *idev, ...@@ -3317,8 +3320,8 @@ void addrconf_add_linklocal(struct inet6_dev *idev,
struct inet6_ifaddr *ifp; struct inet6_ifaddr *ifp;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
if ((dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad || if ((READ_ONCE(dev_net(idev->dev)->ipv6.devconf_all->optimistic_dad) ||
idev->cnf.optimistic_dad) && READ_ONCE(idev->cnf.optimistic_dad)) &&
!dev_net(idev->dev)->ipv6.devconf_all->forwarding) !dev_net(idev->dev)->ipv6.devconf_all->forwarding)
cfg.ifa_flags |= IFA_F_OPTIMISTIC; cfg.ifa_flags |= IFA_F_OPTIMISTIC;
#endif #endif
...@@ -3890,10 +3893,10 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister) ...@@ -3890,10 +3893,10 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister)
*/ */
if (!unregister && !idev->cnf.disable_ipv6) { if (!unregister && !idev->cnf.disable_ipv6) {
/* aggregate the system setting and interface setting */ /* aggregate the system setting and interface setting */
int _keep_addr = net->ipv6.devconf_all->keep_addr_on_down; int _keep_addr = READ_ONCE(net->ipv6.devconf_all->keep_addr_on_down);
if (!_keep_addr) if (!_keep_addr)
_keep_addr = idev->cnf.keep_addr_on_down; _keep_addr = READ_ONCE(idev->cnf.keep_addr_on_down);
keep_addr = (_keep_addr > 0); keep_addr = (_keep_addr > 0);
} }
...@@ -4119,8 +4122,8 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp) ...@@ -4119,8 +4122,8 @@ static void addrconf_dad_begin(struct inet6_ifaddr *ifp)
net = dev_net(dev); net = dev_net(dev);
if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
(net->ipv6.devconf_all->accept_dad < 1 && (READ_ONCE(net->ipv6.devconf_all->accept_dad) < 1 &&
idev->cnf.accept_dad < 1) || READ_ONCE(idev->cnf.accept_dad) < 1) ||
!(ifp->flags&IFA_F_TENTATIVE) || !(ifp->flags&IFA_F_TENTATIVE) ||
ifp->flags & IFA_F_NODAD) { ifp->flags & IFA_F_NODAD) {
bool send_na = false; bool send_na = false;
...@@ -4212,8 +4215,8 @@ static void addrconf_dad_work(struct work_struct *w) ...@@ -4212,8 +4215,8 @@ static void addrconf_dad_work(struct work_struct *w)
action = DAD_ABORT; action = DAD_ABORT;
ifp->state = INET6_IFADDR_STATE_POSTDAD; ifp->state = INET6_IFADDR_STATE_POSTDAD;
if ((dev_net(idev->dev)->ipv6.devconf_all->accept_dad > 1 || if ((READ_ONCE(dev_net(idev->dev)->ipv6.devconf_all->accept_dad) > 1 ||
idev->cnf.accept_dad > 1) && READ_ONCE(idev->cnf.accept_dad) > 1) &&
!idev->cnf.disable_ipv6 && !idev->cnf.disable_ipv6 &&
!(ifp->flags & IFA_F_STABLE_PRIVACY)) { !(ifp->flags & IFA_F_STABLE_PRIVACY)) {
struct in6_addr addr; struct in6_addr addr;
...@@ -4352,8 +4355,8 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id, ...@@ -4352,8 +4355,8 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
/* send unsolicited NA if enabled */ /* send unsolicited NA if enabled */
if (send_na && if (send_na &&
(ifp->idev->cnf.ndisc_notify || (READ_ONCE(ifp->idev->cnf.ndisc_notify) ||
dev_net(dev)->ipv6.devconf_all->ndisc_notify)) { READ_ONCE(dev_net(dev)->ipv6.devconf_all->ndisc_notify))) {
ndisc_send_na(dev, &in6addr_linklocal_allnodes, &ifp->addr, ndisc_send_na(dev, &in6addr_linklocal_allnodes, &ifp->addr,
/*router=*/ !!ifp->idev->cnf.forwarding, /*router=*/ !!ifp->idev->cnf.forwarding,
/*solicited=*/ false, /*override=*/ true, /*solicited=*/ false, /*override=*/ true,
...@@ -6541,7 +6544,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -6541,7 +6544,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) { } else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {
struct net_device *dev; struct net_device *dev;
net->ipv6.devconf_dflt->addr_gen_mode = new_val; WRITE_ONCE(net->ipv6.devconf_dflt->addr_gen_mode, new_val);
for_each_netdev(net, dev) { for_each_netdev(net, dev) {
idev = __in6_dev_get(dev); idev = __in6_dev_get(dev);
if (idev && if (idev &&
...@@ -6553,7 +6556,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write, ...@@ -6553,7 +6556,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,
} }
} }
*((u32 *)ctl->data) = new_val; WRITE_ONCE(*((u32 *)ctl->data), new_val);
} }
out: out:
......
...@@ -379,9 +379,8 @@ static int ipv6_srh_rcv(struct sk_buff *skb) ...@@ -379,9 +379,8 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
idev = __in6_dev_get(skb->dev); idev = __in6_dev_get(skb->dev);
accept_seg6 = net->ipv6.devconf_all->seg6_enabled; accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled),
if (accept_seg6 > idev->cnf.seg6_enabled) READ_ONCE(idev->cnf.seg6_enabled));
accept_seg6 = idev->cnf.seg6_enabled;
if (!accept_seg6) { if (!accept_seg6) {
kfree_skb(skb); kfree_skb(skb);
...@@ -655,10 +654,13 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb) ...@@ -655,10 +654,13 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
struct ipv6_rt_hdr *hdr; struct ipv6_rt_hdr *hdr;
struct rt0_hdr *rthdr; struct rt0_hdr *rthdr;
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
int accept_source_route = net->ipv6.devconf_all->accept_source_route; int accept_source_route;
if (idev && accept_source_route > idev->cnf.accept_source_route) accept_source_route = READ_ONCE(net->ipv6.devconf_all->accept_source_route);
accept_source_route = idev->cnf.accept_source_route;
if (idev)
accept_source_route = min(accept_source_route,
READ_ONCE(idev->cnf.accept_source_route));
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
!pskb_may_pull(skb, (skb_transport_offset(skb) + !pskb_may_pull(skb, (skb_transport_offset(skb) +
...@@ -919,7 +921,7 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff) ...@@ -919,7 +921,7 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff)
goto drop; goto drop;
/* Ignore if IOAM is not enabled on ingress */ /* Ignore if IOAM is not enabled on ingress */
if (!__in6_dev_get(skb->dev)->cnf.ioam6_enabled) if (!READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_enabled))
goto ignore; goto ignore;
/* Truncated Option header */ /* Truncated Option header */
......
...@@ -727,7 +727,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb, ...@@ -727,7 +727,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
if (!skb->dev) if (!skb->dev)
raw16 = IOAM6_U16_UNAVAILABLE; raw16 = IOAM6_U16_UNAVAILABLE;
else else
raw16 = (__force u16)__in6_dev_get(skb->dev)->cnf.ioam6_id; raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id);
*(__be16 *)data = cpu_to_be16(raw16); *(__be16 *)data = cpu_to_be16(raw16);
data += sizeof(__be16); data += sizeof(__be16);
...@@ -735,7 +735,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb, ...@@ -735,7 +735,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
raw16 = IOAM6_U16_UNAVAILABLE; raw16 = IOAM6_U16_UNAVAILABLE;
else else
raw16 = (__force u16)__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id; raw16 = (__force u16)READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id);
*(__be16 *)data = cpu_to_be16(raw16); *(__be16 *)data = cpu_to_be16(raw16);
data += sizeof(__be16); data += sizeof(__be16);
...@@ -822,7 +822,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb, ...@@ -822,7 +822,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
if (!skb->dev) if (!skb->dev)
raw32 = IOAM6_U32_UNAVAILABLE; raw32 = IOAM6_U32_UNAVAILABLE;
else else
raw32 = __in6_dev_get(skb->dev)->cnf.ioam6_id_wide; raw32 = READ_ONCE(__in6_dev_get(skb->dev)->cnf.ioam6_id_wide);
*(__be32 *)data = cpu_to_be32(raw32); *(__be32 *)data = cpu_to_be32(raw32);
data += sizeof(__be32); data += sizeof(__be32);
...@@ -830,7 +830,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb, ...@@ -830,7 +830,7 @@ static void __ioam6_fill_trace_data(struct sk_buff *skb,
if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) if (skb_dst(skb)->dev->flags & IFF_LOOPBACK)
raw32 = IOAM6_U32_UNAVAILABLE; raw32 = IOAM6_U32_UNAVAILABLE;
else else
raw32 = __in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide; raw32 = READ_ONCE(__in6_dev_get(skb_dst(skb)->dev)->cnf.ioam6_id_wide);
*(__be32 *)data = cpu_to_be32(raw32); *(__be32 *)data = cpu_to_be32(raw32);
data += sizeof(__be32); data += sizeof(__be32);
......
...@@ -236,7 +236,7 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev, ...@@ -236,7 +236,7 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
if (!ipv6_addr_is_multicast(&hdr->daddr) && if (!ipv6_addr_is_multicast(&hdr->daddr) &&
(skb->pkt_type == PACKET_BROADCAST || (skb->pkt_type == PACKET_BROADCAST ||
skb->pkt_type == PACKET_MULTICAST) && skb->pkt_type == PACKET_MULTICAST) &&
idev->cnf.drop_unicast_in_l2_multicast) { READ_ONCE(idev->cnf.drop_unicast_in_l2_multicast)) {
SKB_DR_SET(reason, UNICAST_IN_L2_MULTICAST); SKB_DR_SET(reason, UNICAST_IN_L2_MULTICAST);
goto err; goto err;
} }
......
...@@ -159,9 +159,9 @@ static int unsolicited_report_interval(struct inet6_dev *idev) ...@@ -159,9 +159,9 @@ static int unsolicited_report_interval(struct inet6_dev *idev)
int iv; int iv;
if (mld_in_v1_mode(idev)) if (mld_in_v1_mode(idev))
iv = idev->cnf.mldv1_unsolicited_report_interval; iv = READ_ONCE(idev->cnf.mldv1_unsolicited_report_interval);
else else
iv = idev->cnf.mldv2_unsolicited_report_interval; iv = READ_ONCE(idev->cnf.mldv2_unsolicited_report_interval);
return iv > 0 ? iv : 1; return iv > 0 ? iv : 1;
} }
...@@ -1202,15 +1202,15 @@ static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, ...@@ -1202,15 +1202,15 @@ static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
static int mld_force_mld_version(const struct inet6_dev *idev) static int mld_force_mld_version(const struct inet6_dev *idev)
{ {
const struct net *net = dev_net(idev->dev);
int all_force;
all_force = READ_ONCE(net->ipv6.devconf_all->force_mld_version);
/* Normally, both are 0 here. If enforcement to a particular is /* Normally, both are 0 here. If enforcement to a particular is
* being used, individual device enforcement will have a lower * being used, individual device enforcement will have a lower
* precedence over 'all' device (.../conf/all/force_mld_version). * precedence over 'all' device (.../conf/all/force_mld_version).
*/ */
return all_force ?: READ_ONCE(idev->cnf.force_mld_version);
if (dev_net(idev->dev)->ipv6.devconf_all->force_mld_version != 0)
return dev_net(idev->dev)->ipv6.devconf_all->force_mld_version;
else
return idev->cnf.force_mld_version;
} }
static bool mld_in_v2_mode_only(const struct inet6_dev *idev) static bool mld_in_v2_mode_only(const struct inet6_dev *idev)
......
...@@ -451,7 +451,7 @@ static void ip6_nd_hdr(struct sk_buff *skb, ...@@ -451,7 +451,7 @@ static void ip6_nd_hdr(struct sk_buff *skb,
rcu_read_lock(); rcu_read_lock();
idev = __in6_dev_get(skb->dev); idev = __in6_dev_get(skb->dev);
tclass = idev ? idev->cnf.ndisc_tclass : 0; tclass = idev ? READ_ONCE(idev->cnf.ndisc_tclass) : 0;
rcu_read_unlock(); rcu_read_unlock();
skb_push(skb, sizeof(*hdr)); skb_push(skb, sizeof(*hdr));
...@@ -535,7 +535,7 @@ void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr, ...@@ -535,7 +535,7 @@ void ndisc_send_na(struct net_device *dev, const struct in6_addr *daddr,
src_addr = solicited_addr; src_addr = solicited_addr;
if (ifp->flags & IFA_F_OPTIMISTIC) if (ifp->flags & IFA_F_OPTIMISTIC)
override = false; override = false;
inc_opt |= ifp->idev->cnf.force_tllao; inc_opt |= READ_ONCE(ifp->idev->cnf.force_tllao);
in6_ifa_put(ifp); in6_ifa_put(ifp);
} else { } else {
if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr, if (ipv6_dev_get_saddr(dev_net(dev), dev, daddr,
...@@ -974,7 +974,7 @@ static int accept_untracked_na(struct net_device *dev, struct in6_addr *saddr) ...@@ -974,7 +974,7 @@ static int accept_untracked_na(struct net_device *dev, struct in6_addr *saddr)
{ {
struct inet6_dev *idev = __in6_dev_get(dev); struct inet6_dev *idev = __in6_dev_get(dev);
switch (idev->cnf.accept_untracked_na) { switch (READ_ONCE(idev->cnf.accept_untracked_na)) {
case 0: /* Don't accept untracked na (absent in neighbor cache) */ case 0: /* Don't accept untracked na (absent in neighbor cache) */
return 0; return 0;
case 1: /* Create new entries from na if currently untracked */ case 1: /* Create new entries from na if currently untracked */
...@@ -1025,7 +1025,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb) ...@@ -1025,7 +1025,7 @@ static enum skb_drop_reason ndisc_recv_na(struct sk_buff *skb)
* drop_unsolicited_na takes precedence over accept_untracked_na * drop_unsolicited_na takes precedence over accept_untracked_na
*/ */
if (!msg->icmph.icmp6_solicited && idev && if (!msg->icmph.icmp6_solicited && idev &&
idev->cnf.drop_unsolicited_na) READ_ONCE(idev->cnf.drop_unsolicited_na))
return reason; return reason;
if (!ndisc_parse_options(dev, msg->opt, ndoptlen, &ndopts)) if (!ndisc_parse_options(dev, msg->opt, ndoptlen, &ndopts))
...@@ -1818,7 +1818,7 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb) ...@@ -1818,7 +1818,7 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
if (!idev) if (!idev)
return true; return true;
if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED && if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED &&
idev->cnf.suppress_frag_ndisc) { READ_ONCE(idev->cnf.suppress_frag_ndisc)) {
net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n"); net_warn_ratelimited("Received fragmented ndisc packet. Carefully consider disabling suppress_frag_ndisc.\n");
return true; return true;
} }
...@@ -1895,8 +1895,8 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, ...@@ -1895,8 +1895,8 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
idev = in6_dev_get(dev); idev = in6_dev_get(dev);
if (!idev) if (!idev)
break; break;
if (idev->cnf.ndisc_notify || if (READ_ONCE(idev->cnf.ndisc_notify) ||
net->ipv6.devconf_all->ndisc_notify) READ_ONCE(net->ipv6.devconf_all->ndisc_notify))
ndisc_send_unsol_na(dev); ndisc_send_unsol_na(dev);
in6_dev_put(idev); in6_dev_put(idev);
break; break;
...@@ -1905,8 +1905,8 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, ...@@ -1905,8 +1905,8 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
if (!idev) if (!idev)
evict_nocarrier = true; evict_nocarrier = true;
else { else {
evict_nocarrier = idev->cnf.ndisc_evict_nocarrier && evict_nocarrier = READ_ONCE(idev->cnf.ndisc_evict_nocarrier) &&
net->ipv6.devconf_all->ndisc_evict_nocarrier; READ_ONCE(net->ipv6.devconf_all->ndisc_evict_nocarrier);
in6_dev_put(idev); in6_dev_put(idev);
} }
......
...@@ -241,6 +241,7 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) ...@@ -241,6 +241,7 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb)
struct sr6_tlv_hmac *tlv; struct sr6_tlv_hmac *tlv;
struct ipv6_sr_hdr *srh; struct ipv6_sr_hdr *srh;
struct inet6_dev *idev; struct inet6_dev *idev;
int require_hmac;
idev = __in6_dev_get(skb->dev); idev = __in6_dev_get(skb->dev);
...@@ -248,16 +249,17 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) ...@@ -248,16 +249,17 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb)
tlv = seg6_get_tlv_hmac(srh); tlv = seg6_get_tlv_hmac(srh);
require_hmac = READ_ONCE(idev->cnf.seg6_require_hmac);
/* mandatory check but no tlv */ /* mandatory check but no tlv */
if (idev->cnf.seg6_require_hmac > 0 && !tlv) if (require_hmac > 0 && !tlv)
return false; return false;
/* no check */ /* no check */
if (idev->cnf.seg6_require_hmac < 0) if (require_hmac < 0)
return true; return true;
/* check only if present */ /* check only if present */
if (idev->cnf.seg6_require_hmac == 0 && !tlv) if (require_hmac == 0 && !tlv)
return true; return true;
/* now, seg6_require_hmac >= 0 && tlv */ /* now, seg6_require_hmac >= 0 && tlv */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment