aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-01-14 02:12:19 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-14 18:16:59 -0500
commit5dbbaf2de89613d19a9286d4db0a535ca2735d26 (patch)
tree1eaa64968a8ecf83aee4d2f6792840abde6c4916 /drivers/net/tun.c
parent6f96c142f77c96a34ac377a3616ee7abcd77fb4d (diff)
tun: fix LSM/SELinux labeling of tun/tap devices
This patch corrects some problems with LSM/SELinux that were introduced with the multiqueue patchset. The problem stems from the fact that the multiqueue work changed the relationship between the tun device and its associated socket; before the socket persisted for the life of the device, however after the multiqueue changes the socket only persisted for the life of the userspace connection (fd open). For non-persistent devices this is not an issue, but for persistent devices this can cause the tun device to lose its SELinux label. We correct this problem by adding an opaque LSM security blob to the tun device struct which allows us to have the LSM security state, e.g. SELinux labeling information, persist for the lifetime of the tun device. In the process we tweak the LSM hooks to work with this new approach to TUN device/socket labeling and introduce a new LSM hook, security_tun_dev_attach_queue(), to approve requests to attach to a TUN queue via TUNSETQUEUE. The SELinux code has been adjusted to match the new LSM hooks, the other LSMs do not make use of the LSM TUN controls. This patch makes use of the recently added "tun_socket:attach_queue" permission to restrict access to the TUNSETQUEUE operation. On older SELinux policies which do not define the "tun_socket:attach_queue" permission the access control decision for TUNSETQUEUE will be handled according to the SELinux policy's unknown permission setting. Signed-off-by: Paul Moore <pmoore@redhat.com> Acked-by: Eric Paris <eparis@parisplace.org> Tested-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index af372d0957fe..c81680dc10eb 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -185,6 +185,7 @@ struct tun_struct {
185 unsigned long ageing_time; 185 unsigned long ageing_time;
186 unsigned int numdisabled; 186 unsigned int numdisabled;
187 struct list_head disabled; 187 struct list_head disabled;
188 void *security;
188}; 189};
189 190
190static inline u32 tun_hashfn(u32 rxhash) 191static inline u32 tun_hashfn(u32 rxhash)
@@ -490,6 +491,10 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
490 struct tun_file *tfile = file->private_data; 491 struct tun_file *tfile = file->private_data;
491 int err; 492 int err;
492 493
494 err = security_tun_dev_attach(tfile->socket.sk, tun->security);
495 if (err < 0)
496 goto out;
497
493 err = -EINVAL; 498 err = -EINVAL;
494 if (rtnl_dereference(tfile->tun)) 499 if (rtnl_dereference(tfile->tun))
495 goto out; 500 goto out;
@@ -1373,6 +1378,7 @@ static void tun_free_netdev(struct net_device *dev)
1373 1378
1374 BUG_ON(!(list_empty(&tun->disabled))); 1379 BUG_ON(!(list_empty(&tun->disabled)));
1375 tun_flow_uninit(tun); 1380 tun_flow_uninit(tun);
1381 security_tun_dev_free_security(tun->security);
1376 free_netdev(dev); 1382 free_netdev(dev);
1377} 1383}
1378 1384
@@ -1562,7 +1568,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1562 1568
1563 if (tun_not_capable(tun)) 1569 if (tun_not_capable(tun))
1564 return -EPERM; 1570 return -EPERM;
1565 err = security_tun_dev_attach(tfile->socket.sk); 1571 err = security_tun_dev_open(tun->security);
1566 if (err < 0) 1572 if (err < 0)
1567 return err; 1573 return err;
1568 1574
@@ -1619,7 +1625,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
1619 1625
1620 spin_lock_init(&tun->lock); 1626 spin_lock_init(&tun->lock);
1621 1627
1622 security_tun_dev_post_create(&tfile->sk); 1628 err = security_tun_dev_alloc_security(&tun->security);
1629 if (err < 0)
1630 goto err_free_dev;
1623 1631
1624 tun_net_init(dev); 1632 tun_net_init(dev);
1625 1633
@@ -1789,10 +1797,14 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
1789 1797
1790 if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { 1798 if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
1791 tun = tfile->detached; 1799 tun = tfile->detached;
1792 if (!tun) 1800 if (!tun) {
1793 ret = -EINVAL; 1801 ret = -EINVAL;
1794 else 1802 goto unlock;
1795 ret = tun_attach(tun, file); 1803 }
1804 ret = security_tun_dev_attach_queue(tun->security);
1805 if (ret < 0)
1806 goto unlock;
1807 ret = tun_attach(tun, file);
1796 } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { 1808 } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
1797 tun = rtnl_dereference(tfile->tun); 1809 tun = rtnl_dereference(tfile->tun);
1798 if (!tun || !(tun->flags & TUN_TAP_MQ)) 1810 if (!tun || !(tun->flags & TUN_TAP_MQ))
@@ -1802,6 +1814,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
1802 } else 1814 } else
1803 ret = -EINVAL; 1815 ret = -EINVAL;
1804 1816
1817unlock:
1805 rtnl_unlock(); 1818 rtnl_unlock();
1806 return ret; 1819 return ret;
1807} 1820}