aboutsummaryrefslogtreecommitdiffstats
path: root/security
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 /security
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 'security')
-rw-r--r--security/capability.c24
-rw-r--r--security/security.c28
-rw-r--r--security/selinux/hooks.c50
-rw-r--r--security/selinux/include/objsec.h4
4 files changed, 87 insertions, 19 deletions
diff --git a/security/capability.c b/security/capability.c
index 0fe5a026aef8..579775088967 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -709,16 +709,31 @@ static void cap_req_classify_flow(const struct request_sock *req,
709{ 709{
710} 710}
711 711
712static int cap_tun_dev_alloc_security(void **security)
713{
714 return 0;
715}
716
717static void cap_tun_dev_free_security(void *security)
718{
719}
720
712static int cap_tun_dev_create(void) 721static int cap_tun_dev_create(void)
713{ 722{
714 return 0; 723 return 0;
715} 724}
716 725
717static void cap_tun_dev_post_create(struct sock *sk) 726static int cap_tun_dev_attach_queue(void *security)
727{
728 return 0;
729}
730
731static int cap_tun_dev_attach(struct sock *sk, void *security)
718{ 732{
733 return 0;
719} 734}
720 735
721static int cap_tun_dev_attach(struct sock *sk) 736static int cap_tun_dev_open(void *security)
722{ 737{
723 return 0; 738 return 0;
724} 739}
@@ -1050,8 +1065,11 @@ void __init security_fixup_ops(struct security_operations *ops)
1050 set_to_cap_if_null(ops, secmark_refcount_inc); 1065 set_to_cap_if_null(ops, secmark_refcount_inc);
1051 set_to_cap_if_null(ops, secmark_refcount_dec); 1066 set_to_cap_if_null(ops, secmark_refcount_dec);
1052 set_to_cap_if_null(ops, req_classify_flow); 1067 set_to_cap_if_null(ops, req_classify_flow);
1068 set_to_cap_if_null(ops, tun_dev_alloc_security);
1069 set_to_cap_if_null(ops, tun_dev_free_security);
1053 set_to_cap_if_null(ops, tun_dev_create); 1070 set_to_cap_if_null(ops, tun_dev_create);
1054 set_to_cap_if_null(ops, tun_dev_post_create); 1071 set_to_cap_if_null(ops, tun_dev_open);
1072 set_to_cap_if_null(ops, tun_dev_attach_queue);
1055 set_to_cap_if_null(ops, tun_dev_attach); 1073 set_to_cap_if_null(ops, tun_dev_attach);
1056#endif /* CONFIG_SECURITY_NETWORK */ 1074#endif /* CONFIG_SECURITY_NETWORK */
1057#ifdef CONFIG_SECURITY_NETWORK_XFRM 1075#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/security.c b/security/security.c
index daa97f4ac9d1..7b88c6aeaed4 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1254,24 +1254,42 @@ void security_secmark_refcount_dec(void)
1254} 1254}
1255EXPORT_SYMBOL(security_secmark_refcount_dec); 1255EXPORT_SYMBOL(security_secmark_refcount_dec);
1256 1256
1257int security_tun_dev_alloc_security(void **security)
1258{
1259 return security_ops->tun_dev_alloc_security(security);
1260}
1261EXPORT_SYMBOL(security_tun_dev_alloc_security);
1262
1263void security_tun_dev_free_security(void *security)
1264{
1265 security_ops->tun_dev_free_security(security);
1266}
1267EXPORT_SYMBOL(security_tun_dev_free_security);
1268
1257int security_tun_dev_create(void) 1269int security_tun_dev_create(void)
1258{ 1270{
1259 return security_ops->tun_dev_create(); 1271 return security_ops->tun_dev_create();
1260} 1272}
1261EXPORT_SYMBOL(security_tun_dev_create); 1273EXPORT_SYMBOL(security_tun_dev_create);
1262 1274
1263void security_tun_dev_post_create(struct sock *sk) 1275int security_tun_dev_attach_queue(void *security)
1264{ 1276{
1265 return security_ops->tun_dev_post_create(sk); 1277 return security_ops->tun_dev_attach_queue(security);
1266} 1278}
1267EXPORT_SYMBOL(security_tun_dev_post_create); 1279EXPORT_SYMBOL(security_tun_dev_attach_queue);
1268 1280
1269int security_tun_dev_attach(struct sock *sk) 1281int security_tun_dev_attach(struct sock *sk, void *security)
1270{ 1282{
1271 return security_ops->tun_dev_attach(sk); 1283 return security_ops->tun_dev_attach(sk, security);
1272} 1284}
1273EXPORT_SYMBOL(security_tun_dev_attach); 1285EXPORT_SYMBOL(security_tun_dev_attach);
1274 1286
1287int security_tun_dev_open(void *security)
1288{
1289 return security_ops->tun_dev_open(security);
1290}
1291EXPORT_SYMBOL(security_tun_dev_open);
1292
1275#endif /* CONFIG_SECURITY_NETWORK */ 1293#endif /* CONFIG_SECURITY_NETWORK */
1276 1294
1277#ifdef CONFIG_SECURITY_NETWORK_XFRM 1295#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 61a53367d029..ef26e9611ffb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4399,6 +4399,24 @@ static void selinux_req_classify_flow(const struct request_sock *req,
4399 fl->flowi_secid = req->secid; 4399 fl->flowi_secid = req->secid;
4400} 4400}
4401 4401
4402static int selinux_tun_dev_alloc_security(void **security)
4403{
4404 struct tun_security_struct *tunsec;
4405
4406 tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
4407 if (!tunsec)
4408 return -ENOMEM;
4409 tunsec->sid = current_sid();
4410
4411 *security = tunsec;
4412 return 0;
4413}
4414
4415static void selinux_tun_dev_free_security(void *security)
4416{
4417 kfree(security);
4418}
4419
4402static int selinux_tun_dev_create(void) 4420static int selinux_tun_dev_create(void)
4403{ 4421{
4404 u32 sid = current_sid(); 4422 u32 sid = current_sid();
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)
4414 NULL); 4432 NULL);
4415} 4433}
4416 4434
4417static void selinux_tun_dev_post_create(struct sock *sk) 4435static int selinux_tun_dev_attach_queue(void *security)
4418{ 4436{
4437 struct tun_security_struct *tunsec = security;
4438
4439 return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
4440 TUN_SOCKET__ATTACH_QUEUE, NULL);
4441}
4442
4443static int selinux_tun_dev_attach(struct sock *sk, void *security)
4444{
4445 struct tun_security_struct *tunsec = security;
4419 struct sk_security_struct *sksec = sk->sk_security; 4446 struct sk_security_struct *sksec = sk->sk_security;
4420 4447
4421 /* we don't currently perform any NetLabel based labeling here and it 4448 /* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)
4425 * cause confusion to the TUN user that had no idea network labeling 4452 * cause confusion to the TUN user that had no idea network labeling
4426 * protocols were being used */ 4453 * protocols were being used */
4427 4454
4428 /* see the comments in selinux_tun_dev_create() about why we don't use 4455 sksec->sid = tunsec->sid;
4429 * the sockcreate SID here */
4430
4431 sksec->sid = current_sid();
4432 sksec->sclass = SECCLASS_TUN_SOCKET; 4456 sksec->sclass = SECCLASS_TUN_SOCKET;
4457
4458 return 0;
4433} 4459}
4434 4460
4435static int selinux_tun_dev_attach(struct sock *sk) 4461static int selinux_tun_dev_open(void *security)
4436{ 4462{
4437 struct sk_security_struct *sksec = sk->sk_security; 4463 struct tun_security_struct *tunsec = security;
4438 u32 sid = current_sid(); 4464 u32 sid = current_sid();
4439 int err; 4465 int err;
4440 4466
4441 err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, 4467 err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
4442 TUN_SOCKET__RELABELFROM, NULL); 4468 TUN_SOCKET__RELABELFROM, NULL);
4443 if (err) 4469 if (err)
4444 return err; 4470 return err;
@@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk)
4446 TUN_SOCKET__RELABELTO, NULL); 4472 TUN_SOCKET__RELABELTO, NULL);
4447 if (err) 4473 if (err)
4448 return err; 4474 return err;
4449 4475 tunsec->sid = sid;
4450 sksec->sid = sid;
4451 4476
4452 return 0; 4477 return 0;
4453} 4478}
@@ -5642,9 +5667,12 @@ static struct security_operations selinux_ops = {
5642 .secmark_refcount_inc = selinux_secmark_refcount_inc, 5667 .secmark_refcount_inc = selinux_secmark_refcount_inc,
5643 .secmark_refcount_dec = selinux_secmark_refcount_dec, 5668 .secmark_refcount_dec = selinux_secmark_refcount_dec,
5644 .req_classify_flow = selinux_req_classify_flow, 5669 .req_classify_flow = selinux_req_classify_flow,
5670 .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
5671 .tun_dev_free_security = selinux_tun_dev_free_security,
5645 .tun_dev_create = selinux_tun_dev_create, 5672 .tun_dev_create = selinux_tun_dev_create,
5646 .tun_dev_post_create = selinux_tun_dev_post_create, 5673 .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
5647 .tun_dev_attach = selinux_tun_dev_attach, 5674 .tun_dev_attach = selinux_tun_dev_attach,
5675 .tun_dev_open = selinux_tun_dev_open,
5648 5676
5649#ifdef CONFIG_SECURITY_NETWORK_XFRM 5677#ifdef CONFIG_SECURITY_NETWORK_XFRM
5650 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, 5678 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 26c7eee1c309..aa47bcabb5f6 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -110,6 +110,10 @@ struct sk_security_struct {
110 u16 sclass; /* sock security class */ 110 u16 sclass; /* sock security class */
111}; 111};
112 112
113struct tun_security_struct {
114 u32 sid; /* SID for the tun device sockets */
115};
116
113struct key_security_struct { 117struct key_security_struct {
114 u32 sid; /* SID of key */ 118 u32 sid; /* SID of key */
115}; 119};