[NET]: Allow group ownership of TUN/TAP devices.
authorGuido Guenther <agx@sigxcpu.org>
Tue, 3 Jul 2007 05:50:25 +0000 (22:50 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Wed, 11 Jul 2007 05:16:42 +0000 (22:16 -0700)
Introduce a new syscall TUNSETGROUP for group ownership setting of tap
devices. The user now is allowed to send packages if either his euid or
his egid matches the one specified via tunctl (via -u or -g
respecitvely). If both, gid and uid, are set via tunctl, both have to
match.

Signed-off-by: Guido Guenther <agx@sigxcpu.org>
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tun.c
include/linux/if_tun.h

index a2c6caaaae932a672a34058619f6998ee8e7bc59..62b2b3005019c90865ef0f019f16d8d2607089f0 100644 (file)
@@ -432,6 +432,7 @@ static void tun_setup(struct net_device *dev)
        init_waitqueue_head(&tun->read_wait);
 
        tun->owner = -1;
+       tun->group = -1;
 
        SET_MODULE_OWNER(dev);
        dev->open = tun_net_open;
@@ -467,8 +468,11 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
                        return -EBUSY;
 
                /* Check permissions */
-               if (tun->owner != -1 &&
-                   current->euid != tun->owner && !capable(CAP_NET_ADMIN))
+               if (((tun->owner != -1 &&
+                     current->euid != tun->owner) ||
+                    (tun->group != -1 &&
+                     current->egid != tun->group)) &&
+                    !capable(CAP_NET_ADMIN))
                        return -EPERM;
        }
        else if (__dev_get_by_name(ifr->ifr_name))
@@ -610,6 +614,13 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
                break;
 
+       case TUNSETGROUP:
+               /* Set group of the device */
+               tun->group= (gid_t) arg;
+
+               DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+               break;
+
        case TUNSETLINK:
                /* Only allow setting the type when the interface is down */
                if (tun->dev->flags & IFF_UP) {
index 88aef7b86ef43be6b5b2408aa233f559fa88c115..42eb6945b93ede5bc06463e1b5cfda9e5e940109 100644 (file)
@@ -36,6 +36,7 @@ struct tun_struct {
        unsigned long           flags;
        int                     attached;
        uid_t                   owner;
+       gid_t                   group;
 
        wait_queue_head_t       read_wait;
        struct sk_buff_head     readq;
@@ -78,6 +79,7 @@ struct tun_struct {
 #define TUNSETPERSIST _IOW('T', 203, int) 
 #define TUNSETOWNER   _IOW('T', 204, int)
 #define TUNSETLINK    _IOW('T', 205, int)
+#define TUNSETGROUP   _IOW('T', 206, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001