Re: [net-next v5 6/7] tuntap: add ioctl to attach or detach a file form tuntap device

2012-11-12 Thread Michael S. Tsirkin
On Thu, Nov 01, 2012 at 01:46:01PM +0800, Jason Wang wrote:
> Sometimes usespace may need to active/deactive a queue, this could be done by
> detaching and attaching a file from tuntap device.
> 
> This patch introduces a new ioctls - TUNSETQUEUE which could be used to do
> this. Flag IFF_ATTACH_QUEUE were introduced to do attaching while
> IFF_DETACH_QUEUE were introduced to do the detaching.
> 
> Signed-off-by: Jason Wang 
> ---
>  drivers/net/tun.c   |   56 --
>  include/uapi/linux/if_tun.h |3 ++
>  2 files changed, 51 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 2762c55..79b6f9e 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -195,6 +195,15 @@ static u16 tun_select_queue(struct net_device *dev, 
> struct sk_buff *skb)
>   return txq;
>  }
>  
> +static inline bool tun_not_capable(struct tun_struct *tun)
> +{
> + const struct cred *cred = current_cred();
> +
> + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
> +   (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
> + !capable(CAP_NET_ADMIN);
> +}
> +
>  static void tun_set_real_num_queues(struct tun_struct *tun)
>  {
>   netif_set_real_num_tx_queues(tun->dev, tun->numqueues);
> @@ -1310,8 +1319,6 @@ static int tun_set_iff(struct net *net, struct file 
> *file, struct ifreq *ifr)
>  
>   dev = __dev_get_by_name(net, ifr->ifr_name);
>   if (dev) {
> - const struct cred *cred = current_cred();
> -
>   if (ifr->ifr_flags & IFF_TUN_EXCL)
>   return -EBUSY;
>   if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == 
> _netdev_ops)
> @@ -1321,9 +1328,7 @@ static int tun_set_iff(struct net *net, struct file 
> *file, struct ifreq *ifr)
>   else
>   return -EINVAL;
>  
> - if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) 
> ||
> -  (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
> - !capable(CAP_NET_ADMIN))
> + if (tun_not_capable(tun))
>   return -EPERM;
>   err = security_tun_dev_attach(tfile->socket.sk);
>   if (err < 0)
> @@ -1530,6 +1535,40 @@ static void tun_set_sndbuf(struct tun_struct *tun)
>   }
>  }
>  
> +static int tun_set_queue(struct file *file, struct ifreq *ifr)
> +{
> + struct tun_file *tfile = file->private_data;
> + struct tun_struct *tun;
> + struct net_device *dev;
> + int ret = 0;
> +
> + rtnl_lock();
> +
> + if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
> + dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
> + if (!dev) {
> + ret = -EINVAL;
> + goto unlock;
> + }
> +
> + tun = netdev_priv(dev);
> + if (dev->netdev_ops != _netdev_ops &&
> + dev->netdev_ops != _netdev_ops)
> + ret = -EINVAL;
> + else if (tun_not_capable(tun))
> + ret = -EPERM;
> + else
> + ret = tun_attach(tun, file);

looks like we need to check 
security_tun_dev_attach here as well.
As the patch is in net-next now we need a patch on top for that.



> + } else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
> + __tun_detach(tfile, false);
> + else
> + ret = -EINVAL;
> +
> +unlock:
> + rtnl_unlock();
> + return ret;
> +}
> +
>  static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
>   unsigned long arg, int ifreq_len)
>  {
> @@ -1543,7 +1582,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
> int cmd,
>   int vnet_hdr_sz;
>   int ret;
>  
> - if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
> + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
>   if (copy_from_user(, argp, ifreq_len))
>   return -EFAULT;
>   } else {
> @@ -1554,9 +1593,10 @@ static long __tun_chr_ioctl(struct file *file, 
> unsigned int cmd,
>* This is needed because we never checked for invalid flags on
>* TUNSETIFF. */
>   return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
> - IFF_VNET_HDR,
> + IFF_VNET_HDR | IFF_MULTI_QUEUE,
>   (unsigned int __user*)argp);
> - }
> + } else if (cmd == TUNSETQUEUE)
> + return tun_set_queue(file, );
>  
>   ret = 0;
>   rtnl_lock();
> diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
> index 8ef3a87..958497a 100644
> --- a/include/uapi/linux/if_tun.h
> +++ b/include/uapi/linux/if_tun.h
> @@ -54,6 +54,7 @@
>  #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
>  #define TUNGETVNETHDRSZ _IOR('T', 215, int)
>  

Re: [net-next v5 6/7] tuntap: add ioctl to attach or detach a file form tuntap device

2012-11-12 Thread Michael S. Tsirkin
On Thu, Nov 01, 2012 at 01:46:01PM +0800, Jason Wang wrote:
 Sometimes usespace may need to active/deactive a queue, this could be done by
 detaching and attaching a file from tuntap device.
 
 This patch introduces a new ioctls - TUNSETQUEUE which could be used to do
 this. Flag IFF_ATTACH_QUEUE were introduced to do attaching while
 IFF_DETACH_QUEUE were introduced to do the detaching.
 
 Signed-off-by: Jason Wang jasow...@redhat.com
 ---
  drivers/net/tun.c   |   56 --
  include/uapi/linux/if_tun.h |3 ++
  2 files changed, 51 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/net/tun.c b/drivers/net/tun.c
 index 2762c55..79b6f9e 100644
 --- a/drivers/net/tun.c
 +++ b/drivers/net/tun.c
 @@ -195,6 +195,15 @@ static u16 tun_select_queue(struct net_device *dev, 
 struct sk_buff *skb)
   return txq;
  }
  
 +static inline bool tun_not_capable(struct tun_struct *tun)
 +{
 + const struct cred *cred = current_cred();
 +
 + return ((uid_valid(tun-owner)  !uid_eq(cred-euid, tun-owner)) ||
 +   (gid_valid(tun-group)  !in_egroup_p(tun-group))) 
 + !capable(CAP_NET_ADMIN);
 +}
 +
  static void tun_set_real_num_queues(struct tun_struct *tun)
  {
   netif_set_real_num_tx_queues(tun-dev, tun-numqueues);
 @@ -1310,8 +1319,6 @@ static int tun_set_iff(struct net *net, struct file 
 *file, struct ifreq *ifr)
  
   dev = __dev_get_by_name(net, ifr-ifr_name);
   if (dev) {
 - const struct cred *cred = current_cred();
 -
   if (ifr-ifr_flags  IFF_TUN_EXCL)
   return -EBUSY;
   if ((ifr-ifr_flags  IFF_TUN)  dev-netdev_ops == 
 tun_netdev_ops)
 @@ -1321,9 +1328,7 @@ static int tun_set_iff(struct net *net, struct file 
 *file, struct ifreq *ifr)
   else
   return -EINVAL;
  
 - if (((uid_valid(tun-owner)  !uid_eq(cred-euid, tun-owner)) 
 ||
 -  (gid_valid(tun-group)  !in_egroup_p(tun-group))) 
 - !capable(CAP_NET_ADMIN))
 + if (tun_not_capable(tun))
   return -EPERM;
   err = security_tun_dev_attach(tfile-socket.sk);
   if (err  0)
 @@ -1530,6 +1535,40 @@ static void tun_set_sndbuf(struct tun_struct *tun)
   }
  }
  
 +static int tun_set_queue(struct file *file, struct ifreq *ifr)
 +{
 + struct tun_file *tfile = file-private_data;
 + struct tun_struct *tun;
 + struct net_device *dev;
 + int ret = 0;
 +
 + rtnl_lock();
 +
 + if (ifr-ifr_flags  IFF_ATTACH_QUEUE) {
 + dev = __dev_get_by_name(tfile-net, ifr-ifr_name);
 + if (!dev) {
 + ret = -EINVAL;
 + goto unlock;
 + }
 +
 + tun = netdev_priv(dev);
 + if (dev-netdev_ops != tap_netdev_ops 
 + dev-netdev_ops != tun_netdev_ops)
 + ret = -EINVAL;
 + else if (tun_not_capable(tun))
 + ret = -EPERM;
 + else
 + ret = tun_attach(tun, file);

looks like we need to check 
security_tun_dev_attach here as well.
As the patch is in net-next now we need a patch on top for that.



 + } else if (ifr-ifr_flags  IFF_DETACH_QUEUE)
 + __tun_detach(tfile, false);
 + else
 + ret = -EINVAL;
 +
 +unlock:
 + rtnl_unlock();
 + return ret;
 +}
 +
  static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
   unsigned long arg, int ifreq_len)
  {
 @@ -1543,7 +1582,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
 int cmd,
   int vnet_hdr_sz;
   int ret;
  
 - if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
 + if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
   if (copy_from_user(ifr, argp, ifreq_len))
   return -EFAULT;
   } else {
 @@ -1554,9 +1593,10 @@ static long __tun_chr_ioctl(struct file *file, 
 unsigned int cmd,
* This is needed because we never checked for invalid flags on
* TUNSETIFF. */
   return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
 - IFF_VNET_HDR,
 + IFF_VNET_HDR | IFF_MULTI_QUEUE,
   (unsigned int __user*)argp);
 - }
 + } else if (cmd == TUNSETQUEUE)
 + return tun_set_queue(file, ifr);
  
   ret = 0;
   rtnl_lock();
 diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
 index 8ef3a87..958497a 100644
 --- a/include/uapi/linux/if_tun.h
 +++ b/include/uapi/linux/if_tun.h
 @@ -54,6 +54,7 @@
  #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
  #define TUNGETVNETHDRSZ _IOR('T', 215, int)
  #define TUNSETVNETHDRSZ _IOW('T', 216, int)
 +#define TUNSETQUEUE  _IOW('T', 217, int)
  
  /* TUNSETIFF ifr flags */
  #define IFF_TUN

[net-next v5 6/7] tuntap: add ioctl to attach or detach a file form tuntap device

2012-10-31 Thread Jason Wang
Sometimes usespace may need to active/deactive a queue, this could be done by
detaching and attaching a file from tuntap device.

This patch introduces a new ioctls - TUNSETQUEUE which could be used to do
this. Flag IFF_ATTACH_QUEUE were introduced to do attaching while
IFF_DETACH_QUEUE were introduced to do the detaching.

Signed-off-by: Jason Wang 
---
 drivers/net/tun.c   |   56 --
 include/uapi/linux/if_tun.h |3 ++
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2762c55..79b6f9e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -195,6 +195,15 @@ static u16 tun_select_queue(struct net_device *dev, struct 
sk_buff *skb)
return txq;
 }
 
+static inline bool tun_not_capable(struct tun_struct *tun)
+{
+   const struct cred *cred = current_cred();
+
+   return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
+ (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
+   !capable(CAP_NET_ADMIN);
+}
+
 static void tun_set_real_num_queues(struct tun_struct *tun)
 {
netif_set_real_num_tx_queues(tun->dev, tun->numqueues);
@@ -1310,8 +1319,6 @@ static int tun_set_iff(struct net *net, struct file 
*file, struct ifreq *ifr)
 
dev = __dev_get_by_name(net, ifr->ifr_name);
if (dev) {
-   const struct cred *cred = current_cred();
-
if (ifr->ifr_flags & IFF_TUN_EXCL)
return -EBUSY;
if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == 
_netdev_ops)
@@ -1321,9 +1328,7 @@ static int tun_set_iff(struct net *net, struct file 
*file, struct ifreq *ifr)
else
return -EINVAL;
 
-   if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) 
||
-(gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
-   !capable(CAP_NET_ADMIN))
+   if (tun_not_capable(tun))
return -EPERM;
err = security_tun_dev_attach(tfile->socket.sk);
if (err < 0)
@@ -1530,6 +1535,40 @@ static void tun_set_sndbuf(struct tun_struct *tun)
}
 }
 
+static int tun_set_queue(struct file *file, struct ifreq *ifr)
+{
+   struct tun_file *tfile = file->private_data;
+   struct tun_struct *tun;
+   struct net_device *dev;
+   int ret = 0;
+
+   rtnl_lock();
+
+   if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
+   dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
+   if (!dev) {
+   ret = -EINVAL;
+   goto unlock;
+   }
+
+   tun = netdev_priv(dev);
+   if (dev->netdev_ops != _netdev_ops &&
+   dev->netdev_ops != _netdev_ops)
+   ret = -EINVAL;
+   else if (tun_not_capable(tun))
+   ret = -EPERM;
+   else
+   ret = tun_attach(tun, file);
+   } else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
+   __tun_detach(tfile, false);
+   else
+   ret = -EINVAL;
+
+unlock:
+   rtnl_unlock();
+   return ret;
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
unsigned long arg, int ifreq_len)
 {
@@ -1543,7 +1582,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
int cmd,
int vnet_hdr_sz;
int ret;
 
-   if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
+   if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
if (copy_from_user(, argp, ifreq_len))
return -EFAULT;
} else {
@@ -1554,9 +1593,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
int cmd,
 * This is needed because we never checked for invalid flags on
 * TUNSETIFF. */
return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-   IFF_VNET_HDR,
+   IFF_VNET_HDR | IFF_MULTI_QUEUE,
(unsigned int __user*)argp);
-   }
+   } else if (cmd == TUNSETQUEUE)
+   return tun_set_queue(file, );
 
ret = 0;
rtnl_lock();
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 8ef3a87..958497a 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -54,6 +54,7 @@
 #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
+#define TUNSETQUEUE  _IOW('T', 217, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN0x0001
@@ -63,6 +64,8 @@
 #define IFF_VNET_HDR   0x4000
 #define IFF_TUN_EXCL   0x8000
 #define IFF_MULTI_QUEUE 0x0100
+#define IFF_ATTACH_QUEUE 0x0200
+#define IFF_DETACH_QUEUE 

[net-next v5 6/7] tuntap: add ioctl to attach or detach a file form tuntap device

2012-10-31 Thread Jason Wang
Sometimes usespace may need to active/deactive a queue, this could be done by
detaching and attaching a file from tuntap device.

This patch introduces a new ioctls - TUNSETQUEUE which could be used to do
this. Flag IFF_ATTACH_QUEUE were introduced to do attaching while
IFF_DETACH_QUEUE were introduced to do the detaching.

Signed-off-by: Jason Wang jasow...@redhat.com
---
 drivers/net/tun.c   |   56 --
 include/uapi/linux/if_tun.h |3 ++
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2762c55..79b6f9e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -195,6 +195,15 @@ static u16 tun_select_queue(struct net_device *dev, struct 
sk_buff *skb)
return txq;
 }
 
+static inline bool tun_not_capable(struct tun_struct *tun)
+{
+   const struct cred *cred = current_cred();
+
+   return ((uid_valid(tun-owner)  !uid_eq(cred-euid, tun-owner)) ||
+ (gid_valid(tun-group)  !in_egroup_p(tun-group))) 
+   !capable(CAP_NET_ADMIN);
+}
+
 static void tun_set_real_num_queues(struct tun_struct *tun)
 {
netif_set_real_num_tx_queues(tun-dev, tun-numqueues);
@@ -1310,8 +1319,6 @@ static int tun_set_iff(struct net *net, struct file 
*file, struct ifreq *ifr)
 
dev = __dev_get_by_name(net, ifr-ifr_name);
if (dev) {
-   const struct cred *cred = current_cred();
-
if (ifr-ifr_flags  IFF_TUN_EXCL)
return -EBUSY;
if ((ifr-ifr_flags  IFF_TUN)  dev-netdev_ops == 
tun_netdev_ops)
@@ -1321,9 +1328,7 @@ static int tun_set_iff(struct net *net, struct file 
*file, struct ifreq *ifr)
else
return -EINVAL;
 
-   if (((uid_valid(tun-owner)  !uid_eq(cred-euid, tun-owner)) 
||
-(gid_valid(tun-group)  !in_egroup_p(tun-group))) 
-   !capable(CAP_NET_ADMIN))
+   if (tun_not_capable(tun))
return -EPERM;
err = security_tun_dev_attach(tfile-socket.sk);
if (err  0)
@@ -1530,6 +1535,40 @@ static void tun_set_sndbuf(struct tun_struct *tun)
}
 }
 
+static int tun_set_queue(struct file *file, struct ifreq *ifr)
+{
+   struct tun_file *tfile = file-private_data;
+   struct tun_struct *tun;
+   struct net_device *dev;
+   int ret = 0;
+
+   rtnl_lock();
+
+   if (ifr-ifr_flags  IFF_ATTACH_QUEUE) {
+   dev = __dev_get_by_name(tfile-net, ifr-ifr_name);
+   if (!dev) {
+   ret = -EINVAL;
+   goto unlock;
+   }
+
+   tun = netdev_priv(dev);
+   if (dev-netdev_ops != tap_netdev_ops 
+   dev-netdev_ops != tun_netdev_ops)
+   ret = -EINVAL;
+   else if (tun_not_capable(tun))
+   ret = -EPERM;
+   else
+   ret = tun_attach(tun, file);
+   } else if (ifr-ifr_flags  IFF_DETACH_QUEUE)
+   __tun_detach(tfile, false);
+   else
+   ret = -EINVAL;
+
+unlock:
+   rtnl_unlock();
+   return ret;
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
unsigned long arg, int ifreq_len)
 {
@@ -1543,7 +1582,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
int cmd,
int vnet_hdr_sz;
int ret;
 
-   if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
+   if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
if (copy_from_user(ifr, argp, ifreq_len))
return -EFAULT;
} else {
@@ -1554,9 +1593,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned 
int cmd,
 * This is needed because we never checked for invalid flags on
 * TUNSETIFF. */
return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-   IFF_VNET_HDR,
+   IFF_VNET_HDR | IFF_MULTI_QUEUE,
(unsigned int __user*)argp);
-   }
+   } else if (cmd == TUNSETQUEUE)
+   return tun_set_queue(file, ifr);
 
ret = 0;
rtnl_lock();
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 8ef3a87..958497a 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -54,6 +54,7 @@
 #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
+#define TUNSETQUEUE  _IOW('T', 217, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN0x0001
@@ -63,6 +64,8 @@
 #define IFF_VNET_HDR   0x4000
 #define IFF_TUN_EXCL   0x8000
 #define IFF_MULTI_QUEUE 0x0100
+#define IFF_ATTACH_QUEUE 0x0200
+#define IFF_DETACH_QUEUE 0x0400
 
 /*