userns: Convert tun/tap to use kuid and kgid where appropriate
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 8 Feb 2012 00:48:55 +0000 (16:48 -0800)
committerEric W. Biederman <ebiederm@xmission.com>
Wed, 15 Aug 2012 04:55:31 +0000 (21:55 -0700)
Cc: Maxim Krasnyansky <maxk@qualcomm.com>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
drivers/net/tun.c
init/Kconfig

index 926d4db5cb384f2de6df5ae871d0ec6171c6fe7d..a9bd9f384f5fbb3c2fb3faf19526d7b49924fabc 100644 (file)
@@ -120,8 +120,8 @@ struct tun_sock;
 struct tun_struct {
        struct tun_file         *tfile;
        unsigned int            flags;
-       uid_t                   owner;
-       gid_t                   group;
+       kuid_t                  owner;
+       kgid_t                  group;
 
        struct net_device       *dev;
        netdev_features_t       set_features;
@@ -1032,8 +1032,8 @@ static void tun_setup(struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
 
-       tun->owner = -1;
-       tun->group = -1;
+       tun->owner = INVALID_UID;
+       tun->group = INVALID_GID;
 
        dev->ethtool_ops = &tun_ethtool_ops;
        dev->destructor = tun_free_netdev;
@@ -1156,14 +1156,20 @@ static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
                              char *buf)
 {
        struct tun_struct *tun = netdev_priv(to_net_dev(dev));
-       return sprintf(buf, "%d\n", tun->owner);
+       return uid_valid(tun->owner)?
+               sprintf(buf, "%u\n",
+                       from_kuid_munged(current_user_ns(), tun->owner)):
+               sprintf(buf, "-1\n");
 }
 
 static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
                              char *buf)
 {
        struct tun_struct *tun = netdev_priv(to_net_dev(dev));
-       return sprintf(buf, "%d\n", tun->group);
+       return gid_valid(tun->group) ?
+               sprintf(buf, "%u\n",
+                       from_kgid_munged(current_user_ns(), tun->group)):
+               sprintf(buf, "-1\n");
 }
 
 static DEVICE_ATTR(tun_flags, 0444, tun_show_flags, NULL);
@@ -1190,8 +1196,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                else
                        return -EINVAL;
 
-               if (((tun->owner != -1 && cred->euid != tun->owner) ||
-                    (tun->group != -1 && !in_egroup_p(tun->group))) &&
+               if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
+                    (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
                    !capable(CAP_NET_ADMIN))
                        return -EPERM;
                err = security_tun_dev_attach(tun->socket.sk);
@@ -1375,6 +1381,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
        void __user* argp = (void __user*)arg;
        struct sock_fprog fprog;
        struct ifreq ifr;
+       kuid_t owner;
+       kgid_t group;
        int sndbuf;
        int vnet_hdr_sz;
        int ret;
@@ -1448,16 +1456,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 
        case TUNSETOWNER:
                /* Set owner of the device */
-               tun->owner = (uid_t) arg;
-
-               tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->owner);
+               owner = make_kuid(current_user_ns(), arg);
+               if (!uid_valid(owner)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               tun->owner = owner;
+               tun_debug(KERN_INFO, tun, "owner set to %d\n",
+                         from_kuid(&init_user_ns, tun->owner));
                break;
 
        case TUNSETGROUP:
                /* Set group of the device */
-               tun->group= (gid_t) arg;
-
-               tun_debug(KERN_INFO, tun, "group set to %d\n", tun->group);
+               group = make_kgid(current_user_ns(), arg);
+               if (!gid_valid(group)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               tun->group = group;
+               tun_debug(KERN_INFO, tun, "group set to %d\n",
+                         from_kgid(&init_user_ns, tun->group));
                break;
 
        case TUNSETLINK:
index eac23a6fa2369fa5603bc5331f466f25655c89ff..b445d6f49bcf4a62bb3db54e3b9b7497a9672f68 100644 (file)
@@ -1003,7 +1003,6 @@ config UIDGID_CONVERTED
        depends on !UML || HOSTFS = n
 
        # The rare drivers that won't build
-       depends on TUN = n
        depends on INFINIBAND_QIB = n
        depends on BLK_DEV_LOOP = n
        depends on ANDROID_BINDER_IPC = n