Fix some multiqueue TUN problems
Subsystems (5)
cover Fix some multiqueue TUN problems
No significant changes to this patchset since the last posting, just a slight merge with the recent changes in tun_set_queue() and some Acked-by and Tested-by additions. I believe all the concerns have been addressed and this patch is ready for merging.
Dave, I think it makes the most sense for this to get pulled in via the netdev tree but if you think otherwise let me know and I'll go bug James and Eric.
-Paul
---
Paul Moore (2):
selinux: add the "attach_queue" permission to the "tun_socket" class
tun: fix LSM/SELinux labeling of tun/tap devices
drivers/net/tun.c | 23 +++++++++++--- include/linux/security.h | 59 +++++++++++++++++++++++++++-------- security/capability.c | 24 ++++++++++++-- security/security.c | 28 ++++++++++++++--- security/selinux/hooks.c | 50 +++++++++++++++++++++++------- security/selinux/include/classmap.h | 2 + security/selinux/include/objsec.h | 4 ++ 7 files changed, 152 insertions(+), 38 deletions(-)
PATCH 1/2 selinux: add the "attach_queue" permission to the "tun_socket" class
Add a new permission to align with the new TUN multiqueue support, "tun_socket:attach_queue".
The corresponding SELinux reference policy patch is show below:
diff --git a/policy/flask/access_vectors b/policy/flask/access_vectors index 28802c5..a0664a1 100644
--- a/policy/flask/access_vectors
+++ b/policy/flask/access_vectors
@@ -827,6 +827,9 @@ class kernel_service
class tun_socket
inherits socket
+{
+ attach_queue
+}
class x_pointer
inherits x_device
--- security/selinux/include/classmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/selinux/include/classmap.h +1 -1
@@ -150,6 +150,6 @@ struct security_class_mapping secclass_map[] = { NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, {"tun_socket" , - { COMMON_SOCK_PERMS, NULL } }, + { COMMON_SOCK_PERMS, "attach_queue", NULL } }, { NULL } };
PATCH 2/2 tun: fix LSM/SELinux labeling of tun/tap devices
In reply to Paul MooreThis 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.
--- drivers/net/tun.c | 23 +++++++++++--- include/linux/security.h | 59 +++++++++++++++++++++++++++++-------- security/capability.c | 24 +++++++++++++-- security/security.c | 28 ++++++++++++++---- security/selinux/hooks.c | 50 ++++++++++++++++++++++++------- security/selinux/include/objsec.h | 4 +++ 6 files changed, 151 insertions(+), 37 deletions(-)
drivers/net/tun.c +18 -5
@@ -185,6 +185,7 @@ struct tun_struct {unsigned long ageing_time;unsigned int numdisabled;struct list_head disabled; +void *security; };static inline u32 tun_hashfn (u32 rxhash)
@@ -490,6 +491,10 @@ static int tun_attach(struct tun_struct *tun, struct file *file)struct tun_file *tfile = file->private_data;int err; + err =security_tun_dev_attach (tfile->socket.sk, tun->security); +if (err <0 ) + goto out; + err = -EINVAL ;if (rtnl_dereference (tfile->tun)) goto out;
@@ -1373,6 +1378,7 @@ static void tun_free_netdev(struct net_device *dev)BUG_ON (!(list_empty (&tun->disabled)));tun_flow_uninit (tun); +security_tun_dev_free_security (tun->security);free_netdev (dev); }
@@ -1562,7 +1568,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)if (tun_not_capable (tun))return -EPERM ; - err =security_tun_dev_attach (tfile->socket.sk); + err =security_tun_dev_open (tun->security);if (err <0 )return err;
@@ -1619,7 +1625,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)spin_lock_init (&tun->lock); -security_tun_dev_post_create (&tfile->sk); + err =security_tun_dev_alloc_security (&tun->security); +if (err <0 ) + goto err_free_dev;tun_net_init (dev);
@@ -1789,10 +1797,14 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)if (ifr->ifr_flags &IFF_ATTACH_QUEUE ) { tun = tfile->detached; -if (!tun) +if (!tun) { ret = -EINVAL ; -else - ret =tun_attach (tun, file); + goto unlock; + } + ret =security_tun_dev_attach_queue (tun->security); +if (ret <0 ) + goto unlock; + ret =tun_attach (tun, file); }else if (ifr->ifr_flags &IFF_DETACH_QUEUE ) { tun =rtnl_dereference (tfile->tun);if (!tun || !(tun->flags &TUN_TAP_MQ ))
@@ -1802,6 +1814,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) }else ret = -EINVAL ; +unlock:rtnl_unlock ();return ret; }
include/linux/security.h +46 -13
97 lines not on this page · raw message
security/capability.c +21 -3
@@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req, { } +static int cap_tun_dev_alloc_security (void **security) +{ +return 0 ; +} + +static void cap_tun_dev_free_security (void *security) +{ +} +static int cap_tun_dev_create (void ) {return 0 ; } -static void cap_tun_dev_post_create (struct sock *sk) +static int cap_tun_dev_attach_queue (void *security) +{ +return 0 ; +} + +static int cap_tun_dev_attach (struct sock *sk,void *security) { +return 0 ; } -static int cap_tun_dev_attach (struct sock *sk) +static int cap_tun_dev_open (void *security) {return 0 ; }
@@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops)set_to_cap_if_null (ops, secmark_refcount_inc);set_to_cap_if_null (ops, secmark_refcount_dec);set_to_cap_if_null (ops, req_classify_flow); +set_to_cap_if_null (ops, tun_dev_alloc_security); +set_to_cap_if_null (ops, tun_dev_free_security);set_to_cap_if_null (ops, tun_dev_create); -set_to_cap_if_null (ops, tun_dev_post_create); +set_to_cap_if_null (ops, tun_dev_open); +set_to_cap_if_null (ops, tun_dev_attach_queue);set_to_cap_if_null (ops, tun_dev_attach);#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
security/security.c +23 -5
@@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void) }EXPORT_SYMBOL (security_secmark_refcount_dec); +int security_tun_dev_alloc_security (void **security) +{ +return security_ops->tun_dev_alloc_security (security); +} +EXPORT_SYMBOL (security_tun_dev_alloc_security); + +void security_tun_dev_free_security (void *security) +{ + security_ops->tun_dev_free_security (security); +} +EXPORT_SYMBOL (security_tun_dev_free_security); +int security_tun_dev_create (void ) {return security_ops->tun_dev_create (); }EXPORT_SYMBOL (security_tun_dev_create); -void security_tun_dev_post_create (struct sock *sk) +int security_tun_dev_attach_queue (void *security) { -return security_ops->tun_dev_post_create (sk); +return security_ops->tun_dev_attach_queue (security); } -EXPORT_SYMBOL (security_tun_dev_post_create); +EXPORT_SYMBOL (security_tun_dev_attach_queue); -int security_tun_dev_attach (struct sock *sk) +int security_tun_dev_attach (struct sock *sk,void *security) { -return security_ops->tun_dev_attach (sk); +return security_ops->tun_dev_attach (sk, security); }EXPORT_SYMBOL (security_tun_dev_attach); +int security_tun_dev_open (void *security) +{ +return security_ops->tun_dev_open (security); +} +EXPORT_SYMBOL (security_tun_dev_open); +#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
security/selinux/hooks.c +39 -11
90 lines not on this page · raw message
security/selinux/include/objsec.h +4 -0
@@ -110,6 +110,10 @@ struct sk_security_struct {u16 sclass;/* sock security class */ }; +struct tun_security_struct { +u32 sid;/* SID for the tun device sockets */ +}; +struct key_security_struct {u32 sid;/* SID of key */ };
David Miller
maintainerFrom: Paul Moore <[email protected]>
Date: Mon, 14 Jan 2013 12:12:06 -0500
Quoted 8 lines
No significant changes to this patchset since the last posting, just a slight merge with the recent changes in
tun_set_queue()and some Acked-by and Tested-by additions. I believe all the concerns have been addressed and this patch is ready for merging.Dave, I think it makes the most sense for this to get pulled in via the netdev tree but if you think otherwise let me know and I'll go bug James and Eric.
Series applied, thanks Paul.