aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c18
-rw-r--r--security/selinux/Kconfig29
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/avc.c13
-rw-r--r--security/selinux/exports.c96
-rw-r--r--security/selinux/hooks.c263
-rw-r--r--security/selinux/include/av_inherit.h1
-rw-r--r--security/selinux/include/av_perm_to_string.h3
-rw-r--r--security/selinux/include/av_permissions.h26
-rw-r--r--security/selinux/include/class_to_string.h2
-rw-r--r--security/selinux/include/flask.h2
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/selinux/include/xfrm.h4
-rw-r--r--security/selinux/selinuxfs.c66
-rw-r--r--security/selinux/ss/mls.c30
-rw-r--r--security/selinux/ss/mls.h4
-rw-r--r--security/selinux/ss/services.c239
-rw-r--r--security/selinux/xfrm.c51
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
566static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
567{
568 return -EOPNOTSUPP;
569}
570
571static int dummy_msg_msg_alloc_security (struct msg_msg *msg) 566static 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
813static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
814{
815 return 0;
816}
817
818static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) 818static 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
827static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
828{
829 return 0;
830}
831
827static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) 832static 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 @@
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/Makefile b/security/selinux/Makefile
index 688c0a267b62..faf2e02e4410 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ 5obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
6 6
7selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o 7selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
8 8
9selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o 9selinux-$(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:
800int avc_ss_reset(u32 seqno) 800int 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);
824out:
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
24void 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
33int 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
45void 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
55void 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
65void 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
75int 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}
84EXPORT_SYMBOL_GPL(selinux_string_to_sid);
85
86int 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}
96EXPORT_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
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;
@@ -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
106int 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
3215static 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)
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) 3278out:
3314 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;
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);
3316out: 3335out:
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
3455static unsigned int selinux_ip_postroute_last(unsigned int hooknum, 3474static 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 }
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;
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);
3557out: 3585out:
3558 return err; 3586 return err ? NF_DROP : NF_ACCEPT;
3559} 3587}
3560 3588
3561static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, 3589static 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
4055static 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 */
4063static int selinux_register_security (const char *name, struct security_operations *ops) 4084static 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);
4432next_sb: 4455next_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
33extern int selinux_enabled; 32extern int selinux_enabled;
34#else
35#define selinux_enabled 1
36#endif
37
38extern int selinux_mls_enabled; 33extern int selinux_mls_enabled;
39 34
40int security_load_policy(void * data, size_t len); 35int 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 @@
9int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); 9int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
10int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); 10int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
11void selinux_xfrm_policy_free(struct xfrm_policy *xp); 11void selinux_xfrm_policy_free(struct xfrm_policy *xp);
12int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
12int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); 13int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
13void selinux_xfrm_state_free(struct xfrm_state *x); 14void selinux_xfrm_state_free(struct xfrm_state *x);
15int selinux_xfrm_state_delete(struct xfrm_state *x);
14int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir); 16int 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
50static 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)
51{ 53{
52 return NF_ACCEPT; 54 return 0;
53} 55}
54 56
55static 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/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 */
393int 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 */
390static inline int mls_scopy_context(struct context *dst, 418static 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
30int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
31
30int mls_convert_context(struct policydb *oldp, 32int 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
1820struct selinux_audit_rule {
1821 u32 au_seqno;
1822 struct context au_ctxt;
1823};
1824
1825void 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
1833int 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
1916int 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
2017out:
2018 POLICY_RDUNLOCK;
2019 return match;
2020}
2021
2022static int (*aurule_callback)(void) = NULL;
2023
2024static 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
2034static 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
2047void 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 */
203int 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 */
312int 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) 396out:
366 goto drop; 397 return rc;
367
368accept:
369 return NF_ACCEPT;
370
371drop:
372 return NF_DROP;
373} 398}