userns: Convert tun/tap to use kuid and kgid where appropriate
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>
This commit is contained in:
@@ -120,8 +120,8 @@ struct tun_sock;
|
|||||||
struct tun_struct {
|
struct tun_struct {
|
||||||
struct tun_file *tfile;
|
struct tun_file *tfile;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
uid_t owner;
|
kuid_t owner;
|
||||||
gid_t group;
|
kgid_t group;
|
||||||
|
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
netdev_features_t set_features;
|
netdev_features_t set_features;
|
||||||
@@ -1032,8 +1032,8 @@ static void tun_setup(struct net_device *dev)
|
|||||||
{
|
{
|
||||||
struct tun_struct *tun = netdev_priv(dev);
|
struct tun_struct *tun = netdev_priv(dev);
|
||||||
|
|
||||||
tun->owner = -1;
|
tun->owner = INVALID_UID;
|
||||||
tun->group = -1;
|
tun->group = INVALID_GID;
|
||||||
|
|
||||||
dev->ethtool_ops = &tun_ethtool_ops;
|
dev->ethtool_ops = &tun_ethtool_ops;
|
||||||
dev->destructor = tun_free_netdev;
|
dev->destructor = tun_free_netdev;
|
||||||
@@ -1156,14 +1156,20 @@ static ssize_t tun_show_owner(struct device *dev, struct device_attribute *attr,
|
|||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct tun_struct *tun = netdev_priv(to_net_dev(dev));
|
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,
|
static ssize_t tun_show_group(struct device *dev, struct device_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct tun_struct *tun = netdev_priv(to_net_dev(dev));
|
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);
|
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
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (((tun->owner != -1 && cred->euid != tun->owner) ||
|
if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
|
||||||
(tun->group != -1 && !in_egroup_p(tun->group))) &&
|
(gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
|
||||||
!capable(CAP_NET_ADMIN))
|
!capable(CAP_NET_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
err = security_tun_dev_attach(tun->socket.sk);
|
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;
|
void __user* argp = (void __user*)arg;
|
||||||
struct sock_fprog fprog;
|
struct sock_fprog fprog;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
kuid_t owner;
|
||||||
|
kgid_t group;
|
||||||
int sndbuf;
|
int sndbuf;
|
||||||
int vnet_hdr_sz;
|
int vnet_hdr_sz;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1448,16 +1456,26 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
|
|||||||
|
|
||||||
case TUNSETOWNER:
|
case TUNSETOWNER:
|
||||||
/* Set owner of the device */
|
/* Set owner of the device */
|
||||||
tun->owner = (uid_t) arg;
|
owner = make_kuid(current_user_ns(), arg);
|
||||||
|
if (!uid_valid(owner)) {
|
||||||
tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->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;
|
break;
|
||||||
|
|
||||||
case TUNSETGROUP:
|
case TUNSETGROUP:
|
||||||
/* Set group of the device */
|
/* Set group of the device */
|
||||||
tun->group= (gid_t) arg;
|
group = make_kgid(current_user_ns(), arg);
|
||||||
|
if (!gid_valid(group)) {
|
||||||
tun_debug(KERN_INFO, tun, "group set to %d\n", tun->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;
|
break;
|
||||||
|
|
||||||
case TUNSETLINK:
|
case TUNSETLINK:
|
||||||
|
@@ -1003,7 +1003,6 @@ config UIDGID_CONVERTED
|
|||||||
depends on !UML || HOSTFS = n
|
depends on !UML || HOSTFS = n
|
||||||
|
|
||||||
# The rare drivers that won't build
|
# The rare drivers that won't build
|
||||||
depends on TUN = n
|
|
||||||
depends on INFINIBAND_QIB = n
|
depends on INFINIBAND_QIB = n
|
||||||
depends on BLK_DEV_LOOP = n
|
depends on BLK_DEV_LOOP = n
|
||||||
depends on ANDROID_BINDER_IPC = n
|
depends on ANDROID_BINDER_IPC = n
|
||||||
|
Reference in New Issue
Block a user