aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/tun.c32
-rw-r--r--include/linux/if_tun.h2
2 files changed, 30 insertions, 4 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e525a6cf558..6b150c072a4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -110,6 +110,9 @@ struct tun_struct {
110 struct tap_filter txflt; 110 struct tap_filter txflt;
111 struct socket socket; 111 struct socket socket;
112 struct socket_wq wq; 112 struct socket_wq wq;
113
114 int vnet_hdr_sz;
115
113#ifdef TUN_DEBUG 116#ifdef TUN_DEBUG
114 int debug; 117 int debug;
115#endif 118#endif
@@ -563,7 +566,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
563 } 566 }
564 567
565 if (tun->flags & TUN_VNET_HDR) { 568 if (tun->flags & TUN_VNET_HDR) {
566 if ((len -= sizeof(gso)) > count) 569 if ((len -= tun->vnet_hdr_sz) > count)
567 return -EINVAL; 570 return -EINVAL;
568 571
569 if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) 572 if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso)))
@@ -575,7 +578,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
575 578
576 if (gso.hdr_len > len) 579 if (gso.hdr_len > len)
577 return -EINVAL; 580 return -EINVAL;
578 offset += sizeof(gso); 581 offset += tun->vnet_hdr_sz;
579 } 582 }
580 583
581 if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { 584 if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) {
@@ -718,7 +721,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
718 721
719 if (tun->flags & TUN_VNET_HDR) { 722 if (tun->flags & TUN_VNET_HDR) {
720 struct virtio_net_hdr gso = { 0 }; /* no info leak */ 723 struct virtio_net_hdr gso = { 0 }; /* no info leak */
721 if ((len -= sizeof(gso)) < 0) 724 if ((len -= tun->vnet_hdr_sz) < 0)
722 return -EINVAL; 725 return -EINVAL;
723 726
724 if (skb_is_gso(skb)) { 727 if (skb_is_gso(skb)) {
@@ -749,7 +752,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
749 if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, 752 if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
750 sizeof(gso)))) 753 sizeof(gso))))
751 return -EFAULT; 754 return -EFAULT;
752 total += sizeof(gso); 755 total += tun->vnet_hdr_sz;
753 } 756 }
754 757
755 len = min_t(int, skb->len, len); 758 len = min_t(int, skb->len, len);
@@ -1035,6 +1038,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1035 tun->dev = dev; 1038 tun->dev = dev;
1036 tun->flags = flags; 1039 tun->flags = flags;
1037 tun->txflt.count = 0; 1040 tun->txflt.count = 0;
1041 tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
1038 1042
1039 err = -ENOMEM; 1043 err = -ENOMEM;
1040 sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); 1044 sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
@@ -1177,6 +1181,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1177 struct sock_fprog fprog; 1181 struct sock_fprog fprog;
1178 struct ifreq ifr; 1182 struct ifreq ifr;
1179 int sndbuf; 1183 int sndbuf;
1184 int vnet_hdr_sz;
1180 int ret; 1185 int ret;
1181 1186
1182 if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) 1187 if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
@@ -1322,6 +1327,25 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
1322 tun->socket.sk->sk_sndbuf = sndbuf; 1327 tun->socket.sk->sk_sndbuf = sndbuf;
1323 break; 1328 break;
1324 1329
1330 case TUNGETVNETHDRSZ:
1331 vnet_hdr_sz = tun->vnet_hdr_sz;
1332 if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz)))
1333 ret = -EFAULT;
1334 break;
1335
1336 case TUNSETVNETHDRSZ:
1337 if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) {
1338 ret = -EFAULT;
1339 break;
1340 }
1341 if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) {
1342 ret = -EINVAL;
1343 break;
1344 }
1345
1346 tun->vnet_hdr_sz = vnet_hdr_sz;
1347 break;
1348
1325 case TUNATTACHFILTER: 1349 case TUNATTACHFILTER:
1326 /* Can be set only for TAPs */ 1350 /* Can be set only for TAPs */
1327 ret = -EINVAL; 1351 ret = -EINVAL;
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 1350a246893..06b1829731f 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -51,6 +51,8 @@
51#define TUNSETSNDBUF _IOW('T', 212, int) 51#define TUNSETSNDBUF _IOW('T', 212, int)
52#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) 52#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog)
53#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) 53#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
54#define TUNGETVNETHDRSZ _IOR('T', 215, int)
55#define TUNSETVNETHDRSZ _IOW('T', 216, int)
54 56
55/* TUNSETIFF ifr flags */ 57/* TUNSETIFF ifr flags */
56#define IFF_TUN 0x0001 58#define IFF_TUN 0x0001