diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/dummy.c | 18 | ||||
-rw-r--r-- | security/selinux/Kconfig | 29 | ||||
-rw-r--r-- | security/selinux/Makefile | 2 | ||||
-rw-r--r-- | security/selinux/avc.c | 13 | ||||
-rw-r--r-- | security/selinux/exports.c | 96 | ||||
-rw-r--r-- | security/selinux/hooks.c | 263 | ||||
-rw-r--r-- | security/selinux/include/av_inherit.h | 1 | ||||
-rw-r--r-- | security/selinux/include/av_perm_to_string.h | 3 | ||||
-rw-r--r-- | security/selinux/include/av_permissions.h | 26 | ||||
-rw-r--r-- | security/selinux/include/class_to_string.h | 2 | ||||
-rw-r--r-- | security/selinux/include/flask.h | 2 | ||||
-rw-r--r-- | security/selinux/include/security.h | 5 | ||||
-rw-r--r-- | security/selinux/include/xfrm.h | 4 | ||||
-rw-r--r-- | security/selinux/selinuxfs.c | 66 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 30 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 4 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 239 | ||||
-rw-r--r-- | security/selinux/xfrm.c | 51 |
18 files changed, 700 insertions, 154 deletions
diff --git a/security/dummy.c b/security/dummy.c index fd99429278e9..64f6da0f422e 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -563,11 +563,6 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag) | |||
563 | return 0; | 563 | return 0; |
564 | } | 564 | } |
565 | 565 | ||
566 | static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size) | ||
567 | { | ||
568 | return -EOPNOTSUPP; | ||
569 | } | ||
570 | |||
571 | static int dummy_msg_msg_alloc_security (struct msg_msg *msg) | 566 | static int dummy_msg_msg_alloc_security (struct msg_msg *msg) |
572 | { | 567 | { |
573 | return 0; | 568 | return 0; |
@@ -815,6 +810,11 @@ static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp) | |||
815 | { | 810 | { |
816 | } | 811 | } |
817 | 812 | ||
813 | static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp) | ||
814 | { | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) | 818 | static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) |
819 | { | 819 | { |
820 | return 0; | 820 | return 0; |
@@ -824,6 +824,11 @@ static void dummy_xfrm_state_free_security(struct xfrm_state *x) | |||
824 | { | 824 | { |
825 | } | 825 | } |
826 | 826 | ||
827 | static int dummy_xfrm_state_delete_security(struct xfrm_state *x) | ||
828 | { | ||
829 | return 0; | ||
830 | } | ||
831 | |||
827 | static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) | 832 | static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) |
828 | { | 833 | { |
829 | return 0; | 834 | return 0; |
@@ -976,7 +981,6 @@ void security_fixup_ops (struct security_operations *ops) | |||
976 | set_to_dummy_if_null(ops, task_reparent_to_init); | 981 | set_to_dummy_if_null(ops, task_reparent_to_init); |
977 | set_to_dummy_if_null(ops, task_to_inode); | 982 | set_to_dummy_if_null(ops, task_to_inode); |
978 | set_to_dummy_if_null(ops, ipc_permission); | 983 | set_to_dummy_if_null(ops, ipc_permission); |
979 | set_to_dummy_if_null(ops, ipc_getsecurity); | ||
980 | set_to_dummy_if_null(ops, msg_msg_alloc_security); | 984 | set_to_dummy_if_null(ops, msg_msg_alloc_security); |
981 | set_to_dummy_if_null(ops, msg_msg_free_security); | 985 | set_to_dummy_if_null(ops, msg_msg_free_security); |
982 | set_to_dummy_if_null(ops, msg_queue_alloc_security); | 986 | set_to_dummy_if_null(ops, msg_queue_alloc_security); |
@@ -1030,8 +1034,10 @@ void security_fixup_ops (struct security_operations *ops) | |||
1030 | set_to_dummy_if_null(ops, xfrm_policy_alloc_security); | 1034 | set_to_dummy_if_null(ops, xfrm_policy_alloc_security); |
1031 | set_to_dummy_if_null(ops, xfrm_policy_clone_security); | 1035 | set_to_dummy_if_null(ops, xfrm_policy_clone_security); |
1032 | set_to_dummy_if_null(ops, xfrm_policy_free_security); | 1036 | set_to_dummy_if_null(ops, xfrm_policy_free_security); |
1037 | set_to_dummy_if_null(ops, xfrm_policy_delete_security); | ||
1033 | set_to_dummy_if_null(ops, xfrm_state_alloc_security); | 1038 | set_to_dummy_if_null(ops, xfrm_state_alloc_security); |
1034 | set_to_dummy_if_null(ops, xfrm_state_free_security); | 1039 | set_to_dummy_if_null(ops, xfrm_state_free_security); |
1040 | set_to_dummy_if_null(ops, xfrm_state_delete_security); | ||
1035 | set_to_dummy_if_null(ops, xfrm_policy_lookup); | 1041 | set_to_dummy_if_null(ops, xfrm_policy_lookup); |
1036 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ | 1042 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ |
1037 | #ifdef CONFIG_KEYS | 1043 | #ifdef CONFIG_KEYS |
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/Makefile b/security/selinux/Makefile index 688c0a267b62..faf2e02e4410 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ | 5 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ |
6 | 6 | ||
7 | selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o | 7 | selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o |
8 | 8 | ||
9 | selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o | 9 | selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o |
10 | 10 | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index ac5d69bb3377..a300702da527 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -800,7 +800,7 @@ out: | |||
800 | int avc_ss_reset(u32 seqno) | 800 | int avc_ss_reset(u32 seqno) |
801 | { | 801 | { |
802 | struct avc_callback_node *c; | 802 | struct avc_callback_node *c; |
803 | int i, rc = 0; | 803 | int i, rc = 0, tmprc; |
804 | unsigned long flag; | 804 | unsigned long flag; |
805 | struct avc_node *node; | 805 | struct avc_node *node; |
806 | 806 | ||
@@ -813,15 +813,16 @@ int avc_ss_reset(u32 seqno) | |||
813 | 813 | ||
814 | for (c = avc_callbacks; c; c = c->next) { | 814 | for (c = avc_callbacks; c; c = c->next) { |
815 | if (c->events & AVC_CALLBACK_RESET) { | 815 | if (c->events & AVC_CALLBACK_RESET) { |
816 | rc = c->callback(AVC_CALLBACK_RESET, | 816 | tmprc = c->callback(AVC_CALLBACK_RESET, |
817 | 0, 0, 0, 0, NULL); | 817 | 0, 0, 0, 0, NULL); |
818 | if (rc) | 818 | /* save the first error encountered for the return |
819 | goto out; | 819 | value and continue processing the callbacks */ |
820 | if (!rc) | ||
821 | rc = tmprc; | ||
820 | } | 822 | } |
821 | } | 823 | } |
822 | 824 | ||
823 | avc_latest_notif_update(seqno, 0); | 825 | avc_latest_notif_update(seqno, 0); |
824 | out: | ||
825 | return rc; | 826 | return rc; |
826 | } | 827 | } |
827 | 828 | ||
diff --git a/security/selinux/exports.c b/security/selinux/exports.c new file mode 100644 index 000000000000..9d7737db5e51 --- /dev/null +++ b/security/selinux/exports.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * SELinux services exported to the rest of the kernel. | ||
3 | * | ||
4 | * Author: James Morris <jmorris@redhat.com> | ||
5 | * | ||
6 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> | ||
7 | * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | ||
8 | * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2, | ||
12 | * as published by the Free Software Foundation. | ||
13 | */ | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/selinux.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/ipc.h> | ||
20 | |||
21 | #include "security.h" | ||
22 | #include "objsec.h" | ||
23 | |||
24 | void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid) | ||
25 | { | ||
26 | struct task_security_struct *tsec = tsk->security; | ||
27 | if (selinux_enabled) | ||
28 | *ctxid = tsec->sid; | ||
29 | else | ||
30 | *ctxid = 0; | ||
31 | } | ||
32 | |||
33 | int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen) | ||
34 | { | ||
35 | if (selinux_enabled) | ||
36 | return security_sid_to_context(ctxid, ctx, ctxlen); | ||
37 | else { | ||
38 | *ctx = NULL; | ||
39 | *ctxlen = 0; | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | void selinux_get_inode_sid(const struct inode *inode, u32 *sid) | ||
46 | { | ||
47 | if (selinux_enabled) { | ||
48 | struct inode_security_struct *isec = inode->i_security; | ||
49 | *sid = isec->sid; | ||
50 | return; | ||
51 | } | ||
52 | *sid = 0; | ||
53 | } | ||
54 | |||
55 | void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid) | ||
56 | { | ||
57 | if (selinux_enabled) { | ||
58 | struct ipc_security_struct *isec = ipcp->security; | ||
59 | *sid = isec->sid; | ||
60 | return; | ||
61 | } | ||
62 | *sid = 0; | ||
63 | } | ||
64 | |||
65 | void selinux_get_task_sid(struct task_struct *tsk, u32 *sid) | ||
66 | { | ||
67 | if (selinux_enabled) { | ||
68 | struct task_security_struct *tsec = tsk->security; | ||
69 | *sid = tsec->sid; | ||
70 | return; | ||
71 | } | ||
72 | *sid = 0; | ||
73 | } | ||
74 | |||
75 | int selinux_string_to_sid(char *str, u32 *sid) | ||
76 | { | ||
77 | if (selinux_enabled) | ||
78 | return security_context_to_sid(str, strlen(str), sid); | ||
79 | else { | ||
80 | *sid = 0; | ||
81 | return 0; | ||
82 | } | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(selinux_string_to_sid); | ||
85 | |||
86 | int selinux_relabel_packet_permission(u32 sid) | ||
87 | { | ||
88 | if (selinux_enabled) { | ||
89 | struct task_security_struct *tsec = current->security; | ||
90 | |||
91 | return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET, | ||
92 | PACKET__RELABELTO, NULL); | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission); | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b61b9554bc27..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; |
@@ -101,6 +102,8 @@ static int __init selinux_enabled_setup(char *str) | |||
101 | return 1; | 102 | return 1; |
102 | } | 103 | } |
103 | __setup("selinux=", selinux_enabled_setup); | 104 | __setup("selinux=", selinux_enabled_setup); |
105 | #else | ||
106 | int selinux_enabled = 1; | ||
104 | #endif | 107 | #endif |
105 | 108 | ||
106 | /* Original (dummy) security module. */ | 109 | /* Original (dummy) security module. */ |
@@ -694,6 +697,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
694 | return SECCLASS_PACKET_SOCKET; | 697 | return SECCLASS_PACKET_SOCKET; |
695 | case PF_KEY: | 698 | case PF_KEY: |
696 | return SECCLASS_KEY_SOCKET; | 699 | return SECCLASS_KEY_SOCKET; |
700 | case PF_APPLETALK: | ||
701 | return SECCLASS_APPLETALK_SOCKET; | ||
697 | } | 702 | } |
698 | 703 | ||
699 | return SECCLASS_SOCKET; | 704 | return SECCLASS_SOCKET; |
@@ -3212,47 +3217,17 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3212 | return 0; | 3217 | return 0; |
3213 | } | 3218 | } |
3214 | 3219 | ||
3215 | 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) | ||
3216 | { | 3223 | { |
3217 | u16 family; | 3224 | int err = 0; |
3218 | char *addrp; | ||
3219 | int len, err = 0; | ||
3220 | 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; |
3221 | u32 sock_sid = 0; | ||
3222 | u16 sock_class = 0; | ||
3223 | struct socket *sock; | ||
3224 | struct net_device *dev; | ||
3225 | struct avc_audit_data ad; | ||
3226 | 3226 | ||
3227 | family = sk->sk_family; | 3227 | if (!skb->dev) |
3228 | if (family != PF_INET && family != PF_INET6) | ||
3229 | goto out; | 3228 | goto out; |
3230 | 3229 | ||
3231 | /* Handle mapped IPv4 packets arriving via IPv6 sockets */ | 3230 | err = sel_netif_sids(skb->dev, &if_sid, NULL); |
3232 | if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) | ||
3233 | family = PF_INET; | ||
3234 | |||
3235 | read_lock_bh(&sk->sk_callback_lock); | ||
3236 | sock = sk->sk_socket; | ||
3237 | if (sock) { | ||
3238 | struct inode *inode; | ||
3239 | inode = SOCK_INODE(sock); | ||
3240 | if (inode) { | ||
3241 | struct inode_security_struct *isec; | ||
3242 | isec = inode->i_security; | ||
3243 | sock_sid = isec->sid; | ||
3244 | sock_class = isec->sclass; | ||
3245 | } | ||
3246 | } | ||
3247 | read_unlock_bh(&sk->sk_callback_lock); | ||
3248 | if (!sock_sid) | ||
3249 | goto out; | ||
3250 | |||
3251 | dev = skb->dev; | ||
3252 | if (!dev) | ||
3253 | goto out; | ||
3254 | |||
3255 | err = sel_netif_sids(dev, &if_sid, NULL); | ||
3256 | if (err) | 3231 | if (err) |
3257 | goto out; | 3232 | goto out; |
3258 | 3233 | ||
@@ -3275,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3275 | break; | 3250 | break; |
3276 | } | 3251 | } |
3277 | 3252 | ||
3278 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3253 | err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); |
3279 | ad.u.net.netif = dev->name; | ||
3280 | ad.u.net.family = family; | ||
3281 | |||
3282 | err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); | ||
3283 | if (err) | ||
3284 | goto out; | ||
3285 | |||
3286 | err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad); | ||
3287 | if (err) | 3254 | if (err) |
3288 | goto out; | 3255 | goto out; |
3289 | 3256 | ||
3290 | /* Fixme: this lookup is inefficient */ | ||
3291 | err = security_node_sid(family, addrp, len, &node_sid); | 3257 | err = security_node_sid(family, addrp, len, &node_sid); |
3292 | if (err) | 3258 | if (err) |
3293 | goto out; | 3259 | goto out; |
3294 | 3260 | ||
3295 | 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); |
3296 | if (err) | 3262 | if (err) |
3297 | goto out; | 3263 | goto out; |
3298 | 3264 | ||
3299 | if (recv_perm) { | 3265 | if (recv_perm) { |
3300 | u32 port_sid; | 3266 | u32 port_sid; |
3301 | 3267 | ||
3302 | /* Fixme: make this more efficient */ | ||
3303 | err = security_port_sid(sk->sk_family, sk->sk_type, | 3268 | err = security_port_sid(sk->sk_family, sk->sk_type, |
3304 | sk->sk_protocol, ntohs(ad.u.net.sport), | 3269 | sk->sk_protocol, ntohs(ad->u.net.sport), |
3305 | &port_sid); | 3270 | &port_sid); |
3306 | if (err) | 3271 | if (err) |
3307 | goto out; | 3272 | goto out; |
3308 | 3273 | ||
3309 | err = avc_has_perm(sock_sid, port_sid, | 3274 | err = avc_has_perm(sock_sid, port_sid, |
3310 | sock_class, recv_perm, &ad); | 3275 | sock_class, recv_perm, ad); |
3311 | } | 3276 | } |
3312 | 3277 | ||
3313 | if (!err) | 3278 | out: |
3314 | 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; | ||
3315 | 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; | ||
3333 | |||
3334 | err = selinux_xfrm_sock_rcv_skb(sock_sid, skb); | ||
3316 | out: | 3335 | out: |
3317 | return err; | 3336 | return err; |
3318 | } | 3337 | } |
@@ -3452,42 +3471,18 @@ out: | |||
3452 | 3471 | ||
3453 | #ifdef CONFIG_NETFILTER | 3472 | #ifdef CONFIG_NETFILTER |
3454 | 3473 | ||
3455 | 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, |
3456 | struct sk_buff **pskb, | 3475 | struct inode_security_struct *isec, |
3457 | const struct net_device *in, | 3476 | struct avc_audit_data *ad, |
3458 | const struct net_device *out, | 3477 | u16 family, char *addrp, int len) |
3459 | int (*okfn)(struct sk_buff *), | ||
3460 | u16 family) | ||
3461 | { | 3478 | { |
3462 | char *addrp; | 3479 | int err; |
3463 | int len, err = NF_ACCEPT; | ||
3464 | 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; |
3465 | struct sock *sk; | ||
3466 | struct socket *sock; | ||
3467 | struct inode *inode; | ||
3468 | struct sk_buff *skb = *pskb; | ||
3469 | struct inode_security_struct *isec; | ||
3470 | struct avc_audit_data ad; | ||
3471 | struct net_device *dev = (struct net_device *)out; | ||
3472 | 3481 | ||
3473 | sk = skb->sk; | ||
3474 | if (!sk) | ||
3475 | goto out; | ||
3476 | |||
3477 | sock = sk->sk_socket; | ||
3478 | if (!sock) | ||
3479 | goto out; | ||
3480 | |||
3481 | inode = SOCK_INODE(sock); | ||
3482 | if (!inode) | ||
3483 | goto out; | ||
3484 | |||
3485 | err = sel_netif_sids(dev, &if_sid, NULL); | 3482 | err = sel_netif_sids(dev, &if_sid, NULL); |
3486 | if (err) | 3483 | if (err) |
3487 | goto out; | 3484 | goto out; |
3488 | 3485 | ||
3489 | isec = inode->i_security; | ||
3490 | |||
3491 | switch (isec->sclass) { | 3486 | switch (isec->sclass) { |
3492 | case SECCLASS_UDP_SOCKET: | 3487 | case SECCLASS_UDP_SOCKET: |
3493 | netif_perm = NETIF__UDP_SEND; | 3488 | netif_perm = NETIF__UDP_SEND; |
@@ -3507,55 +3502,88 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
3507 | break; | 3502 | break; |
3508 | } | 3503 | } |
3509 | 3504 | ||
3510 | 3505 | err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad); | |
3511 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3506 | if (err) |
3512 | ad.u.net.netif = dev->name; | ||
3513 | ad.u.net.family = family; | ||
3514 | |||
3515 | err = selinux_parse_skb(skb, &ad, &addrp, | ||
3516 | &len, 0) ? NF_DROP : NF_ACCEPT; | ||
3517 | if (err != NF_ACCEPT) | ||
3518 | goto out; | ||
3519 | |||
3520 | err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, | ||
3521 | netif_perm, &ad) ? NF_DROP : NF_ACCEPT; | ||
3522 | if (err != NF_ACCEPT) | ||
3523 | goto out; | 3507 | goto out; |
3524 | 3508 | ||
3525 | /* Fixme: this lookup is inefficient */ | 3509 | err = security_node_sid(family, addrp, len, &node_sid); |
3526 | err = security_node_sid(family, addrp, len, | 3510 | if (err) |
3527 | &node_sid) ? NF_DROP : NF_ACCEPT; | ||
3528 | if (err != NF_ACCEPT) | ||
3529 | goto out; | 3511 | goto out; |
3530 | 3512 | ||
3531 | err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, | 3513 | err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad); |
3532 | node_perm, &ad) ? NF_DROP : NF_ACCEPT; | 3514 | if (err) |
3533 | if (err != NF_ACCEPT) | ||
3534 | goto out; | 3515 | goto out; |
3535 | 3516 | ||
3536 | if (send_perm) { | 3517 | if (send_perm) { |
3537 | u32 port_sid; | 3518 | u32 port_sid; |
3538 | 3519 | ||
3539 | /* Fixme: make this more efficient */ | ||
3540 | err = security_port_sid(sk->sk_family, | 3520 | err = security_port_sid(sk->sk_family, |
3541 | sk->sk_type, | 3521 | sk->sk_type, |
3542 | sk->sk_protocol, | 3522 | sk->sk_protocol, |
3543 | ntohs(ad.u.net.dport), | 3523 | ntohs(ad->u.net.dport), |
3544 | &port_sid) ? NF_DROP : NF_ACCEPT; | 3524 | &port_sid); |
3545 | if (err != NF_ACCEPT) | 3525 | if (err) |
3546 | goto out; | 3526 | goto out; |
3547 | 3527 | ||
3548 | err = avc_has_perm(isec->sid, port_sid, isec->sclass, | 3528 | err = avc_has_perm(isec->sid, port_sid, isec->sclass, |
3549 | send_perm, &ad) ? NF_DROP : NF_ACCEPT; | 3529 | send_perm, ad); |
3550 | } | 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; | ||
3551 | 3551 | ||
3552 | if (err != NF_ACCEPT) | 3552 | sk = skb->sk; |
3553 | if (!sk) | ||
3553 | goto out; | 3554 | goto out; |
3554 | 3555 | ||
3555 | 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; | ||
3556 | 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); | ||
3580 | |||
3581 | if (err) | ||
3582 | goto out; | ||
3583 | |||
3584 | err = selinux_xfrm_postroute_last(isec->sid, skb); | ||
3557 | out: | 3585 | out: |
3558 | return err; | 3586 | return err ? NF_DROP : NF_ACCEPT; |
3559 | } | 3587 | } |
3560 | 3588 | ||
3561 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, | 3589 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, |
@@ -4052,13 +4080,6 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | |||
4052 | return ipc_has_perm(ipcp, av); | 4080 | return ipc_has_perm(ipcp, av); |
4053 | } | 4081 | } |
4054 | 4082 | ||
4055 | static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size) | ||
4056 | { | ||
4057 | struct ipc_security_struct *isec = ipcp->security; | ||
4058 | |||
4059 | return selinux_getsecurity(isec->sid, buffer, size); | ||
4060 | } | ||
4061 | |||
4062 | /* module stacking operations */ | 4083 | /* module stacking operations */ |
4063 | static int selinux_register_security (const char *name, struct security_operations *ops) | 4084 | static int selinux_register_security (const char *name, struct security_operations *ops) |
4064 | { | 4085 | { |
@@ -4321,7 +4342,6 @@ static struct security_operations selinux_ops = { | |||
4321 | .task_to_inode = selinux_task_to_inode, | 4342 | .task_to_inode = selinux_task_to_inode, |
4322 | 4343 | ||
4323 | .ipc_permission = selinux_ipc_permission, | 4344 | .ipc_permission = selinux_ipc_permission, |
4324 | .ipc_getsecurity = selinux_ipc_getsecurity, | ||
4325 | 4345 | ||
4326 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, | 4346 | .msg_msg_alloc_security = selinux_msg_msg_alloc_security, |
4327 | .msg_msg_free_security = selinux_msg_msg_free_security, | 4347 | .msg_msg_free_security = selinux_msg_msg_free_security, |
@@ -4380,8 +4400,10 @@ static struct security_operations selinux_ops = { | |||
4380 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 4400 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
4381 | .xfrm_policy_clone_security = selinux_xfrm_policy_clone, | 4401 | .xfrm_policy_clone_security = selinux_xfrm_policy_clone, |
4382 | .xfrm_policy_free_security = selinux_xfrm_policy_free, | 4402 | .xfrm_policy_free_security = selinux_xfrm_policy_free, |
4403 | .xfrm_policy_delete_security = selinux_xfrm_policy_delete, | ||
4383 | .xfrm_state_alloc_security = selinux_xfrm_state_alloc, | 4404 | .xfrm_state_alloc_security = selinux_xfrm_state_alloc, |
4384 | .xfrm_state_free_security = selinux_xfrm_state_free, | 4405 | .xfrm_state_free_security = selinux_xfrm_state_free, |
4406 | .xfrm_state_delete_security = selinux_xfrm_state_delete, | ||
4385 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, | 4407 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, |
4386 | #endif | 4408 | #endif |
4387 | }; | 4409 | }; |
@@ -4428,6 +4450,7 @@ void selinux_complete_init(void) | |||
4428 | 4450 | ||
4429 | /* Set up any superblocks initialized prior to the policy load. */ | 4451 | /* Set up any superblocks initialized prior to the policy load. */ |
4430 | printk(KERN_INFO "SELinux: Setting up existing superblocks.\n"); | 4452 | printk(KERN_INFO "SELinux: Setting up existing superblocks.\n"); |
4453 | spin_lock(&sb_lock); | ||
4431 | spin_lock(&sb_security_lock); | 4454 | spin_lock(&sb_security_lock); |
4432 | next_sb: | 4455 | next_sb: |
4433 | if (!list_empty(&superblock_security_head)) { | 4456 | if (!list_empty(&superblock_security_head)) { |
@@ -4436,19 +4459,20 @@ next_sb: | |||
4436 | struct superblock_security_struct, | 4459 | struct superblock_security_struct, |
4437 | list); | 4460 | list); |
4438 | struct super_block *sb = sbsec->sb; | 4461 | struct super_block *sb = sbsec->sb; |
4439 | spin_lock(&sb_lock); | ||
4440 | sb->s_count++; | 4462 | sb->s_count++; |
4441 | spin_unlock(&sb_lock); | ||
4442 | spin_unlock(&sb_security_lock); | 4463 | spin_unlock(&sb_security_lock); |
4464 | spin_unlock(&sb_lock); | ||
4443 | down_read(&sb->s_umount); | 4465 | down_read(&sb->s_umount); |
4444 | if (sb->s_root) | 4466 | if (sb->s_root) |
4445 | superblock_doinit(sb, NULL); | 4467 | superblock_doinit(sb, NULL); |
4446 | drop_super(sb); | 4468 | drop_super(sb); |
4469 | spin_lock(&sb_lock); | ||
4447 | spin_lock(&sb_security_lock); | 4470 | spin_lock(&sb_security_lock); |
4448 | list_del_init(&sbsec->list); | 4471 | list_del_init(&sbsec->list); |
4449 | goto next_sb; | 4472 | goto next_sb; |
4450 | } | 4473 | } |
4451 | spin_unlock(&sb_security_lock); | 4474 | spin_unlock(&sb_security_lock); |
4475 | spin_unlock(&sb_lock); | ||
4452 | } | 4476 | } |
4453 | 4477 | ||
4454 | /* SELinux requires early initialization in order to label | 4478 | /* SELinux requires early initialization in order to label |
@@ -4543,6 +4567,7 @@ int selinux_disable(void) | |||
4543 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); | 4567 | printk(KERN_INFO "SELinux: Disabled at runtime.\n"); |
4544 | 4568 | ||
4545 | selinux_disabled = 1; | 4569 | selinux_disabled = 1; |
4570 | selinux_enabled = 0; | ||
4546 | 4571 | ||
4547 | /* Reset security_ops to the secondary module, dummy or capability. */ | 4572 | /* Reset security_ops to the secondary module, dummy or capability. */ |
4548 | security_ops = secondary_ops; | 4573 | security_ops = secondary_ops; |
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index b0e6b12931c9..a68fdd55597f 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h | |||
@@ -29,3 +29,4 @@ | |||
29 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) | 29 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) |
30 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) | 30 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) |
31 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) | 31 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) |
32 | S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 591e98d9315a..70ee65a58817 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -239,3 +239,6 @@ | |||
239 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") | 239 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") |
240 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") | 240 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") |
241 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") | 241 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") |
242 | S_(SECCLASS_PACKET, PACKET__SEND, "send") | ||
243 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") | ||
244 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index d7f02edf3930..1d9cf3d306bc 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -933,3 +933,29 @@ | |||
933 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL | 933 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL |
934 | #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL | 934 | #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL |
935 | 935 | ||
936 | #define APPLETALK_SOCKET__IOCTL 0x00000001UL | ||
937 | #define APPLETALK_SOCKET__READ 0x00000002UL | ||
938 | #define APPLETALK_SOCKET__WRITE 0x00000004UL | ||
939 | #define APPLETALK_SOCKET__CREATE 0x00000008UL | ||
940 | #define APPLETALK_SOCKET__GETATTR 0x00000010UL | ||
941 | #define APPLETALK_SOCKET__SETATTR 0x00000020UL | ||
942 | #define APPLETALK_SOCKET__LOCK 0x00000040UL | ||
943 | #define APPLETALK_SOCKET__RELABELFROM 0x00000080UL | ||
944 | #define APPLETALK_SOCKET__RELABELTO 0x00000100UL | ||
945 | #define APPLETALK_SOCKET__APPEND 0x00000200UL | ||
946 | #define APPLETALK_SOCKET__BIND 0x00000400UL | ||
947 | #define APPLETALK_SOCKET__CONNECT 0x00000800UL | ||
948 | #define APPLETALK_SOCKET__LISTEN 0x00001000UL | ||
949 | #define APPLETALK_SOCKET__ACCEPT 0x00002000UL | ||
950 | #define APPLETALK_SOCKET__GETOPT 0x00004000UL | ||
951 | #define APPLETALK_SOCKET__SETOPT 0x00008000UL | ||
952 | #define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL | ||
953 | #define APPLETALK_SOCKET__RECVFROM 0x00020000UL | ||
954 | #define APPLETALK_SOCKET__SENDTO 0x00040000UL | ||
955 | #define APPLETALK_SOCKET__RECV_MSG 0x00080000UL | ||
956 | #define APPLETALK_SOCKET__SEND_MSG 0x00100000UL | ||
957 | #define APPLETALK_SOCKET__NAME_BIND 0x00200000UL | ||
958 | |||
959 | #define PACKET__SEND 0x00000001UL | ||
960 | #define PACKET__RECV 0x00000002UL | ||
961 | #define PACKET__RELABELTO 0x00000004UL | ||
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 77b2c5996f35..3aec75fee4f7 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h | |||
@@ -58,3 +58,5 @@ | |||
58 | S_("nscd") | 58 | S_("nscd") |
59 | S_("association") | 59 | S_("association") |
60 | S_("netlink_kobject_uevent_socket") | 60 | S_("netlink_kobject_uevent_socket") |
61 | S_("appletalk_socket") | ||
62 | S_("packet") | ||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index eb9f50823f6e..a0eb9e281d18 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h | |||
@@ -60,6 +60,8 @@ | |||
60 | #define SECCLASS_NSCD 53 | 60 | #define SECCLASS_NSCD 53 |
61 | #define SECCLASS_ASSOCIATION 54 | 61 | #define SECCLASS_ASSOCIATION 54 |
62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 | 62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 |
63 | #define SECCLASS_APPLETALK_SOCKET 56 | ||
64 | #define SECCLASS_PACKET 57 | ||
63 | 65 | ||
64 | /* | 66 | /* |
65 | * Security identifier indices for initial entities | 67 | * Security identifier indices for initial entities |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 5f016c98056f..063af47bb231 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -29,12 +29,7 @@ | |||
29 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 29 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
30 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB | 30 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB |
31 | 31 | ||
32 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | ||
33 | extern int selinux_enabled; | 32 | extern int selinux_enabled; |
34 | #else | ||
35 | #define selinux_enabled 1 | ||
36 | #endif | ||
37 | |||
38 | extern int selinux_mls_enabled; | 33 | extern int selinux_mls_enabled; |
39 | 34 | ||
40 | int security_load_policy(void * data, size_t len); | 35 | int security_load_policy(void * data, size_t len); |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index c10f1fc41502..c96498a10eb8 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -9,8 +9,10 @@ | |||
9 | int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); | 9 | int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); |
10 | int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); | 10 | int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); |
11 | void selinux_xfrm_policy_free(struct xfrm_policy *xp); | 11 | void selinux_xfrm_policy_free(struct xfrm_policy *xp); |
12 | int selinux_xfrm_policy_delete(struct xfrm_policy *xp); | ||
12 | int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); | 13 | int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); |
13 | void selinux_xfrm_state_free(struct xfrm_state *x); | 14 | void selinux_xfrm_state_free(struct xfrm_state *x); |
15 | int selinux_xfrm_state_delete(struct xfrm_state *x); | ||
14 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir); | 16 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir); |
15 | 17 | ||
16 | /* | 18 | /* |
@@ -49,7 +51,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) | |||
49 | 51 | ||
50 | 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) |
51 | { | 53 | { |
52 | return NF_ACCEPT; | 54 | return 0; |
53 | } | 55 | } |
54 | 56 | ||
55 | 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/ss/mls.c b/security/selinux/ss/mls.c index 84047f69f9c1..7bc5b6440f70 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
10 | * | 10 | * |
11 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 11 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
@@ -385,6 +385,34 @@ out: | |||
385 | } | 385 | } |
386 | 386 | ||
387 | /* | 387 | /* |
388 | * Set the MLS fields in the security context structure | ||
389 | * `context' based on the string representation in | ||
390 | * the string `str'. This function will allocate temporary memory with the | ||
391 | * given constraints of gfp_mask. | ||
392 | */ | ||
393 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | ||
394 | { | ||
395 | char *tmpstr, *freestr; | ||
396 | int rc; | ||
397 | |||
398 | if (!selinux_mls_enabled) | ||
399 | return -EINVAL; | ||
400 | |||
401 | /* we need freestr because mls_context_to_sid will change | ||
402 | the value of tmpstr */ | ||
403 | tmpstr = freestr = kstrdup(str, gfp_mask); | ||
404 | if (!tmpstr) { | ||
405 | rc = -ENOMEM; | ||
406 | } else { | ||
407 | rc = mls_context_to_sid(':', &tmpstr, context, | ||
408 | NULL, SECSID_NULL); | ||
409 | kfree(freestr); | ||
410 | } | ||
411 | |||
412 | return rc; | ||
413 | } | ||
414 | |||
415 | /* | ||
388 | * Copies the effective MLS range from `src' into `dst'. | 416 | * Copies the effective MLS range from `src' into `dst'. |
389 | */ | 417 | */ |
390 | static inline int mls_scopy_context(struct context *dst, | 418 | static inline int mls_scopy_context(struct context *dst, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 03de697c8058..fbb42f07dd7c 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
10 | * | 10 | * |
11 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 11 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef _SS_MLS_H_ | 14 | #ifndef _SS_MLS_H_ |
@@ -27,6 +27,8 @@ int mls_context_to_sid(char oldc, | |||
27 | struct sidtab *s, | 27 | struct sidtab *s, |
28 | u32 def_sid); | 28 | u32 def_sid); |
29 | 29 | ||
30 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | ||
31 | |||
30 | int mls_convert_context(struct policydb *oldp, | 32 | int mls_convert_context(struct policydb *oldp, |
31 | struct policydb *newp, | 33 | struct policydb *newp, |
32 | struct context *context); | 34 | struct context *context); |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 61492485de84..c284dbb8b8c0 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -7,12 +7,13 @@ | |||
7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | 7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> |
8 | * | 8 | * |
9 | * Support for enhanced MLS infrastructure. | 9 | * Support for enhanced MLS infrastructure. |
10 | * Support for context based audit filters. | ||
10 | * | 11 | * |
11 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> | 12 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> |
12 | * | 13 | * |
13 | * Added conditional policy language extensions | 14 | * Added conditional policy language extensions |
14 | * | 15 | * |
15 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 16 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
16 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC | 17 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC |
17 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> | 18 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> |
18 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
@@ -593,6 +594,10 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) | |||
593 | 594 | ||
594 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; | 595 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; |
595 | scontextp = kmalloc(*scontext_len,GFP_ATOMIC); | 596 | scontextp = kmalloc(*scontext_len,GFP_ATOMIC); |
597 | if (!scontextp) { | ||
598 | rc = -ENOMEM; | ||
599 | goto out; | ||
600 | } | ||
596 | strcpy(scontextp, initial_sid_to_string[sid]); | 601 | strcpy(scontextp, initial_sid_to_string[sid]); |
597 | *scontext = scontextp; | 602 | *scontext = scontextp; |
598 | goto out; | 603 | goto out; |
@@ -1811,3 +1816,235 @@ out: | |||
1811 | POLICY_RDUNLOCK; | 1816 | POLICY_RDUNLOCK; |
1812 | return rc; | 1817 | return rc; |
1813 | } | 1818 | } |
1819 | |||
1820 | struct selinux_audit_rule { | ||
1821 | u32 au_seqno; | ||
1822 | struct context au_ctxt; | ||
1823 | }; | ||
1824 | |||
1825 | void selinux_audit_rule_free(struct selinux_audit_rule *rule) | ||
1826 | { | ||
1827 | if (rule) { | ||
1828 | context_destroy(&rule->au_ctxt); | ||
1829 | kfree(rule); | ||
1830 | } | ||
1831 | } | ||
1832 | |||
1833 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, | ||
1834 | struct selinux_audit_rule **rule) | ||
1835 | { | ||
1836 | struct selinux_audit_rule *tmprule; | ||
1837 | struct role_datum *roledatum; | ||
1838 | struct type_datum *typedatum; | ||
1839 | struct user_datum *userdatum; | ||
1840 | int rc = 0; | ||
1841 | |||
1842 | *rule = NULL; | ||
1843 | |||
1844 | if (!ss_initialized) | ||
1845 | return -ENOTSUPP; | ||
1846 | |||
1847 | switch (field) { | ||
1848 | case AUDIT_SE_USER: | ||
1849 | case AUDIT_SE_ROLE: | ||
1850 | case AUDIT_SE_TYPE: | ||
1851 | /* only 'equals' and 'not equals' fit user, role, and type */ | ||
1852 | if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) | ||
1853 | return -EINVAL; | ||
1854 | break; | ||
1855 | case AUDIT_SE_SEN: | ||
1856 | case AUDIT_SE_CLR: | ||
1857 | /* we do not allow a range, indicated by the presense of '-' */ | ||
1858 | if (strchr(rulestr, '-')) | ||
1859 | return -EINVAL; | ||
1860 | break; | ||
1861 | default: | ||
1862 | /* only the above fields are valid */ | ||
1863 | return -EINVAL; | ||
1864 | } | ||
1865 | |||
1866 | tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL); | ||
1867 | if (!tmprule) | ||
1868 | return -ENOMEM; | ||
1869 | |||
1870 | context_init(&tmprule->au_ctxt); | ||
1871 | |||
1872 | POLICY_RDLOCK; | ||
1873 | |||
1874 | tmprule->au_seqno = latest_granting; | ||
1875 | |||
1876 | switch (field) { | ||
1877 | case AUDIT_SE_USER: | ||
1878 | userdatum = hashtab_search(policydb.p_users.table, rulestr); | ||
1879 | if (!userdatum) | ||
1880 | rc = -EINVAL; | ||
1881 | else | ||
1882 | tmprule->au_ctxt.user = userdatum->value; | ||
1883 | break; | ||
1884 | case AUDIT_SE_ROLE: | ||
1885 | roledatum = hashtab_search(policydb.p_roles.table, rulestr); | ||
1886 | if (!roledatum) | ||
1887 | rc = -EINVAL; | ||
1888 | else | ||
1889 | tmprule->au_ctxt.role = roledatum->value; | ||
1890 | break; | ||
1891 | case AUDIT_SE_TYPE: | ||
1892 | typedatum = hashtab_search(policydb.p_types.table, rulestr); | ||
1893 | if (!typedatum) | ||
1894 | rc = -EINVAL; | ||
1895 | else | ||
1896 | tmprule->au_ctxt.type = typedatum->value; | ||
1897 | break; | ||
1898 | case AUDIT_SE_SEN: | ||
1899 | case AUDIT_SE_CLR: | ||
1900 | rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); | ||
1901 | break; | ||
1902 | } | ||
1903 | |||
1904 | POLICY_RDUNLOCK; | ||
1905 | |||
1906 | if (rc) { | ||
1907 | selinux_audit_rule_free(tmprule); | ||
1908 | tmprule = NULL; | ||
1909 | } | ||
1910 | |||
1911 | *rule = tmprule; | ||
1912 | |||
1913 | return rc; | ||
1914 | } | ||
1915 | |||
1916 | int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, | ||
1917 | struct selinux_audit_rule *rule, | ||
1918 | struct audit_context *actx) | ||
1919 | { | ||
1920 | struct context *ctxt; | ||
1921 | struct mls_level *level; | ||
1922 | int match = 0; | ||
1923 | |||
1924 | if (!rule) { | ||
1925 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
1926 | "selinux_audit_rule_match: missing rule\n"); | ||
1927 | return -ENOENT; | ||
1928 | } | ||
1929 | |||
1930 | POLICY_RDLOCK; | ||
1931 | |||
1932 | if (rule->au_seqno < latest_granting) { | ||
1933 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
1934 | "selinux_audit_rule_match: stale rule\n"); | ||
1935 | match = -ESTALE; | ||
1936 | goto out; | ||
1937 | } | ||
1938 | |||
1939 | ctxt = sidtab_search(&sidtab, ctxid); | ||
1940 | if (!ctxt) { | ||
1941 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
1942 | "selinux_audit_rule_match: unrecognized SID %d\n", | ||
1943 | ctxid); | ||
1944 | match = -ENOENT; | ||
1945 | goto out; | ||
1946 | } | ||
1947 | |||
1948 | /* a field/op pair that is not caught here will simply fall through | ||
1949 | without a match */ | ||
1950 | switch (field) { | ||
1951 | case AUDIT_SE_USER: | ||
1952 | switch (op) { | ||
1953 | case AUDIT_EQUAL: | ||
1954 | match = (ctxt->user == rule->au_ctxt.user); | ||
1955 | break; | ||
1956 | case AUDIT_NOT_EQUAL: | ||
1957 | match = (ctxt->user != rule->au_ctxt.user); | ||
1958 | break; | ||
1959 | } | ||
1960 | break; | ||
1961 | case AUDIT_SE_ROLE: | ||
1962 | switch (op) { | ||
1963 | case AUDIT_EQUAL: | ||
1964 | match = (ctxt->role == rule->au_ctxt.role); | ||
1965 | break; | ||
1966 | case AUDIT_NOT_EQUAL: | ||
1967 | match = (ctxt->role != rule->au_ctxt.role); | ||
1968 | break; | ||
1969 | } | ||
1970 | break; | ||
1971 | case AUDIT_SE_TYPE: | ||
1972 | switch (op) { | ||
1973 | case AUDIT_EQUAL: | ||
1974 | match = (ctxt->type == rule->au_ctxt.type); | ||
1975 | break; | ||
1976 | case AUDIT_NOT_EQUAL: | ||
1977 | match = (ctxt->type != rule->au_ctxt.type); | ||
1978 | break; | ||
1979 | } | ||
1980 | break; | ||
1981 | case AUDIT_SE_SEN: | ||
1982 | case AUDIT_SE_CLR: | ||
1983 | level = (op == AUDIT_SE_SEN ? | ||
1984 | &ctxt->range.level[0] : &ctxt->range.level[1]); | ||
1985 | switch (op) { | ||
1986 | case AUDIT_EQUAL: | ||
1987 | match = mls_level_eq(&rule->au_ctxt.range.level[0], | ||
1988 | level); | ||
1989 | break; | ||
1990 | case AUDIT_NOT_EQUAL: | ||
1991 | match = !mls_level_eq(&rule->au_ctxt.range.level[0], | ||
1992 | level); | ||
1993 | break; | ||
1994 | case AUDIT_LESS_THAN: | ||
1995 | match = (mls_level_dom(&rule->au_ctxt.range.level[0], | ||
1996 | level) && | ||
1997 | !mls_level_eq(&rule->au_ctxt.range.level[0], | ||
1998 | level)); | ||
1999 | break; | ||
2000 | case AUDIT_LESS_THAN_OR_EQUAL: | ||
2001 | match = mls_level_dom(&rule->au_ctxt.range.level[0], | ||
2002 | level); | ||
2003 | break; | ||
2004 | case AUDIT_GREATER_THAN: | ||
2005 | match = (mls_level_dom(level, | ||
2006 | &rule->au_ctxt.range.level[0]) && | ||
2007 | !mls_level_eq(level, | ||
2008 | &rule->au_ctxt.range.level[0])); | ||
2009 | break; | ||
2010 | case AUDIT_GREATER_THAN_OR_EQUAL: | ||
2011 | match = mls_level_dom(level, | ||
2012 | &rule->au_ctxt.range.level[0]); | ||
2013 | break; | ||
2014 | } | ||
2015 | } | ||
2016 | |||
2017 | out: | ||
2018 | POLICY_RDUNLOCK; | ||
2019 | return match; | ||
2020 | } | ||
2021 | |||
2022 | static int (*aurule_callback)(void) = NULL; | ||
2023 | |||
2024 | static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, | ||
2025 | u16 class, u32 perms, u32 *retained) | ||
2026 | { | ||
2027 | int err = 0; | ||
2028 | |||
2029 | if (event == AVC_CALLBACK_RESET && aurule_callback) | ||
2030 | err = aurule_callback(); | ||
2031 | return err; | ||
2032 | } | ||
2033 | |||
2034 | static int __init aurule_init(void) | ||
2035 | { | ||
2036 | int err; | ||
2037 | |||
2038 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | ||
2039 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | ||
2040 | if (err) | ||
2041 | panic("avc_add_callback() failed, error %d\n", err); | ||
2042 | |||
2043 | return err; | ||
2044 | } | ||
2045 | __initcall(aurule_init); | ||
2046 | |||
2047 | void selinux_audit_set_callback(int (*callback)(void)) | ||
2048 | { | ||
2049 | aurule_callback = callback; | ||
2050 | } | ||
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index abe99d881376..6633fb059313 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -132,10 +132,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_us | |||
132 | goto out; | 132 | goto out; |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * Does the subject have permission to set security or permission to | 135 | * Does the subject have permission to set security context? |
136 | * do the relabel? | ||
137 | * Must be permitted to relabel from default socket type (process type) | ||
138 | * to specified context | ||
139 | */ | 136 | */ |
140 | rc = avc_has_perm(tsec->sid, ctx->ctx_sid, | 137 | rc = avc_has_perm(tsec->sid, ctx->ctx_sid, |
141 | SECCLASS_ASSOCIATION, | 138 | SECCLASS_ASSOCIATION, |
@@ -201,6 +198,23 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp) | |||
201 | } | 198 | } |
202 | 199 | ||
203 | /* | 200 | /* |
201 | * LSM hook implementation that authorizes deletion of labeled policies. | ||
202 | */ | ||
203 | int selinux_xfrm_policy_delete(struct xfrm_policy *xp) | ||
204 | { | ||
205 | struct task_security_struct *tsec = current->security; | ||
206 | struct xfrm_sec_ctx *ctx = xp->security; | ||
207 | int rc = 0; | ||
208 | |||
209 | if (ctx) | ||
210 | rc = avc_has_perm(tsec->sid, ctx->ctx_sid, | ||
211 | SECCLASS_ASSOCIATION, | ||
212 | ASSOCIATION__SETCONTEXT, NULL); | ||
213 | |||
214 | return rc; | ||
215 | } | ||
216 | |||
217 | /* | ||
204 | * LSM hook implementation that allocs and transfers sec_ctx spec to | 218 | * LSM hook implementation that allocs and transfers sec_ctx spec to |
205 | * xfrm_state. | 219 | * xfrm_state. |
206 | */ | 220 | */ |
@@ -292,6 +306,23 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb) | |||
292 | return SECSID_NULL; | 306 | return SECSID_NULL; |
293 | } | 307 | } |
294 | 308 | ||
309 | /* | ||
310 | * LSM hook implementation that authorizes deletion of labeled SAs. | ||
311 | */ | ||
312 | int selinux_xfrm_state_delete(struct xfrm_state *x) | ||
313 | { | ||
314 | struct task_security_struct *tsec = current->security; | ||
315 | struct xfrm_sec_ctx *ctx = x->security; | ||
316 | int rc = 0; | ||
317 | |||
318 | if (ctx) | ||
319 | rc = avc_has_perm(tsec->sid, ctx->ctx_sid, | ||
320 | SECCLASS_ASSOCIATION, | ||
321 | ASSOCIATION__SETCONTEXT, NULL); | ||
322 | |||
323 | return rc; | ||
324 | } | ||
325 | |||
295 | /* | 326 | /* |
296 | * LSM hook that controls access to unlabelled packets. If | 327 | * LSM hook that controls access to unlabelled packets. If |
297 | * a xfrm_state is authorizable (defined by macro) then it was | 328 | * a xfrm_state is authorizable (defined by macro) then it was |
@@ -356,18 +387,12 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) | |||
356 | struct xfrm_state *x = dst_test->xfrm; | 387 | struct xfrm_state *x = dst_test->xfrm; |
357 | 388 | ||
358 | if (x && selinux_authorizable_xfrm(x)) | 389 | if (x && selinux_authorizable_xfrm(x)) |
359 | goto accept; | 390 | goto out; |
360 | } | 391 | } |
361 | } | 392 | } |
362 | 393 | ||
363 | rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, | 394 | rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, |
364 | ASSOCIATION__SENDTO, NULL); | 395 | ASSOCIATION__SENDTO, NULL); |
365 | if (rc) | 396 | out: |
366 | goto drop; | 397 | return rc; |
367 | |||
368 | accept: | ||
369 | return NF_ACCEPT; | ||
370 | |||
371 | drop: | ||
372 | return NF_DROP; | ||
373 | } | 398 | } |