diff options
author | David S. Miller <davem@davemloft.net> | 2017-02-06 22:41:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-02-06 22:41:27 -0500 |
commit | 432d4f8ab03527958294ad5e539acaebfc4625e3 (patch) | |
tree | 9acf1060c120551d70a9b31fc8075bf1d834eb98 | |
parent | ccf7abb93af09ad0868ae9033d1ca8108bdaec82 (diff) | |
parent | 837585a5375c38d40361cfe64e6fd11e1addb936 (diff) |
Merge branch 'read-vnet_hdr_sz-once'
Willem de Bruijn says:
====================
read vnet_hdr_sz once
Tuntap devices allow concurrent use and update of field vnet_hdr_sz.
Read the field once to avoid TOCTOU.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/macvtap.c | 4 | ||||
-rw-r--r-- | drivers/net/tun.c | 10 |
2 files changed, 8 insertions, 6 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 402618565838..c27011bbe30c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -681,7 +681,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
681 | size_t linear; | 681 | size_t linear; |
682 | 682 | ||
683 | if (q->flags & IFF_VNET_HDR) { | 683 | if (q->flags & IFF_VNET_HDR) { |
684 | vnet_hdr_len = q->vnet_hdr_sz; | 684 | vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); |
685 | 685 | ||
686 | err = -EINVAL; | 686 | err = -EINVAL; |
687 | if (len < vnet_hdr_len) | 687 | if (len < vnet_hdr_len) |
@@ -820,7 +820,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
820 | 820 | ||
821 | if (q->flags & IFF_VNET_HDR) { | 821 | if (q->flags & IFF_VNET_HDR) { |
822 | struct virtio_net_hdr vnet_hdr; | 822 | struct virtio_net_hdr vnet_hdr; |
823 | vnet_hdr_len = q->vnet_hdr_sz; | 823 | vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); |
824 | if (iov_iter_count(iter) < vnet_hdr_len) | 824 | if (iov_iter_count(iter) < vnet_hdr_len) |
825 | return -EINVAL; | 825 | return -EINVAL; |
826 | 826 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2cd10b26b650..bfabe180053e 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1170,9 +1170,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | if (tun->flags & IFF_VNET_HDR) { | 1172 | if (tun->flags & IFF_VNET_HDR) { |
1173 | if (len < tun->vnet_hdr_sz) | 1173 | int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); |
1174 | |||
1175 | if (len < vnet_hdr_sz) | ||
1174 | return -EINVAL; | 1176 | return -EINVAL; |
1175 | len -= tun->vnet_hdr_sz; | 1177 | len -= vnet_hdr_sz; |
1176 | 1178 | ||
1177 | if (!copy_from_iter_full(&gso, sizeof(gso), from)) | 1179 | if (!copy_from_iter_full(&gso, sizeof(gso), from)) |
1178 | return -EFAULT; | 1180 | return -EFAULT; |
@@ -1183,7 +1185,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1183 | 1185 | ||
1184 | if (tun16_to_cpu(tun, gso.hdr_len) > len) | 1186 | if (tun16_to_cpu(tun, gso.hdr_len) > len) |
1185 | return -EINVAL; | 1187 | return -EINVAL; |
1186 | iov_iter_advance(from, tun->vnet_hdr_sz - sizeof(gso)); | 1188 | iov_iter_advance(from, vnet_hdr_sz - sizeof(gso)); |
1187 | } | 1189 | } |
1188 | 1190 | ||
1189 | if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) { | 1191 | if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP) { |
@@ -1335,7 +1337,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, | |||
1335 | vlan_hlen = VLAN_HLEN; | 1337 | vlan_hlen = VLAN_HLEN; |
1336 | 1338 | ||
1337 | if (tun->flags & IFF_VNET_HDR) | 1339 | if (tun->flags & IFF_VNET_HDR) |
1338 | vnet_hdr_sz = tun->vnet_hdr_sz; | 1340 | vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); |
1339 | 1341 | ||
1340 | total = skb->len + vlan_hlen + vnet_hdr_sz; | 1342 | total = skb->len + vlan_hlen + vnet_hdr_sz; |
1341 | 1343 | ||