lsm: Add hooks to the TUN driver
The TUN driver lacks any LSM hooks which makes it difficult for LSM modules, such as SELinux, to enforce access controls on network traffic generated by TUN users; this is particularly problematic for virtualization apps such as QEMU and KVM. This patch adds three new LSM hooks designed to control the creation and attachment of TUN devices, the hooks are: * security_tun_dev_create() Provides access control for the creation of new TUN devices * security_tun_dev_post_create() Provides the ability to create the necessary socket LSM state for newly created TUN devices * security_tun_dev_attach() Provides access control for attaching to existing, persistent TUN devices and the ability to update the TUN device's socket LSM state as necessary Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: Eric Paris <eparis@parisplace.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
@@ -130,17 +130,10 @@ static inline struct tun_sock *tun_sk(struct sock *sk)
|
||||
static int tun_attach(struct tun_struct *tun, struct file *file)
|
||||
{
|
||||
struct tun_file *tfile = file->private_data;
|
||||
const struct cred *cred = current_cred();
|
||||
int err;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* Check permissions */
|
||||
if (((tun->owner != -1 && cred->euid != tun->owner) ||
|
||||
(tun->group != -1 && !in_egroup_p(tun->group))) &&
|
||||
!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
netif_tx_lock_bh(tun->dev);
|
||||
|
||||
err = -EINVAL;
|
||||
@@ -926,6 +919,8 @@ 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)
|
||||
@@ -935,6 +930,14 @@ 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))) &&
|
||||
!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
err = security_tun_dev_attach(tun->sk);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = tun_attach(tun, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@@ -947,6 +950,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
err = security_tun_dev_create();
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Set dev type */
|
||||
if (ifr->ifr_flags & IFF_TUN) {
|
||||
@@ -989,6 +995,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
|
||||
tun->sk = sk;
|
||||
container_of(sk, struct tun_sock, sk)->tun = tun;
|
||||
|
||||
security_tun_dev_post_create(sk);
|
||||
|
||||
tun_net_init(dev);
|
||||
|
||||
if (strchr(dev->name, '%')) {
|
||||
|
Reference in New Issue
Block a user