aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-02-06 22:41:27 -0500
committerDavid S. Miller <davem@davemloft.net>2017-02-06 22:41:27 -0500
commit432d4f8ab03527958294ad5e539acaebfc4625e3 (patch)
tree9acf1060c120551d70a9b31fc8075bf1d834eb98
parentccf7abb93af09ad0868ae9033d1ca8108bdaec82 (diff)
parent837585a5375c38d40361cfe64e6fd11e1addb936 (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.c4
-rw-r--r--drivers/net/tun.c10
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