aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/Kconfig29
-rw-r--r--security/selinux/hooks.c242
-rw-r--r--security/selinux/include/xfrm.h2
-rw-r--r--security/selinux/selinuxfs.c66
-rw-r--r--security/selinux/xfrm.c12
5 files changed, 232 insertions, 119 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index f636f53ca544..814ddc42f1f4 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -1,6 +1,7 @@
1config SECURITY_SELINUX 1config SECURITY_SELINUX
2 bool "NSA SELinux Support" 2 bool "NSA SELinux Support"
3 depends on SECURITY_NETWORK && AUDIT && NET && INET 3 depends on SECURITY_NETWORK && AUDIT && NET && INET
4 select NETWORK_SECMARK
4 default n 5 default n
5 help 6 help
6 This selects NSA Security-Enhanced Linux (SELinux). 7 This selects NSA Security-Enhanced Linux (SELinux).
@@ -95,3 +96,31 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
95 via /selinux/checkreqprot if authorized by policy. 96 via /selinux/checkreqprot if authorized by policy.
96 97
97 If you are unsure how to answer this question, answer 1. 98 If you are unsure how to answer this question, answer 1.
99
100config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
101 bool "NSA SELinux enable new secmark network controls by default"
102 depends on SECURITY_SELINUX
103 default n
104 help
105 This option determines whether the new secmark-based network
106 controls will be enabled by default. If not, the old internal
107 per-packet controls will be enabled by default, preserving
108 old behavior.
109
110 If you enable the new controls, you will need updated
111 SELinux userspace libraries, tools and policy. Typically,
112 your distribution will provide these and enable the new controls
113 in the kernel they also distribute.
114
115 Note that this option can be overriden at boot with the
116 selinux_compat_net parameter, and after boot via
117 /selinux/compat_net. See Documentation/kernel-parameters.txt
118 for details on this parameter.
119
120 If you enable the new network controls, you will likely
121 also require the SECMARK and CONNSECMARK targets, as
122 well as any conntrack helpers for protocols which you
123 wish to control.
124
125 If you are unsure what do do here, select N.
126
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 41b6f5d31945..54adc9d31e92 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -80,6 +80,7 @@
80 80
81extern unsigned int policydb_loaded_version; 81extern unsigned int policydb_loaded_version;
82extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); 82extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
83extern int selinux_compat_net;
83 84
84#ifdef CONFIG_SECURITY_SELINUX_DEVELOP 85#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
85int selinux_enforcing = 0; 86int selinux_enforcing = 0;
@@ -3216,47 +3217,17 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3216 return 0; 3217 return 0;
3217} 3218}
3218 3219
3219static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3220static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3221 struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
3222 u16 family, char *addrp, int len)
3220{ 3223{
3221 u16 family; 3224 int err = 0;
3222 char *addrp;
3223 int len, err = 0;
3224 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3225 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
3225 u32 sock_sid = 0;
3226 u16 sock_class = 0;
3227 struct socket *sock;
3228 struct net_device *dev;
3229 struct avc_audit_data ad;
3230
3231 family = sk->sk_family;
3232 if (family != PF_INET && family != PF_INET6)
3233 goto out;
3234
3235 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
3236 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
3237 family = PF_INET;
3238
3239 read_lock_bh(&sk->sk_callback_lock);
3240 sock = sk->sk_socket;
3241 if (sock) {
3242 struct inode *inode;
3243 inode = SOCK_INODE(sock);
3244 if (inode) {
3245 struct inode_security_struct *isec;
3246 isec = inode->i_security;
3247 sock_sid = isec->sid;
3248 sock_class = isec->sclass;
3249 }
3250 }
3251 read_unlock_bh(&sk->sk_callback_lock);
3252 if (!sock_sid)
3253 goto out;
3254 3226
3255 dev = skb->dev; 3227 if (!skb->dev)
3256 if (!dev)
3257 goto out; 3228 goto out;
3258 3229
3259 err = sel_netif_sids(dev, &if_sid, NULL); 3230 err = sel_netif_sids(skb->dev, &if_sid, NULL);
3260 if (err) 3231 if (err)
3261 goto out; 3232 goto out;
3262 3233
@@ -3279,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3279 break; 3250 break;
3280 } 3251 }
3281 3252
3282 AVC_AUDIT_DATA_INIT(&ad, NET); 3253 err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3283 ad.u.net.netif = dev->name;
3284 ad.u.net.family = family;
3285
3286 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
3287 if (err)
3288 goto out;
3289
3290 err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
3291 if (err) 3254 if (err)
3292 goto out; 3255 goto out;
3293 3256
3294 /* Fixme: this lookup is inefficient */
3295 err = security_node_sid(family, addrp, len, &node_sid); 3257 err = security_node_sid(family, addrp, len, &node_sid);
3296 if (err) 3258 if (err)
3297 goto out; 3259 goto out;
3298 3260
3299 err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad); 3261 err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
3300 if (err) 3262 if (err)
3301 goto out; 3263 goto out;
3302 3264
3303 if (recv_perm) { 3265 if (recv_perm) {
3304 u32 port_sid; 3266 u32 port_sid;
3305 3267
3306 /* Fixme: make this more efficient */
3307 err = security_port_sid(sk->sk_family, sk->sk_type, 3268 err = security_port_sid(sk->sk_family, sk->sk_type,
3308 sk->sk_protocol, ntohs(ad.u.net.sport), 3269 sk->sk_protocol, ntohs(ad->u.net.sport),
3309 &port_sid); 3270 &port_sid);
3310 if (err) 3271 if (err)
3311 goto out; 3272 goto out;
3312 3273
3313 err = avc_has_perm(sock_sid, port_sid, 3274 err = avc_has_perm(sock_sid, port_sid,
3314 sock_class, recv_perm, &ad); 3275 sock_class, recv_perm, ad);
3315 } 3276 }
3316 3277
3317 if (!err) 3278out:
3318 err = selinux_xfrm_sock_rcv_skb(sock_sid, skb); 3279 return err;
3280}
3281
3282static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3283{
3284 u16 family;
3285 u16 sock_class = 0;
3286 char *addrp;
3287 int len, err = 0;
3288 u32 sock_sid = 0;
3289 struct socket *sock;
3290 struct avc_audit_data ad;
3291
3292 family = sk->sk_family;
3293 if (family != PF_INET && family != PF_INET6)
3294 goto out;
3295
3296 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
3297 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
3298 family = PF_INET;
3299
3300 read_lock_bh(&sk->sk_callback_lock);
3301 sock = sk->sk_socket;
3302 if (sock) {
3303 struct inode *inode;
3304 inode = SOCK_INODE(sock);
3305 if (inode) {
3306 struct inode_security_struct *isec;
3307 isec = inode->i_security;
3308 sock_sid = isec->sid;
3309 sock_class = isec->sclass;
3310 }
3311 }
3312 read_unlock_bh(&sk->sk_callback_lock);
3313 if (!sock_sid)
3314 goto out;
3315
3316 AVC_AUDIT_DATA_INIT(&ad, NET);
3317 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3318 ad.u.net.family = family;
3319
3320 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
3321 if (err)
3322 goto out;
3323
3324 if (selinux_compat_net)
3325 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
3326 sock_class, family,
3327 addrp, len);
3328 else
3329 err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
3330 PACKET__RECV, &ad);
3331 if (err)
3332 goto out;
3319 3333
3334 err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
3320out: 3335out:
3321 return err; 3336 return err;
3322} 3337}
@@ -3456,42 +3471,18 @@ out:
3456 3471
3457#ifdef CONFIG_NETFILTER 3472#ifdef CONFIG_NETFILTER
3458 3473
3459static unsigned int selinux_ip_postroute_last(unsigned int hooknum, 3474static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
3460 struct sk_buff **pskb, 3475 struct inode_security_struct *isec,
3461 const struct net_device *in, 3476 struct avc_audit_data *ad,
3462 const struct net_device *out, 3477 u16 family, char *addrp, int len)
3463 int (*okfn)(struct sk_buff *),
3464 u16 family)
3465{ 3478{
3466 char *addrp; 3479 int err;
3467 int len, err = NF_ACCEPT;
3468 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 3480 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
3469 struct sock *sk;
3470 struct socket *sock;
3471 struct inode *inode;
3472 struct sk_buff *skb = *pskb;
3473 struct inode_security_struct *isec;
3474 struct avc_audit_data ad;
3475 struct net_device *dev = (struct net_device *)out;
3476 3481
3477 sk = skb->sk;
3478 if (!sk)
3479 goto out;
3480
3481 sock = sk->sk_socket;
3482 if (!sock)
3483 goto out;
3484
3485 inode = SOCK_INODE(sock);
3486 if (!inode)
3487 goto out;
3488
3489 err = sel_netif_sids(dev, &if_sid, NULL); 3482 err = sel_netif_sids(dev, &if_sid, NULL);
3490 if (err) 3483 if (err)
3491 goto out; 3484 goto out;
3492 3485
3493 isec = inode->i_security;
3494
3495 switch (isec->sclass) { 3486 switch (isec->sclass) {
3496 case SECCLASS_UDP_SOCKET: 3487 case SECCLASS_UDP_SOCKET:
3497 netif_perm = NETIF__UDP_SEND; 3488 netif_perm = NETIF__UDP_SEND;
@@ -3511,55 +3502,88 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3511 break; 3502 break;
3512 } 3503 }
3513 3504
3514 3505 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3515 AVC_AUDIT_DATA_INIT(&ad, NET); 3506 if (err)
3516 ad.u.net.netif = dev->name;
3517 ad.u.net.family = family;
3518
3519 err = selinux_parse_skb(skb, &ad, &addrp,
3520 &len, 0) ? NF_DROP : NF_ACCEPT;
3521 if (err != NF_ACCEPT)
3522 goto out;
3523
3524 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
3525 netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
3526 if (err != NF_ACCEPT)
3527 goto out; 3507 goto out;
3528 3508
3529 /* Fixme: this lookup is inefficient */ 3509 err = security_node_sid(family, addrp, len, &node_sid);
3530 err = security_node_sid(family, addrp, len, 3510 if (err)
3531 &node_sid) ? NF_DROP : NF_ACCEPT;
3532 if (err != NF_ACCEPT)
3533 goto out; 3511 goto out;
3534 3512
3535 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, 3513 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
3536 node_perm, &ad) ? NF_DROP : NF_ACCEPT; 3514 if (err)
3537 if (err != NF_ACCEPT)
3538 goto out; 3515 goto out;
3539 3516
3540 if (send_perm) { 3517 if (send_perm) {
3541 u32 port_sid; 3518 u32 port_sid;
3542 3519
3543 /* Fixme: make this more efficient */
3544 err = security_port_sid(sk->sk_family, 3520 err = security_port_sid(sk->sk_family,
3545 sk->sk_type, 3521 sk->sk_type,
3546 sk->sk_protocol, 3522 sk->sk_protocol,
3547 ntohs(ad.u.net.dport), 3523 ntohs(ad->u.net.dport),
3548 &port_sid) ? NF_DROP : NF_ACCEPT; 3524 &port_sid);
3549 if (err != NF_ACCEPT) 3525 if (err)
3550 goto out; 3526 goto out;
3551 3527
3552 err = avc_has_perm(isec->sid, port_sid, isec->sclass, 3528 err = avc_has_perm(isec->sid, port_sid, isec->sclass,
3553 send_perm, &ad) ? NF_DROP : NF_ACCEPT; 3529 send_perm, ad);
3554 } 3530 }
3531out:
3532 return err;
3533}
3534
3535static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3536 struct sk_buff **pskb,
3537 const struct net_device *in,
3538 const struct net_device *out,
3539 int (*okfn)(struct sk_buff *),
3540 u16 family)
3541{
3542 char *addrp;
3543 int len, err = 0;
3544 struct sock *sk;
3545 struct socket *sock;
3546 struct inode *inode;
3547 struct sk_buff *skb = *pskb;
3548 struct inode_security_struct *isec;
3549 struct avc_audit_data ad;
3550 struct net_device *dev = (struct net_device *)out;
3555 3551
3556 if (err != NF_ACCEPT) 3552 sk = skb->sk;
3553 if (!sk)
3557 goto out; 3554 goto out;
3558 3555
3559 err = selinux_xfrm_postroute_last(isec->sid, skb); 3556 sock = sk->sk_socket;
3557 if (!sock)
3558 goto out;
3559
3560 inode = SOCK_INODE(sock);
3561 if (!inode)
3562 goto out;
3563
3564 isec = inode->i_security;
3565
3566 AVC_AUDIT_DATA_INIT(&ad, NET);
3567 ad.u.net.netif = dev->name;
3568 ad.u.net.family = family;
3569
3570 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
3571 if (err)
3572 goto out;
3573
3574 if (selinux_compat_net)
3575 err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
3576 family, addrp, len);
3577 else
3578 err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
3579 PACKET__SEND, &ad);
3560 3580
3581 if (err)
3582 goto out;
3583
3584 err = selinux_xfrm_postroute_last(isec->sid, skb);
3561out: 3585out:
3562 return err; 3586 return err ? NF_DROP : NF_ACCEPT;
3563} 3587}
3564 3588
3565static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, 3589static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index f0f4e480ff99..c96498a10eb8 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -51,7 +51,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
51 51
52static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) 52static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
53{ 53{
54 return NF_ACCEPT; 54 return 0;
55} 55}
56 56
57static inline int selinux_socket_getpeer_stream(struct sock *sk) 57static inline int selinux_socket_getpeer_stream(struct sock *sk)
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index a4efc966f065..2e73d3279f2d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -38,6 +38,14 @@
38 38
39unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 39unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
40 40
41#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
42#define SELINUX_COMPAT_NET_VALUE 0
43#else
44#define SELINUX_COMPAT_NET_VALUE 1
45#endif
46
47int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
48
41static int __init checkreqprot_setup(char *str) 49static int __init checkreqprot_setup(char *str)
42{ 50{
43 selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0; 51 selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -45,6 +53,13 @@ static int __init checkreqprot_setup(char *str)
45} 53}
46__setup("checkreqprot=", checkreqprot_setup); 54__setup("checkreqprot=", checkreqprot_setup);
47 55
56static int __init selinux_compat_net_setup(char *str)
57{
58 selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
59 return 1;
60}
61__setup("selinux_compat_net=", selinux_compat_net_setup);
62
48 63
49static DEFINE_MUTEX(sel_mutex); 64static DEFINE_MUTEX(sel_mutex);
50 65
@@ -85,6 +100,7 @@ enum sel_inos {
85 SEL_AVC, /* AVC management directory */ 100 SEL_AVC, /* AVC management directory */
86 SEL_MEMBER, /* compute polyinstantiation membership decision */ 101 SEL_MEMBER, /* compute polyinstantiation membership decision */
87 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ 102 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
103 SEL_COMPAT_NET, /* whether to use old compat network packet controls */
88}; 104};
89 105
90#define TMPBUFLEN 12 106#define TMPBUFLEN 12
@@ -364,6 +380,55 @@ static struct file_operations sel_checkreqprot_ops = {
364 .write = sel_write_checkreqprot, 380 .write = sel_write_checkreqprot,
365}; 381};
366 382
383static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
384 size_t count, loff_t *ppos)
385{
386 char tmpbuf[TMPBUFLEN];
387 ssize_t length;
388
389 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
390 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
391}
392
393static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
394 size_t count, loff_t *ppos)
395{
396 char *page;
397 ssize_t length;
398 int new_value;
399
400 length = task_has_security(current, SECURITY__LOAD_POLICY);
401 if (length)
402 return length;
403
404 if (count >= PAGE_SIZE)
405 return -ENOMEM;
406 if (*ppos != 0) {
407 /* No partial writes. */
408 return -EINVAL;
409 }
410 page = (char*)get_zeroed_page(GFP_KERNEL);
411 if (!page)
412 return -ENOMEM;
413 length = -EFAULT;
414 if (copy_from_user(page, buf, count))
415 goto out;
416
417 length = -EINVAL;
418 if (sscanf(page, "%d", &new_value) != 1)
419 goto out;
420
421 selinux_compat_net = new_value ? 1 : 0;
422 length = count;
423out:
424 free_page((unsigned long) page);
425 return length;
426}
427static struct file_operations sel_compat_net_ops = {
428 .read = sel_read_compat_net,
429 .write = sel_write_compat_net,
430};
431
367/* 432/*
368 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c 433 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
369 */ 434 */
@@ -1219,6 +1284,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1219 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR}, 1284 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1220 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO}, 1285 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1221 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, 1286 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
1287 [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
1222 /* last one */ {""} 1288 /* last one */ {""}
1223 }; 1289 };
1224 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1290 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 0e24df41099f..6633fb059313 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -387,18 +387,12 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
387 struct xfrm_state *x = dst_test->xfrm; 387 struct xfrm_state *x = dst_test->xfrm;
388 388
389 if (x && selinux_authorizable_xfrm(x)) 389 if (x && selinux_authorizable_xfrm(x))
390 goto accept; 390 goto out;
391 } 391 }
392 } 392 }
393 393
394 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 394 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
395 ASSOCIATION__SENDTO, NULL); 395 ASSOCIATION__SENDTO, NULL);
396 if (rc) 396out:
397 goto drop; 397 return rc;
398
399accept:
400 return NF_ACCEPT;
401
402drop:
403 return NF_DROP;
404} 398}