diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 9 | ||||
-rw-r--r-- | security/selinux/Kconfig | 29 | ||||
-rw-r--r-- | security/selinux/hooks.c | 242 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 2 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 66 | ||||
-rw-r--r-- | security/selinux/xfrm.c | 12 |
6 files changed, 241 insertions, 119 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index b3a6187e5305..a9d3a1794b23 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1402,6 +1402,15 @@ running once the system is up. | |||
1402 | If enabled at boot time, /selinux/disable can be used | 1402 | If enabled at boot time, /selinux/disable can be used |
1403 | later to disable prior to initial policy load. | 1403 | later to disable prior to initial policy load. |
1404 | 1404 | ||
1405 | selinux_compat_net = | ||
1406 | [SELINUX] Set initial selinux_compat_net flag value. | ||
1407 | Format: { "0" | "1" } | ||
1408 | 0 -- use new secmark-based packet controls | ||
1409 | 1 -- use legacy packet controls | ||
1410 | Default value is 0 (preferred). | ||
1411 | Value can be changed at runtime via | ||
1412 | /selinux/compat_net. | ||
1413 | |||
1405 | serialnumber [BUGS=IA-32] | 1414 | serialnumber [BUGS=IA-32] |
1406 | 1415 | ||
1407 | sg_def_reserved_size= [SCSI] | 1416 | sg_def_reserved_size= [SCSI] |
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 @@ | |||
1 | config SECURITY_SELINUX | 1 | config 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 | |||
100 | config 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 | ||
81 | extern unsigned int policydb_loaded_version; | 81 | extern unsigned int policydb_loaded_version; |
82 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 82 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
83 | extern int selinux_compat_net; | ||
83 | 84 | ||
84 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | 85 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP |
85 | int selinux_enforcing = 0; | 86 | int 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 | ||
3219 | static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 3220 | static 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) | 3278 | out: |
3318 | err = selinux_xfrm_sock_rcv_skb(sock_sid, skb); | 3279 | return err; |
3280 | } | ||
3281 | |||
3282 | static 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); | ||
3320 | out: | 3335 | out: |
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 | ||
3459 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | 3474 | static 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 | } |
3531 | out: | ||
3532 | return err; | ||
3533 | } | ||
3534 | |||
3535 | static 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); | ||
3561 | out: | 3585 | out: |
3562 | return err; | 3586 | return err ? NF_DROP : NF_ACCEPT; |
3563 | } | 3587 | } |
3564 | 3588 | ||
3565 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, | 3589 | static 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 | ||
52 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) | 52 | static 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 | ||
57 | static inline int selinux_socket_getpeer_stream(struct sock *sk) | 57 | static 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 | ||
39 | unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; | 39 | unsigned 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 | |||
47 | int selinux_compat_net = SELINUX_COMPAT_NET_VALUE; | ||
48 | |||
41 | static int __init checkreqprot_setup(char *str) | 49 | static 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 | ||
56 | static 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 | ||
49 | static DEFINE_MUTEX(sel_mutex); | 64 | static 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 | ||
383 | static 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 | |||
393 | static 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; | ||
423 | out: | ||
424 | free_page((unsigned long) page); | ||
425 | return length; | ||
426 | } | ||
427 | static 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) | 396 | out: |
397 | goto drop; | 397 | return rc; |
398 | |||
399 | accept: | ||
400 | return NF_ACCEPT; | ||
401 | |||
402 | drop: | ||
403 | return NF_DROP; | ||
404 | } | 398 | } |