Loading drivers/net/macvtap.c +23 −4 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct macvtap_queue { struct sock sk; struct sock sk; struct socket sock; struct socket sock; struct socket_wq wq; struct socket_wq wq; int vnet_hdr_sz; struct macvlan_dev *vlan; struct macvlan_dev *vlan; struct file *file; struct file *file; unsigned int flags; unsigned int flags; Loading Loading @@ -285,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file) sock_init_data(&q->sock, &q->sk); sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; q->sk.sk_write_space = macvtap_sock_write_space; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->vnet_hdr_sz = sizeof(struct virtio_net_hdr); err = macvtap_set_queue(dev, file, q); err = macvtap_set_queue(dev, file, q); if (err) if (err) Loading Loading @@ -445,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, int vnet_hdr_len = 0; int vnet_hdr_len = 0; if (q->flags & IFF_VNET_HDR) { if (q->flags & IFF_VNET_HDR) { vnet_hdr_len = sizeof(vnet_hdr); vnet_hdr_len = q->vnet_hdr_sz; err = -EINVAL; err = -EINVAL; if ((len -= vnet_hdr_len) < 0) if ((len -= vnet_hdr_len) < 0) goto err; goto err; err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, vnet_hdr_len); sizeof(vnet_hdr)); if (err < 0) if (err < 0) goto err; goto err; if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && Loading Loading @@ -534,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (q->flags & IFF_VNET_HDR) { if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; struct virtio_net_hdr vnet_hdr; vnet_hdr_len = sizeof (vnet_hdr); vnet_hdr_len = q->vnet_hdr_sz; if ((len -= vnet_hdr_len) < 0) if ((len -= vnet_hdr_len) < 0) return -EINVAL; return -EINVAL; Loading @@ -542,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (ret) if (ret) return ret; return ret; if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; return -EFAULT; } } Loading Loading @@ -627,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, struct ifreq __user *ifr = argp; struct ifreq __user *ifr = argp; unsigned int __user *up = argp; unsigned int __user *up = argp; unsigned int u; unsigned int u; int __user *sp = argp; int s; int ret; int ret; switch (cmd) { switch (cmd) { Loading Loading @@ -672,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, q->sk.sk_sndbuf = u; q->sk.sk_sndbuf = u; return 0; return 0; case TUNGETVNETHDRSZ: s = q->vnet_hdr_sz; if (put_user(s, sp)) return -EFAULT; return 0; case TUNSETVNETHDRSZ: if (get_user(s, sp)) return -EFAULT; if (s < (int)sizeof(struct virtio_net_hdr)) return -EINVAL; q->vnet_hdr_sz = s; return 0; case TUNSETOFFLOAD: case TUNSETOFFLOAD: /* let the user check for future flags */ /* let the user check for future flags */ if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | Loading drivers/net/tun.c +28 −4 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,9 @@ struct tun_struct { struct tap_filter txflt; struct tap_filter txflt; struct socket socket; struct socket socket; struct socket_wq wq; struct socket_wq wq; int vnet_hdr_sz; #ifdef TUN_DEBUG #ifdef TUN_DEBUG int debug; int debug; #endif #endif Loading Loading @@ -563,7 +566,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, } } if (tun->flags & TUN_VNET_HDR) { if (tun->flags & TUN_VNET_HDR) { if ((len -= sizeof(gso)) > count) if ((len -= tun->vnet_hdr_sz) > count) return -EINVAL; return -EINVAL; if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) Loading @@ -575,7 +578,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, if (gso.hdr_len > len) if (gso.hdr_len > len) return -EINVAL; return -EINVAL; offset += sizeof(gso); offset += tun->vnet_hdr_sz; } } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { Loading Loading @@ -718,7 +721,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, if (tun->flags & TUN_VNET_HDR) { if (tun->flags & TUN_VNET_HDR) { struct virtio_net_hdr gso = { 0 }; /* no info leak */ struct virtio_net_hdr gso = { 0 }; /* no info leak */ if ((len -= sizeof(gso)) < 0) if ((len -= tun->vnet_hdr_sz) < 0) return -EINVAL; return -EINVAL; if (skb_is_gso(skb)) { if (skb_is_gso(skb)) { Loading Loading @@ -749,7 +752,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, sizeof(gso)))) sizeof(gso)))) return -EFAULT; return -EFAULT; total += sizeof(gso); total += tun->vnet_hdr_sz; } } len = min_t(int, skb->len, len); len = min_t(int, skb->len, len); Loading Loading @@ -1035,6 +1038,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->dev = dev; tun->dev = dev; tun->flags = flags; tun->flags = flags; tun->txflt.count = 0; tun->txflt.count = 0; tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); err = -ENOMEM; err = -ENOMEM; sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); Loading Loading @@ -1177,6 +1181,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, struct sock_fprog fprog; struct sock_fprog fprog; struct ifreq ifr; struct ifreq ifr; int sndbuf; int sndbuf; int vnet_hdr_sz; int ret; int ret; if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) Loading Loading @@ -1322,6 +1327,25 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, tun->socket.sk->sk_sndbuf = sndbuf; tun->socket.sk->sk_sndbuf = sndbuf; break; break; case TUNGETVNETHDRSZ: vnet_hdr_sz = tun->vnet_hdr_sz; if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) ret = -EFAULT; break; case TUNSETVNETHDRSZ: if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { ret = -EFAULT; break; } if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { ret = -EINVAL; break; } tun->vnet_hdr_sz = vnet_hdr_sz; break; case TUNATTACHFILTER: case TUNATTACHFILTER: /* Can be set only for TAPs */ /* Can be set only for TAPs */ ret = -EINVAL; ret = -EINVAL; Loading include/linux/if_tun.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -51,6 +51,8 @@ #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) #define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) #define TUNGETVNETHDRSZ _IOR('T', 215, int) #define TUNSETVNETHDRSZ _IOW('T', 216, int) /* TUNSETIFF ifr flags */ /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TUN 0x0001 Loading Loading
drivers/net/macvtap.c +23 −4 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ struct macvtap_queue { struct sock sk; struct sock sk; struct socket sock; struct socket sock; struct socket_wq wq; struct socket_wq wq; int vnet_hdr_sz; struct macvlan_dev *vlan; struct macvlan_dev *vlan; struct file *file; struct file *file; unsigned int flags; unsigned int flags; Loading Loading @@ -285,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file) sock_init_data(&q->sock, &q->sk); sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; q->sk.sk_write_space = macvtap_sock_write_space; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->vnet_hdr_sz = sizeof(struct virtio_net_hdr); err = macvtap_set_queue(dev, file, q); err = macvtap_set_queue(dev, file, q); if (err) if (err) Loading Loading @@ -445,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, int vnet_hdr_len = 0; int vnet_hdr_len = 0; if (q->flags & IFF_VNET_HDR) { if (q->flags & IFF_VNET_HDR) { vnet_hdr_len = sizeof(vnet_hdr); vnet_hdr_len = q->vnet_hdr_sz; err = -EINVAL; err = -EINVAL; if ((len -= vnet_hdr_len) < 0) if ((len -= vnet_hdr_len) < 0) goto err; goto err; err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, vnet_hdr_len); sizeof(vnet_hdr)); if (err < 0) if (err < 0) goto err; goto err; if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && Loading Loading @@ -534,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (q->flags & IFF_VNET_HDR) { if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; struct virtio_net_hdr vnet_hdr; vnet_hdr_len = sizeof (vnet_hdr); vnet_hdr_len = q->vnet_hdr_sz; if ((len -= vnet_hdr_len) < 0) if ((len -= vnet_hdr_len) < 0) return -EINVAL; return -EINVAL; Loading @@ -542,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (ret) if (ret) return ret; return ret; if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; return -EFAULT; } } Loading Loading @@ -627,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, struct ifreq __user *ifr = argp; struct ifreq __user *ifr = argp; unsigned int __user *up = argp; unsigned int __user *up = argp; unsigned int u; unsigned int u; int __user *sp = argp; int s; int ret; int ret; switch (cmd) { switch (cmd) { Loading Loading @@ -672,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, q->sk.sk_sndbuf = u; q->sk.sk_sndbuf = u; return 0; return 0; case TUNGETVNETHDRSZ: s = q->vnet_hdr_sz; if (put_user(s, sp)) return -EFAULT; return 0; case TUNSETVNETHDRSZ: if (get_user(s, sp)) return -EFAULT; if (s < (int)sizeof(struct virtio_net_hdr)) return -EINVAL; q->vnet_hdr_sz = s; return 0; case TUNSETOFFLOAD: case TUNSETOFFLOAD: /* let the user check for future flags */ /* let the user check for future flags */ if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | Loading
drivers/net/tun.c +28 −4 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,9 @@ struct tun_struct { struct tap_filter txflt; struct tap_filter txflt; struct socket socket; struct socket socket; struct socket_wq wq; struct socket_wq wq; int vnet_hdr_sz; #ifdef TUN_DEBUG #ifdef TUN_DEBUG int debug; int debug; #endif #endif Loading Loading @@ -563,7 +566,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, } } if (tun->flags & TUN_VNET_HDR) { if (tun->flags & TUN_VNET_HDR) { if ((len -= sizeof(gso)) > count) if ((len -= tun->vnet_hdr_sz) > count) return -EINVAL; return -EINVAL; if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) Loading @@ -575,7 +578,7 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, if (gso.hdr_len > len) if (gso.hdr_len > len) return -EINVAL; return -EINVAL; offset += sizeof(gso); offset += tun->vnet_hdr_sz; } } if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { Loading Loading @@ -718,7 +721,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, if (tun->flags & TUN_VNET_HDR) { if (tun->flags & TUN_VNET_HDR) { struct virtio_net_hdr gso = { 0 }; /* no info leak */ struct virtio_net_hdr gso = { 0 }; /* no info leak */ if ((len -= sizeof(gso)) < 0) if ((len -= tun->vnet_hdr_sz) < 0) return -EINVAL; return -EINVAL; if (skb_is_gso(skb)) { if (skb_is_gso(skb)) { Loading Loading @@ -749,7 +752,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total, sizeof(gso)))) sizeof(gso)))) return -EFAULT; return -EFAULT; total += sizeof(gso); total += tun->vnet_hdr_sz; } } len = min_t(int, skb->len, len); len = min_t(int, skb->len, len); Loading Loading @@ -1035,6 +1038,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->dev = dev; tun->dev = dev; tun->flags = flags; tun->flags = flags; tun->txflt.count = 0; tun->txflt.count = 0; tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); err = -ENOMEM; err = -ENOMEM; sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto); Loading Loading @@ -1177,6 +1181,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, struct sock_fprog fprog; struct sock_fprog fprog; struct ifreq ifr; struct ifreq ifr; int sndbuf; int sndbuf; int vnet_hdr_sz; int ret; int ret; if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) Loading Loading @@ -1322,6 +1327,25 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, tun->socket.sk->sk_sndbuf = sndbuf; tun->socket.sk->sk_sndbuf = sndbuf; break; break; case TUNGETVNETHDRSZ: vnet_hdr_sz = tun->vnet_hdr_sz; if (copy_to_user(argp, &vnet_hdr_sz, sizeof(vnet_hdr_sz))) ret = -EFAULT; break; case TUNSETVNETHDRSZ: if (copy_from_user(&vnet_hdr_sz, argp, sizeof(vnet_hdr_sz))) { ret = -EFAULT; break; } if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { ret = -EINVAL; break; } tun->vnet_hdr_sz = vnet_hdr_sz; break; case TUNATTACHFILTER: case TUNATTACHFILTER: /* Can be set only for TAPs */ /* Can be set only for TAPs */ ret = -EINVAL; ret = -EINVAL; Loading
include/linux/if_tun.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -51,6 +51,8 @@ #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) #define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) #define TUNGETVNETHDRSZ _IOR('T', 215, int) #define TUNSETVNETHDRSZ _IOW('T', 216, int) /* TUNSETIFF ifr flags */ /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TUN 0x0001 Loading