Commit 638cf4a2 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ip6mr: do not acquire mrt_lock in ioctl(SIOCGETMIFCNT_IN6)

rcu_read_lock() protection is good enough.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d086587
...@@ -1896,20 +1896,20 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) ...@@ -1896,20 +1896,20 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
if (vr.mifi >= mrt->maxvif) if (vr.mifi >= mrt->maxvif)
return -EINVAL; return -EINVAL;
vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif); vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
read_lock(&mrt_lock); rcu_read_lock();
vif = &mrt->vif_table[vr.mifi]; vif = &mrt->vif_table[vr.mifi];
if (VIF_EXISTS(mrt, vr.mifi)) { if (VIF_EXISTS(mrt, vr.mifi)) {
vr.icount = vif->pkt_in; vr.icount = READ_ONCE(vif->pkt_in);
vr.ocount = vif->pkt_out; vr.ocount = READ_ONCE(vif->pkt_out);
vr.ibytes = vif->bytes_in; vr.ibytes = READ_ONCE(vif->bytes_in);
vr.obytes = vif->bytes_out; vr.obytes = READ_ONCE(vif->bytes_out);
read_unlock(&mrt_lock); rcu_read_unlock();
if (copy_to_user(arg, &vr, sizeof(vr))) if (copy_to_user(arg, &vr, sizeof(vr)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
read_unlock(&mrt_lock); rcu_read_unlock();
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
case SIOCGETSGCNT_IN6: case SIOCGETSGCNT_IN6:
if (copy_from_user(&sr, arg, sizeof(sr))) if (copy_from_user(&sr, arg, sizeof(sr)))
...@@ -1971,20 +1971,20 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) ...@@ -1971,20 +1971,20 @@ int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
if (vr.mifi >= mrt->maxvif) if (vr.mifi >= mrt->maxvif)
return -EINVAL; return -EINVAL;
vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif); vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
read_lock(&mrt_lock); rcu_read_lock();
vif = &mrt->vif_table[vr.mifi]; vif = &mrt->vif_table[vr.mifi];
if (VIF_EXISTS(mrt, vr.mifi)) { if (VIF_EXISTS(mrt, vr.mifi)) {
vr.icount = vif->pkt_in; vr.icount = READ_ONCE(vif->pkt_in);
vr.ocount = vif->pkt_out; vr.ocount = READ_ONCE(vif->pkt_out);
vr.ibytes = vif->bytes_in; vr.ibytes = READ_ONCE(vif->bytes_in);
vr.obytes = vif->bytes_out; vr.obytes = READ_ONCE(vif->bytes_out);
read_unlock(&mrt_lock); rcu_read_unlock();
if (copy_to_user(arg, &vr, sizeof(vr))) if (copy_to_user(arg, &vr, sizeof(vr)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
read_unlock(&mrt_lock); rcu_read_unlock();
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
case SIOCGETSGCNT_IN6: case SIOCGETSGCNT_IN6:
if (copy_from_user(&sr, arg, sizeof(sr))) if (copy_from_user(&sr, arg, sizeof(sr)))
...@@ -2038,8 +2038,8 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt, ...@@ -2038,8 +2038,8 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
#ifdef CONFIG_IPV6_PIMSM_V2 #ifdef CONFIG_IPV6_PIMSM_V2
if (vif->flags & MIFF_REGISTER) { if (vif->flags & MIFF_REGISTER) {
vif->pkt_out++; WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1);
vif->bytes_out += skb->len; WRITE_ONCE(vif->bytes_out, vif->bytes_out + skb->len);
vif_dev->stats.tx_bytes += skb->len; vif_dev->stats.tx_bytes += skb->len;
vif_dev->stats.tx_packets++; vif_dev->stats.tx_packets++;
rcu_read_lock(); rcu_read_lock();
...@@ -2077,8 +2077,8 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt, ...@@ -2077,8 +2077,8 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
* result in receiving multiple packets. * result in receiving multiple packets.
*/ */
skb->dev = vif_dev; skb->dev = vif_dev;
vif->pkt_out++; WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1);
vif->bytes_out += skb->len; WRITE_ONCE(vif->bytes_out, vif->bytes_out + skb->len);
/* We are about to write */ /* We are about to write */
/* XXX: extension headers? */ /* XXX: extension headers? */
...@@ -2168,8 +2168,10 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt, ...@@ -2168,8 +2168,10 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
} }
forward: forward:
mrt->vif_table[vif].pkt_in++; WRITE_ONCE(mrt->vif_table[vif].pkt_in,
mrt->vif_table[vif].bytes_in += skb->len; mrt->vif_table[vif].pkt_in + 1);
WRITE_ONCE(mrt->vif_table[vif].bytes_in,
mrt->vif_table[vif].bytes_in + skb->len);
/* /*
* Forward the frame * Forward the frame
......
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