|
@@ -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) {
|