aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-10-19 22:17:52 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-10-19 22:17:52 -0400
commit4cb40f795af36b3deb743f6ccf6c3fd542c61c8d (patch)
treedb3d7519932549bf528f5b8e4cb8350356cd544d /security
parent79ed2a9216dd3cc35c4f2c5dbaddadb195af83ac (diff)
parent0cfd81031a26717fe14380d18275f8e217571615 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: Documentation/kernel-parameters.txt arch/sh/include/asm/elf.h
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig8
-rw-r--r--security/Makefile3
-rw-r--r--security/commoncap.c2
-rw-r--r--security/inode.c36
-rw-r--r--security/security.c8
-rw-r--r--security/selinux/Kconfig3
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c296
-rw-r--r--security/selinux/include/avc.h4
-rw-r--r--security/selinux/include/netlabel.h44
-rw-r--r--security/selinux/include/objsec.h9
-rw-r--r--security/selinux/include/security.h15
-rw-r--r--security/selinux/netlabel.c280
-rw-r--r--security/selinux/ss/avtab.c8
-rw-r--r--security/selinux/ss/conditional.c18
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/ebitmap.c4
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/mls.c14
-rw-r--r--security/selinux/ss/policydb.c225
-rw-r--r--security/selinux/ss/policydb.h5
-rw-r--r--security/selinux/ss/services.c204
-rw-r--r--security/selinux/ss/sidtab.c12
-rw-r--r--security/smack/smack.h1
-rw-r--r--security/smack/smack_access.c10
-rw-r--r--security/smack/smack_lsm.c5
-rw-r--r--security/smack/smackfs.c96
27 files changed, 1082 insertions, 238 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 559293922a47..d9f47ce7e207 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -51,6 +51,14 @@ config SECURITY
51 51
52 If you are unsure how to answer this question, answer N. 52 If you are unsure how to answer this question, answer N.
53 53
54config SECURITYFS
55 bool "Enable the securityfs filesystem"
56 help
57 This will build the securityfs filesystem. It is currently used by
58 the TPM bios character driver. It is not used by SELinux or SMACK.
59
60 If you are unsure how to answer this question, answer N.
61
54config SECURITY_NETWORK 62config SECURITY_NETWORK
55 bool "Socket and Networking Security Hooks" 63 bool "Socket and Networking Security Hooks"
56 depends on SECURITY 64 depends on SECURITY
diff --git a/security/Makefile b/security/Makefile
index f65426099aa6..c05c127fff9a 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -10,7 +10,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
10obj-y += commoncap.o 10obj-y += commoncap.o
11 11
12# Object file lists 12# Object file lists
13obj-$(CONFIG_SECURITY) += security.o capability.o inode.o 13obj-$(CONFIG_SECURITY) += security.o capability.o
14obj-$(CONFIG_SECURITYFS) += inode.o
14# Must precede capability.o in order to stack properly. 15# Must precede capability.o in order to stack properly.
15obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
16obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 17obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
diff --git a/security/commoncap.c b/security/commoncap.c
index e4c4b3fc0c04..399bfdb9e2da 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -541,7 +541,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
541 * yet with increased caps. 541 * yet with increased caps.
542 * So we check for increased caps on the target process. 542 * So we check for increased caps on the target process.
543 */ 543 */
544static inline int cap_safe_nice(struct task_struct *p) 544static int cap_safe_nice(struct task_struct *p)
545{ 545{
546 if (!cap_issubset(p->cap_permitted, current->cap_permitted) && 546 if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
547 !capable(CAP_SYS_NICE)) 547 !capable(CAP_SYS_NICE))
diff --git a/security/inode.c b/security/inode.c
index acc6cf0d7900..efea5a605466 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -20,8 +20,7 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/namei.h> 21#include <linux/namei.h>
22#include <linux/security.h> 22#include <linux/security.h>
23 23#include <linux/magic.h>
24#define SECURITYFS_MAGIC 0x73636673
25 24
26static struct vfsmount *mount; 25static struct vfsmount *mount;
27static int mount_count; 26static int mount_count;
@@ -190,7 +189,7 @@ static int create_by_name(const char *name, mode_t mode,
190 * @name: a pointer to a string containing the name of the file to create. 189 * @name: a pointer to a string containing the name of the file to create.
191 * @mode: the permission that the file should have 190 * @mode: the permission that the file should have
192 * @parent: a pointer to the parent dentry for this file. This should be a 191 * @parent: a pointer to the parent dentry for this file. This should be a
193 * directory dentry if set. If this paramater is NULL, then the 192 * directory dentry if set. If this parameter is %NULL, then the
194 * file will be created in the root of the securityfs filesystem. 193 * file will be created in the root of the securityfs filesystem.
195 * @data: a pointer to something that the caller will want to get to later 194 * @data: a pointer to something that the caller will want to get to later
196 * on. The inode.i_private pointer will point to this value on 195 * on. The inode.i_private pointer will point to this value on
@@ -199,18 +198,18 @@ static int create_by_name(const char *name, mode_t mode,
199 * this file. 198 * this file.
200 * 199 *
201 * This is the basic "create a file" function for securityfs. It allows for a 200 * This is the basic "create a file" function for securityfs. It allows for a
202 * wide range of flexibility in createing a file, or a directory (if you 201 * wide range of flexibility in creating a file, or a directory (if you
203 * want to create a directory, the securityfs_create_dir() function is 202 * want to create a directory, the securityfs_create_dir() function is
204 * recommended to be used instead.) 203 * recommended to be used instead).
205 * 204 *
206 * This function will return a pointer to a dentry if it succeeds. This 205 * This function returns a pointer to a dentry if it succeeds. This
207 * pointer must be passed to the securityfs_remove() function when the file is 206 * pointer must be passed to the securityfs_remove() function when the file is
208 * to be removed (no automatic cleanup happens if your module is unloaded, 207 * to be removed (no automatic cleanup happens if your module is unloaded,
209 * you are responsible here.) If an error occurs, NULL will be returned. 208 * you are responsible here). If an error occurs, %NULL is returned.
210 * 209 *
211 * If securityfs is not enabled in the kernel, the value -ENODEV will be 210 * If securityfs is not enabled in the kernel, the value %-ENODEV is
212 * returned. It is not wise to check for this value, but rather, check for 211 * returned. It is not wise to check for this value, but rather, check for
213 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 212 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
214 * code. 213 * code.
215 */ 214 */
216struct dentry *securityfs_create_file(const char *name, mode_t mode, 215struct dentry *securityfs_create_file(const char *name, mode_t mode,
@@ -252,19 +251,19 @@ EXPORT_SYMBOL_GPL(securityfs_create_file);
252 * @name: a pointer to a string containing the name of the directory to 251 * @name: a pointer to a string containing the name of the directory to
253 * create. 252 * create.
254 * @parent: a pointer to the parent dentry for this file. This should be a 253 * @parent: a pointer to the parent dentry for this file. This should be a
255 * directory dentry if set. If this paramater is NULL, then the 254 * directory dentry if set. If this parameter is %NULL, then the
256 * directory will be created in the root of the securityfs filesystem. 255 * directory will be created in the root of the securityfs filesystem.
257 * 256 *
258 * This function creates a directory in securityfs with the given name. 257 * This function creates a directory in securityfs with the given @name.
259 * 258 *
260 * This function will return a pointer to a dentry if it succeeds. This 259 * This function returns a pointer to a dentry if it succeeds. This
261 * pointer must be passed to the securityfs_remove() function when the file is 260 * pointer must be passed to the securityfs_remove() function when the file is
262 * to be removed (no automatic cleanup happens if your module is unloaded, 261 * to be removed (no automatic cleanup happens if your module is unloaded,
263 * you are responsible here.) If an error occurs, NULL will be returned. 262 * you are responsible here). If an error occurs, %NULL will be returned.
264 * 263 *
265 * If securityfs is not enabled in the kernel, the value -ENODEV will be 264 * If securityfs is not enabled in the kernel, the value %-ENODEV is
266 * returned. It is not wise to check for this value, but rather, check for 265 * returned. It is not wise to check for this value, but rather, check for
267 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 266 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
268 * code. 267 * code.
269 */ 268 */
270struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) 269struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
@@ -278,16 +277,15 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir);
278/** 277/**
279 * securityfs_remove - removes a file or directory from the securityfs filesystem 278 * securityfs_remove - removes a file or directory from the securityfs filesystem
280 * 279 *
281 * @dentry: a pointer to a the dentry of the file or directory to be 280 * @dentry: a pointer to a the dentry of the file or directory to be removed.
282 * removed.
283 * 281 *
284 * This function removes a file or directory in securityfs that was previously 282 * This function removes a file or directory in securityfs that was previously
285 * created with a call to another securityfs function (like 283 * created with a call to another securityfs function (like
286 * securityfs_create_file() or variants thereof.) 284 * securityfs_create_file() or variants thereof.)
287 * 285 *
288 * This function is required to be called in order for the file to be 286 * This function is required to be called in order for the file to be
289 * removed, no automatic cleanup of files will happen when a module is 287 * removed. No automatic cleanup of files will happen when a module is
290 * removed, you are responsible here. 288 * removed; you are responsible here.
291 */ 289 */
292void securityfs_remove(struct dentry *dentry) 290void securityfs_remove(struct dentry *dentry)
293{ 291{
diff --git a/security/security.c b/security/security.c
index 3a4b4f55b33f..255b08559b2b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -82,8 +82,8 @@ __setup("security=", choose_lsm);
82 * 82 *
83 * Return true if: 83 * Return true if:
84 * -The passed LSM is the one chosen by user at boot time, 84 * -The passed LSM is the one chosen by user at boot time,
85 * -or user didsn't specify a specific LSM and we're the first to ask 85 * -or user didn't specify a specific LSM and we're the first to ask
86 * for registeration permissoin, 86 * for registration permission,
87 * -or the passed LSM is currently loaded. 87 * -or the passed LSM is currently loaded.
88 * Otherwise, return false. 88 * Otherwise, return false.
89 */ 89 */
@@ -101,13 +101,13 @@ int __init security_module_enable(struct security_operations *ops)
101 * register_security - registers a security framework with the kernel 101 * register_security - registers a security framework with the kernel
102 * @ops: a pointer to the struct security_options that is to be registered 102 * @ops: a pointer to the struct security_options that is to be registered
103 * 103 *
104 * This function is to allow a security module to register itself with the 104 * This function allows a security module to register itself with the
105 * kernel security subsystem. Some rudimentary checking is done on the @ops 105 * kernel security subsystem. Some rudimentary checking is done on the @ops
106 * value passed to this function. You'll need to check first if your LSM 106 * value passed to this function. You'll need to check first if your LSM
107 * is allowed to register its @ops by calling security_module_enable(@ops). 107 * is allowed to register its @ops by calling security_module_enable(@ops).
108 * 108 *
109 * If there is already a security module registered with the kernel, 109 * If there is already a security module registered with the kernel,
110 * an error will be returned. Otherwise 0 is returned on success. 110 * an error will be returned. Otherwise %0 is returned on success.
111 */ 111 */
112int register_security(struct security_operations *ops) 112int register_security(struct security_operations *ops)
113{ 113{
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index a436d1cfa88b..26301dd651d3 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -6,9 +6,6 @@ config SECURITY_SELINUX
6 help 6 help
7 This selects NSA Security-Enhanced Linux (SELinux). 7 This selects NSA Security-Enhanced Linux (SELinux).
8 You will also need a policy configuration and a labeled filesystem. 8 You will also need a policy configuration and a labeled filesystem.
9 You can obtain the policy compiler (checkpolicy), the utility for
10 labeling filesystems (setfiles), and an example policy configuration
11 from <http://www.nsa.gov/selinux/>.
12 If you are unsure how to answer this question, answer N. 9 If you are unsure how to answer this question, answer N.
13 10
14config SECURITY_SELINUX_BOOTPARAM 11config SECURITY_SELINUX_BOOTPARAM
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 114b4b4c97b2..cb30c7e350b3 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
136 * @tclass: target security class 136 * @tclass: target security class
137 * @av: access vector 137 * @av: access vector
138 */ 138 */
139static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 139void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
140{ 140{
141 const char **common_pts = NULL; 141 const char **common_pts = NULL;
142 u32 common_base = 0; 142 u32 common_base = 0;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 03fc6a81ae32..576e51199079 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -291,6 +291,7 @@ static void sk_free_security(struct sock *sk)
291 struct sk_security_struct *ssec = sk->sk_security; 291 struct sk_security_struct *ssec = sk->sk_security;
292 292
293 sk->sk_security = NULL; 293 sk->sk_security = NULL;
294 selinux_netlbl_sk_security_free(ssec);
294 kfree(ssec); 295 kfree(ssec);
295} 296}
296 297
@@ -324,7 +325,7 @@ enum {
324 Opt_rootcontext = 4, 325 Opt_rootcontext = 4,
325}; 326};
326 327
327static match_table_t tokens = { 328static const match_table_t tokens = {
328 {Opt_context, CONTEXT_STR "%s"}, 329 {Opt_context, CONTEXT_STR "%s"},
329 {Opt_fscontext, FSCONTEXT_STR "%s"}, 330 {Opt_fscontext, FSCONTEXT_STR "%s"},
330 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 331 {Opt_defcontext, DEFCONTEXT_STR "%s"},
@@ -957,7 +958,8 @@ out_err:
957 return rc; 958 return rc;
958} 959}
959 960
960void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) 961static void selinux_write_opts(struct seq_file *m,
962 struct security_mnt_opts *opts)
961{ 963{
962 int i; 964 int i;
963 char *prefix; 965 char *prefix;
@@ -1290,7 +1292,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1290 /* Default to the fs superblock SID. */ 1292 /* Default to the fs superblock SID. */
1291 isec->sid = sbsec->sid; 1293 isec->sid = sbsec->sid;
1292 1294
1293 if (sbsec->proc) { 1295 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
1294 struct proc_inode *proci = PROC_I(inode); 1296 struct proc_inode *proci = PROC_I(inode);
1295 if (proci->pde) { 1297 if (proci->pde) {
1296 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1298 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -2120,7 +2122,6 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2120 long j = -1; 2122 long j = -1;
2121 int drop_tty = 0; 2123 int drop_tty = 0;
2122 2124
2123 mutex_lock(&tty_mutex);
2124 tty = get_current_tty(); 2125 tty = get_current_tty();
2125 if (tty) { 2126 if (tty) {
2126 file_list_lock(); 2127 file_list_lock();
@@ -2138,8 +2139,8 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2138 } 2139 }
2139 } 2140 }
2140 file_list_unlock(); 2141 file_list_unlock();
2142 tty_kref_put(tty);
2141 } 2143 }
2142 mutex_unlock(&tty_mutex);
2143 /* Reset controlling tty. */ 2144 /* Reset controlling tty. */
2144 if (drop_tty) 2145 if (drop_tty)
2145 no_tty(); 2146 no_tty();
@@ -3548,38 +3549,44 @@ out:
3548#endif /* IPV6 */ 3549#endif /* IPV6 */
3549 3550
3550static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3551static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3551 char **addrp, int src, u8 *proto) 3552 char **_addrp, int src, u8 *proto)
3552{ 3553{
3553 int ret = 0; 3554 char *addrp;
3555 int ret;
3554 3556
3555 switch (ad->u.net.family) { 3557 switch (ad->u.net.family) {
3556 case PF_INET: 3558 case PF_INET:
3557 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3559 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3558 if (ret || !addrp) 3560 if (ret)
3559 break; 3561 goto parse_error;
3560 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3562 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3561 &ad->u.net.v4info.daddr); 3563 &ad->u.net.v4info.daddr);
3562 break; 3564 goto okay;
3563 3565
3564#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3566#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3565 case PF_INET6: 3567 case PF_INET6:
3566 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3568 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3567 if (ret || !addrp) 3569 if (ret)
3568 break; 3570 goto parse_error;
3569 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3571 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3570 &ad->u.net.v6info.daddr); 3572 &ad->u.net.v6info.daddr);
3571 break; 3573 goto okay;
3572#endif /* IPV6 */ 3574#endif /* IPV6 */
3573 default: 3575 default:
3574 break; 3576 addrp = NULL;
3577 goto okay;
3575 } 3578 }
3576 3579
3577 if (unlikely(ret)) 3580parse_error:
3578 printk(KERN_WARNING 3581 printk(KERN_WARNING
3579 "SELinux: failure in selinux_parse_skb()," 3582 "SELinux: failure in selinux_parse_skb(),"
3580 " unable to parse packet\n"); 3583 " unable to parse packet\n");
3581
3582 return ret; 3584 return ret;
3585
3586okay:
3587 if (_addrp)
3588 *_addrp = addrp;
3589 return 0;
3583} 3590}
3584 3591
3585/** 3592/**
@@ -3794,6 +3801,7 @@ out:
3794 3801
3795static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3802static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3796{ 3803{
3804 struct sock *sk = sock->sk;
3797 struct inode_security_struct *isec; 3805 struct inode_security_struct *isec;
3798 int err; 3806 int err;
3799 3807
@@ -3807,7 +3815,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3807 isec = SOCK_INODE(sock)->i_security; 3815 isec = SOCK_INODE(sock)->i_security;
3808 if (isec->sclass == SECCLASS_TCP_SOCKET || 3816 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3809 isec->sclass == SECCLASS_DCCP_SOCKET) { 3817 isec->sclass == SECCLASS_DCCP_SOCKET) {
3810 struct sock *sk = sock->sk;
3811 struct avc_audit_data ad; 3818 struct avc_audit_data ad;
3812 struct sockaddr_in *addr4 = NULL; 3819 struct sockaddr_in *addr4 = NULL;
3813 struct sockaddr_in6 *addr6 = NULL; 3820 struct sockaddr_in6 *addr6 = NULL;
@@ -3841,6 +3848,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3841 goto out; 3848 goto out;
3842 } 3849 }
3843 3850
3851 err = selinux_netlbl_socket_connect(sk, address);
3852
3844out: 3853out:
3845 return err; 3854 return err;
3846} 3855}
@@ -4070,20 +4079,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4070} 4079}
4071 4080
4072static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4081static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4073 struct avc_audit_data *ad, 4082 u16 family)
4074 u16 family, char *addrp)
4075{ 4083{
4076 int err; 4084 int err;
4077 struct sk_security_struct *sksec = sk->sk_security; 4085 struct sk_security_struct *sksec = sk->sk_security;
4078 u32 peer_sid; 4086 u32 peer_sid;
4079 u32 sk_sid = sksec->sid; 4087 u32 sk_sid = sksec->sid;
4088 struct avc_audit_data ad;
4089 char *addrp;
4090
4091 AVC_AUDIT_DATA_INIT(&ad, NET);
4092 ad.u.net.netif = skb->iif;
4093 ad.u.net.family = family;
4094 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4095 if (err)
4096 return err;
4080 4097
4081 if (selinux_compat_net) 4098 if (selinux_compat_net)
4082 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, 4099 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4083 family, addrp); 4100 family, addrp);
4084 else 4101 else
4085 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4102 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4086 PACKET__RECV, ad); 4103 PACKET__RECV, &ad);
4087 if (err) 4104 if (err)
4088 return err; 4105 return err;
4089 4106
@@ -4092,12 +4109,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4092 if (err) 4109 if (err)
4093 return err; 4110 return err;
4094 err = avc_has_perm(sk_sid, peer_sid, 4111 err = avc_has_perm(sk_sid, peer_sid,
4095 SECCLASS_PEER, PEER__RECV, ad); 4112 SECCLASS_PEER, PEER__RECV, &ad);
4113 if (err)
4114 selinux_netlbl_err(skb, err, 0);
4096 } else { 4115 } else {
4097 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); 4116 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4098 if (err) 4117 if (err)
4099 return err; 4118 return err;
4100 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); 4119 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
4101 } 4120 }
4102 4121
4103 return err; 4122 return err;
@@ -4111,6 +4130,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4111 u32 sk_sid = sksec->sid; 4130 u32 sk_sid = sksec->sid;
4112 struct avc_audit_data ad; 4131 struct avc_audit_data ad;
4113 char *addrp; 4132 char *addrp;
4133 u8 secmark_active;
4134 u8 peerlbl_active;
4114 4135
4115 if (family != PF_INET && family != PF_INET6) 4136 if (family != PF_INET && family != PF_INET6)
4116 return 0; 4137 return 0;
@@ -4119,6 +4140,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4119 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 4140 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4120 family = PF_INET; 4141 family = PF_INET;
4121 4142
4143 /* If any sort of compatibility mode is enabled then handoff processing
4144 * to the selinux_sock_rcv_skb_compat() function to deal with the
4145 * special handling. We do this in an attempt to keep this function
4146 * as fast and as clean as possible. */
4147 if (selinux_compat_net || !selinux_policycap_netpeer)
4148 return selinux_sock_rcv_skb_compat(sk, skb, family);
4149
4150 secmark_active = selinux_secmark_enabled();
4151 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4152 if (!secmark_active && !peerlbl_active)
4153 return 0;
4154
4122 AVC_AUDIT_DATA_INIT(&ad, NET); 4155 AVC_AUDIT_DATA_INIT(&ad, NET);
4123 ad.u.net.netif = skb->iif; 4156 ad.u.net.netif = skb->iif;
4124 ad.u.net.family = family; 4157 ad.u.net.family = family;
@@ -4126,15 +4159,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4126 if (err) 4159 if (err)
4127 return err; 4160 return err;
4128 4161
4129 /* If any sort of compatibility mode is enabled then handoff processing 4162 if (peerlbl_active) {
4130 * to the selinux_sock_rcv_skb_compat() function to deal with the
4131 * special handling. We do this in an attempt to keep this function
4132 * as fast and as clean as possible. */
4133 if (selinux_compat_net || !selinux_policycap_netpeer)
4134 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4135 family, addrp);
4136
4137 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4138 u32 peer_sid; 4163 u32 peer_sid;
4139 4164
4140 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4165 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4142,13 +4167,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4142 return err; 4167 return err;
4143 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, 4168 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4144 peer_sid, &ad); 4169 peer_sid, &ad);
4145 if (err) 4170 if (err) {
4171 selinux_netlbl_err(skb, err, 0);
4146 return err; 4172 return err;
4173 }
4147 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, 4174 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4148 PEER__RECV, &ad); 4175 PEER__RECV, &ad);
4176 if (err)
4177 selinux_netlbl_err(skb, err, 0);
4149 } 4178 }
4150 4179
4151 if (selinux_secmark_enabled()) { 4180 if (secmark_active) {
4152 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4181 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4153 PACKET__RECV, &ad); 4182 PACKET__RECV, &ad);
4154 if (err) 4183 if (err)
@@ -4207,10 +4236,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
4207 u32 peer_secid = SECSID_NULL; 4236 u32 peer_secid = SECSID_NULL;
4208 u16 family; 4237 u16 family;
4209 4238
4210 if (sock) 4239 if (skb && skb->protocol == htons(ETH_P_IP))
4240 family = PF_INET;
4241 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4242 family = PF_INET6;
4243 else if (sock)
4211 family = sock->sk->sk_family; 4244 family = sock->sk->sk_family;
4212 else if (skb && skb->sk)
4213 family = skb->sk->sk_family;
4214 else 4245 else
4215 goto out; 4246 goto out;
4216 4247
@@ -4268,8 +4299,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
4268 sk->sk_family == PF_UNIX) 4299 sk->sk_family == PF_UNIX)
4269 isec->sid = sksec->sid; 4300 isec->sid = sksec->sid;
4270 sksec->sclass = isec->sclass; 4301 sksec->sclass = isec->sclass;
4271
4272 selinux_netlbl_sock_graft(sk, parent);
4273} 4302}
4274 4303
4275static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, 4304static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
@@ -4277,10 +4306,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4277{ 4306{
4278 struct sk_security_struct *sksec = sk->sk_security; 4307 struct sk_security_struct *sksec = sk->sk_security;
4279 int err; 4308 int err;
4309 u16 family = sk->sk_family;
4280 u32 newsid; 4310 u32 newsid;
4281 u32 peersid; 4311 u32 peersid;
4282 4312
4283 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); 4313 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4314 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4315 family = PF_INET;
4316
4317 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
4284 if (err) 4318 if (err)
4285 return err; 4319 return err;
4286 if (peersid == SECSID_NULL) { 4320 if (peersid == SECSID_NULL) {
@@ -4315,12 +4349,18 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4315 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4349 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
4316} 4350}
4317 4351
4318static void selinux_inet_conn_established(struct sock *sk, 4352static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4319 struct sk_buff *skb)
4320{ 4353{
4354 u16 family = sk->sk_family;
4321 struct sk_security_struct *sksec = sk->sk_security; 4355 struct sk_security_struct *sksec = sk->sk_security;
4322 4356
4323 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); 4357 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4358 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4359 family = PF_INET;
4360
4361 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4362
4363 selinux_netlbl_inet_conn_established(sk, family);
4324} 4364}
4325 4365
4326static void selinux_req_classify_flow(const struct request_sock *req, 4366static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4370,39 +4410,54 @@ out:
4370static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, 4410static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4371 u16 family) 4411 u16 family)
4372{ 4412{
4413 int err;
4373 char *addrp; 4414 char *addrp;
4374 u32 peer_sid; 4415 u32 peer_sid;
4375 struct avc_audit_data ad; 4416 struct avc_audit_data ad;
4376 u8 secmark_active; 4417 u8 secmark_active;
4418 u8 netlbl_active;
4377 u8 peerlbl_active; 4419 u8 peerlbl_active;
4378 4420
4379 if (!selinux_policycap_netpeer) 4421 if (!selinux_policycap_netpeer)
4380 return NF_ACCEPT; 4422 return NF_ACCEPT;
4381 4423
4382 secmark_active = selinux_secmark_enabled(); 4424 secmark_active = selinux_secmark_enabled();
4383 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4425 netlbl_active = netlbl_enabled();
4426 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
4384 if (!secmark_active && !peerlbl_active) 4427 if (!secmark_active && !peerlbl_active)
4385 return NF_ACCEPT; 4428 return NF_ACCEPT;
4386 4429
4430 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4431 return NF_DROP;
4432
4387 AVC_AUDIT_DATA_INIT(&ad, NET); 4433 AVC_AUDIT_DATA_INIT(&ad, NET);
4388 ad.u.net.netif = ifindex; 4434 ad.u.net.netif = ifindex;
4389 ad.u.net.family = family; 4435 ad.u.net.family = family;
4390 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) 4436 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4391 return NF_DROP; 4437 return NF_DROP;
4392 4438
4393 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) 4439 if (peerlbl_active) {
4394 return NF_DROP; 4440 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4395 4441 peer_sid, &ad);
4396 if (peerlbl_active) 4442 if (err) {
4397 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, 4443 selinux_netlbl_err(skb, err, 1);
4398 peer_sid, &ad) != 0)
4399 return NF_DROP; 4444 return NF_DROP;
4445 }
4446 }
4400 4447
4401 if (secmark_active) 4448 if (secmark_active)
4402 if (avc_has_perm(peer_sid, skb->secmark, 4449 if (avc_has_perm(peer_sid, skb->secmark,
4403 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) 4450 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4404 return NF_DROP; 4451 return NF_DROP;
4405 4452
4453 if (netlbl_active)
4454 /* we do this in the FORWARD path and not the POST_ROUTING
4455 * path because we want to make sure we apply the necessary
4456 * labeling before IPsec is applied so we can leverage AH
4457 * protection */
4458 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4459 return NF_DROP;
4460
4406 return NF_ACCEPT; 4461 return NF_ACCEPT;
4407} 4462}
4408 4463
@@ -4426,6 +4481,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4426} 4481}
4427#endif /* IPV6 */ 4482#endif /* IPV6 */
4428 4483
4484static unsigned int selinux_ip_output(struct sk_buff *skb,
4485 u16 family)
4486{
4487 u32 sid;
4488
4489 if (!netlbl_enabled())
4490 return NF_ACCEPT;
4491
4492 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4493 * because we want to make sure we apply the necessary labeling
4494 * before IPsec is applied so we can leverage AH protection */
4495 if (skb->sk) {
4496 struct sk_security_struct *sksec = skb->sk->sk_security;
4497 sid = sksec->sid;
4498 } else
4499 sid = SECINITSID_KERNEL;
4500 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4501 return NF_DROP;
4502
4503 return NF_ACCEPT;
4504}
4505
4506static unsigned int selinux_ipv4_output(unsigned int hooknum,
4507 struct sk_buff *skb,
4508 const struct net_device *in,
4509 const struct net_device *out,
4510 int (*okfn)(struct sk_buff *))
4511{
4512 return selinux_ip_output(skb, PF_INET);
4513}
4514
4429static int selinux_ip_postroute_iptables_compat(struct sock *sk, 4515static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4430 int ifindex, 4516 int ifindex,
4431 struct avc_audit_data *ad, 4517 struct avc_audit_data *ad,
@@ -4493,30 +4579,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4493 4579
4494static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 4580static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4495 int ifindex, 4581 int ifindex,
4496 struct avc_audit_data *ad, 4582 u16 family)
4497 u16 family,
4498 char *addrp,
4499 u8 proto)
4500{ 4583{
4501 struct sock *sk = skb->sk; 4584 struct sock *sk = skb->sk;
4502 struct sk_security_struct *sksec; 4585 struct sk_security_struct *sksec;
4586 struct avc_audit_data ad;
4587 char *addrp;
4588 u8 proto;
4503 4589
4504 if (sk == NULL) 4590 if (sk == NULL)
4505 return NF_ACCEPT; 4591 return NF_ACCEPT;
4506 sksec = sk->sk_security; 4592 sksec = sk->sk_security;
4507 4593
4594 AVC_AUDIT_DATA_INIT(&ad, NET);
4595 ad.u.net.netif = ifindex;
4596 ad.u.net.family = family;
4597 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4598 return NF_DROP;
4599
4508 if (selinux_compat_net) { 4600 if (selinux_compat_net) {
4509 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, 4601 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4510 ad, family, addrp)) 4602 &ad, family, addrp))
4511 return NF_DROP; 4603 return NF_DROP;
4512 } else { 4604 } else {
4513 if (avc_has_perm(sksec->sid, skb->secmark, 4605 if (avc_has_perm(sksec->sid, skb->secmark,
4514 SECCLASS_PACKET, PACKET__SEND, ad)) 4606 SECCLASS_PACKET, PACKET__SEND, &ad))
4515 return NF_DROP; 4607 return NF_DROP;
4516 } 4608 }
4517 4609
4518 if (selinux_policycap_netpeer) 4610 if (selinux_policycap_netpeer)
4519 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) 4611 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4520 return NF_DROP; 4612 return NF_DROP;
4521 4613
4522 return NF_ACCEPT; 4614 return NF_ACCEPT;
@@ -4530,23 +4622,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4530 struct sock *sk; 4622 struct sock *sk;
4531 struct avc_audit_data ad; 4623 struct avc_audit_data ad;
4532 char *addrp; 4624 char *addrp;
4533 u8 proto;
4534 u8 secmark_active; 4625 u8 secmark_active;
4535 u8 peerlbl_active; 4626 u8 peerlbl_active;
4536 4627
4537 AVC_AUDIT_DATA_INIT(&ad, NET);
4538 ad.u.net.netif = ifindex;
4539 ad.u.net.family = family;
4540 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4541 return NF_DROP;
4542
4543 /* If any sort of compatibility mode is enabled then handoff processing 4628 /* If any sort of compatibility mode is enabled then handoff processing
4544 * to the selinux_ip_postroute_compat() function to deal with the 4629 * to the selinux_ip_postroute_compat() function to deal with the
4545 * special handling. We do this in an attempt to keep this function 4630 * special handling. We do this in an attempt to keep this function
4546 * as fast and as clean as possible. */ 4631 * as fast and as clean as possible. */
4547 if (selinux_compat_net || !selinux_policycap_netpeer) 4632 if (selinux_compat_net || !selinux_policycap_netpeer)
4548 return selinux_ip_postroute_compat(skb, ifindex, &ad, 4633 return selinux_ip_postroute_compat(skb, ifindex, family);
4549 family, addrp, proto);
4550 4634
4551 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4635 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4552 * packet transformation so allow the packet to pass without any checks 4636 * packet transformation so allow the packet to pass without any checks
@@ -4562,21 +4646,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4562 if (!secmark_active && !peerlbl_active) 4646 if (!secmark_active && !peerlbl_active)
4563 return NF_ACCEPT; 4647 return NF_ACCEPT;
4564 4648
4565 /* if the packet is locally generated (skb->sk != NULL) then use the 4649 /* if the packet is being forwarded then get the peer label from the
4566 * socket's label as the peer label, otherwise the packet is being 4650 * packet itself; otherwise check to see if it is from a local
4567 * forwarded through this system and we need to fetch the peer label 4651 * application or the kernel, if from an application get the peer label
4568 * directly from the packet */ 4652 * from the sending socket, otherwise use the kernel's sid */
4569 sk = skb->sk; 4653 sk = skb->sk;
4570 if (sk) { 4654 if (sk == NULL) {
4655 switch (family) {
4656 case PF_INET:
4657 if (IPCB(skb)->flags & IPSKB_FORWARDED)
4658 secmark_perm = PACKET__FORWARD_OUT;
4659 else
4660 secmark_perm = PACKET__SEND;
4661 break;
4662 case PF_INET6:
4663 if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
4664 secmark_perm = PACKET__FORWARD_OUT;
4665 else
4666 secmark_perm = PACKET__SEND;
4667 break;
4668 default:
4669 return NF_DROP;
4670 }
4671 if (secmark_perm == PACKET__FORWARD_OUT) {
4672 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4673 return NF_DROP;
4674 } else
4675 peer_sid = SECINITSID_KERNEL;
4676 } else {
4571 struct sk_security_struct *sksec = sk->sk_security; 4677 struct sk_security_struct *sksec = sk->sk_security;
4572 peer_sid = sksec->sid; 4678 peer_sid = sksec->sid;
4573 secmark_perm = PACKET__SEND; 4679 secmark_perm = PACKET__SEND;
4574 } else {
4575 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4576 return NF_DROP;
4577 secmark_perm = PACKET__FORWARD_OUT;
4578 } 4680 }
4579 4681
4682 AVC_AUDIT_DATA_INIT(&ad, NET);
4683 ad.u.net.netif = ifindex;
4684 ad.u.net.family = family;
4685 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
4686 return NF_DROP;
4687
4580 if (secmark_active) 4688 if (secmark_active)
4581 if (avc_has_perm(peer_sid, skb->secmark, 4689 if (avc_has_perm(peer_sid, skb->secmark,
4582 SECCLASS_PACKET, secmark_perm, &ad)) 4690 SECCLASS_PACKET, secmark_perm, &ad))
@@ -5219,8 +5327,12 @@ static int selinux_setprocattr(struct task_struct *p,
5219 5327
5220 if (sid == 0) 5328 if (sid == 0)
5221 return -EINVAL; 5329 return -EINVAL;
5222 5330 /*
5223 /* Only allow single threaded processes to change context */ 5331 * SELinux allows to change context in the following case only.
5332 * - Single threaded processes.
5333 * - Multi threaded processes intend to change its context into
5334 * more restricted domain (defined by TYPEBOUNDS statement).
5335 */
5224 if (atomic_read(&p->mm->mm_users) != 1) { 5336 if (atomic_read(&p->mm->mm_users) != 1) {
5225 struct task_struct *g, *t; 5337 struct task_struct *g, *t;
5226 struct mm_struct *mm = p->mm; 5338 struct mm_struct *mm = p->mm;
@@ -5228,11 +5340,16 @@ static int selinux_setprocattr(struct task_struct *p,
5228 do_each_thread(g, t) { 5340 do_each_thread(g, t) {
5229 if (t->mm == mm && t != p) { 5341 if (t->mm == mm && t != p) {
5230 read_unlock(&tasklist_lock); 5342 read_unlock(&tasklist_lock);
5231 return -EPERM; 5343 error = security_bounded_transition(tsec->sid, sid);
5344 if (!error)
5345 goto boundary_ok;
5346
5347 return error;
5232 } 5348 }
5233 } while_each_thread(g, t); 5349 } while_each_thread(g, t);
5234 read_unlock(&tasklist_lock); 5350 read_unlock(&tasklist_lock);
5235 } 5351 }
5352boundary_ok:
5236 5353
5237 /* Check permissions for the transition. */ 5354 /* Check permissions for the transition. */
5238 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, 5355 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
@@ -5641,6 +5758,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
5641 .pf = PF_INET, 5758 .pf = PF_INET,
5642 .hooknum = NF_INET_FORWARD, 5759 .hooknum = NF_INET_FORWARD,
5643 .priority = NF_IP_PRI_SELINUX_FIRST, 5760 .priority = NF_IP_PRI_SELINUX_FIRST,
5761 },
5762 {
5763 .hook = selinux_ipv4_output,
5764 .owner = THIS_MODULE,
5765 .pf = PF_INET,
5766 .hooknum = NF_INET_LOCAL_OUT,
5767 .priority = NF_IP_PRI_SELINUX_FIRST,
5644 } 5768 }
5645}; 5769};
5646 5770
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 7b9769f5e775..d12ff1a9c0aa 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -12,6 +12,7 @@
12#include <linux/kdev_t.h> 12#include <linux/kdev_t.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/audit.h>
15#include <linux/in6.h> 16#include <linux/in6.h>
16#include <linux/path.h> 17#include <linux/path.h>
17#include <asm/system.h> 18#include <asm/system.h>
@@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
126 u32 events, u32 ssid, u32 tsid, 127 u32 events, u32 ssid, u32 tsid,
127 u16 tclass, u32 perms); 128 u16 tclass, u32 perms);
128 129
130/* Shows permission in human readable form */
131void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
132
129/* Exported to selinuxfs */ 133/* Exported to selinuxfs */
130int avc_get_hash_stats(char *page); 134int avc_get_hash_stats(char *page);
131extern unsigned int avc_cache_threshold; 135extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 487a7d81fe20..b913c8d06038 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -39,6 +39,9 @@
39#ifdef CONFIG_NETLABEL 39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void); 40void selinux_netlbl_cache_invalidate(void);
41 41
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
42void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
43 int family); 46 int family);
44 47
@@ -46,8 +49,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
46 u16 family, 49 u16 family,
47 u32 *type, 50 u32 *type,
48 u32 *sid); 51 u32 *sid);
52int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family,
54 u32 sid);
49 55
50void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family);
51int selinux_netlbl_socket_post_create(struct socket *sock); 57int selinux_netlbl_socket_post_create(struct socket *sock);
52int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_inode_permission(struct inode *inode, int mask);
53int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -57,12 +63,27 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
57int selinux_netlbl_socket_setsockopt(struct socket *sock, 63int selinux_netlbl_socket_setsockopt(struct socket *sock,
58 int level, 64 int level,
59 int optname); 65 int optname);
66int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr);
67
60#else 68#else
61static inline void selinux_netlbl_cache_invalidate(void) 69static inline void selinux_netlbl_cache_invalidate(void)
62{ 70{
63 return; 71 return;
64} 72}
65 73
74static inline void selinux_netlbl_err(struct sk_buff *skb,
75 int error,
76 int gateway)
77{
78 return;
79}
80
81static inline void selinux_netlbl_sk_security_free(
82 struct sk_security_struct *ssec)
83{
84 return;
85}
86
66static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
67 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec,
68 int family) 89 int family)
@@ -79,9 +100,21 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
79 *sid = SECSID_NULL; 100 *sid = SECSID_NULL;
80 return 0; 101 return 0;
81} 102}
103static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
104 u16 family,
105 u32 sid)
106{
107 return 0;
108}
82 109
83static inline void selinux_netlbl_sock_graft(struct sock *sk, 110static inline int selinux_netlbl_conn_setsid(struct sock *sk,
84 struct socket *sock) 111 struct sockaddr *addr)
112{
113 return 0;
114}
115
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk,
117 u16 family)
85{ 118{
86 return; 119 return;
87} 120}
@@ -107,6 +140,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
107{ 140{
108 return 0; 141 return 0;
109} 142}
143static inline int selinux_netlbl_socket_connect(struct sock *sk,
144 struct sockaddr *addr)
145{
146 return 0;
147}
110#endif /* CONFIG_NETLABEL */ 148#endif /* CONFIG_NETLABEL */
111 149
112#endif 150#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91070ab874ce..f8be8d7fa26d 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -109,16 +109,19 @@ struct netport_security_struct {
109}; 109};
110 110
111struct sk_security_struct { 111struct sk_security_struct {
112 u32 sid; /* SID of this object */
113 u32 peer_sid; /* SID of peer */
114 u16 sclass; /* sock security class */
115#ifdef CONFIG_NETLABEL 112#ifdef CONFIG_NETLABEL
116 enum { /* NetLabel state */ 113 enum { /* NetLabel state */
117 NLBL_UNSET = 0, 114 NLBL_UNSET = 0,
118 NLBL_REQUIRE, 115 NLBL_REQUIRE,
119 NLBL_LABELED, 116 NLBL_LABELED,
117 NLBL_REQSKB,
118 NLBL_CONNLABELED,
120 } nlbl_state; 119 } nlbl_state;
120 struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
121#endif 121#endif
122 u32 sid; /* SID of this object */
123 u32 peer_sid; /* SID of peer */
124 u16 sclass; /* sock security class */
122}; 125};
123 126
124struct key_security_struct { 127struct key_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7c543003d653..72447370bc95 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -27,13 +27,14 @@
27#define POLICYDB_VERSION_RANGETRANS 21 27#define POLICYDB_VERSION_RANGETRANS 21
28#define POLICYDB_VERSION_POLCAP 22 28#define POLICYDB_VERSION_POLCAP 22
29#define POLICYDB_VERSION_PERMISSIVE 23 29#define POLICYDB_VERSION_PERMISSIVE 23
30#define POLICYDB_VERSION_BOUNDARY 24
30 31
31/* Range of policy versions we understand*/ 32/* Range of policy versions we understand*/
32#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 33#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
33#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 34#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
34#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 35#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
35#else 36#else
36#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE 37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
37#endif 38#endif
38 39
39#define CONTEXT_MNT 0x01 40#define CONTEXT_MNT 0x01
@@ -62,6 +63,16 @@ enum {
62extern int selinux_policycap_netpeer; 63extern int selinux_policycap_netpeer;
63extern int selinux_policycap_openperm; 64extern int selinux_policycap_openperm;
64 65
66/*
67 * type_datum properties
68 * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
69 */
70#define TYPEDATUM_PROPERTY_PRIMARY 0x0001
71#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002
72
73/* limitation of boundary depth */
74#define POLICYDB_BOUNDS_MAXDEPTH 4
75
65int security_load_policy(void *data, size_t len); 76int security_load_policy(void *data, size_t len);
66 77
67int security_policycap_supported(unsigned int req_cap); 78int security_policycap_supported(unsigned int req_cap);
@@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
117int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 128int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
118 u16 tclass); 129 u16 tclass);
119 130
131int security_bounded_transition(u32 oldsid, u32 newsid);
132
120int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 133int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
121 134
122int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, 135int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 89b418392f11..f58701a7b728 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -9,7 +9,7 @@
9 */ 9 */
10 10
11/* 11/*
12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
13 * 13 *
14 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
@@ -29,8 +29,12 @@
29 29
30#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/rcupdate.h> 31#include <linux/rcupdate.h>
32#include <linux/ip.h>
33#include <linux/ipv6.h>
32#include <net/sock.h> 34#include <net/sock.h>
33#include <net/netlabel.h> 35#include <net/netlabel.h>
36#include <net/ip.h>
37#include <net/ipv6.h>
34 38
35#include "objsec.h" 39#include "objsec.h"
36#include "security.h" 40#include "security.h"
@@ -64,32 +68,69 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
64} 68}
65 69
66/** 70/**
71 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
72 * @sk: the socket
73 *
74 * Description:
75 * Generate the NetLabel security attributes for a socket, making full use of
76 * the socket's attribute cache. Returns a pointer to the security attributes
77 * on success, NULL on failure.
78 *
79 */
80static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
81{
82 int rc;
83 struct sk_security_struct *sksec = sk->sk_security;
84 struct netlbl_lsm_secattr *secattr;
85
86 if (sksec->nlbl_secattr != NULL)
87 return sksec->nlbl_secattr;
88
89 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
90 if (secattr == NULL)
91 return NULL;
92 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
93 if (rc != 0) {
94 netlbl_secattr_free(secattr);
95 return NULL;
96 }
97 sksec->nlbl_secattr = secattr;
98
99 return secattr;
100}
101
102/**
67 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
68 * @sk: the socket to label 104 * @sk: the socket to label
69 * @sid: the SID to use
70 * 105 *
71 * Description: 106 * Description:
72 * Attempt to label a socket using the NetLabel mechanism using the given 107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
73 * SID. Returns zero values on success, negative values on failure. 108 * on success, negative values on failure.
74 * 109 *
75 */ 110 */
76static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) 111static int selinux_netlbl_sock_setsid(struct sock *sk)
77{ 112{
78 int rc; 113 int rc;
79 struct sk_security_struct *sksec = sk->sk_security; 114 struct sk_security_struct *sksec = sk->sk_security;
80 struct netlbl_lsm_secattr secattr; 115 struct netlbl_lsm_secattr *secattr;
81 116
82 netlbl_secattr_init(&secattr); 117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
83 119
84 rc = security_netlbl_sid_to_secattr(sid, &secattr); 120 secattr = selinux_netlbl_sock_genattr(sk);
85 if (rc != 0) 121 if (secattr == NULL)
86 goto sock_setsid_return; 122 return -ENOMEM;
87 rc = netlbl_sock_setattr(sk, &secattr); 123 rc = netlbl_sock_setattr(sk, secattr);
88 if (rc == 0) 124 switch (rc) {
125 case 0:
89 sksec->nlbl_state = NLBL_LABELED; 126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
90 133
91sock_setsid_return:
92 netlbl_secattr_destroy(&secattr);
93 return rc; 134 return rc;
94} 135}
95 136
@@ -106,6 +147,38 @@ void selinux_netlbl_cache_invalidate(void)
106} 147}
107 148
108/** 149/**
150 * selinux_netlbl_err - Handle a NetLabel packet error
151 * @skb: the packet
152 * @error: the error code
153 * @gateway: true if host is acting as a gateway, false otherwise
154 *
155 * Description:
156 * When a packet is dropped due to a call to avc_has_perm() pass the error
157 * code to the NetLabel subsystem so any protocol specific processing can be
158 * done. This is safe to call even if you are unsure if NetLabel labeling is
159 * present on the packet, NetLabel is smart enough to only act when it should.
160 *
161 */
162void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
163{
164 netlbl_skbuff_err(skb, error, gateway);
165}
166
167/**
168 * selinux_netlbl_sk_security_free - Free the NetLabel fields
169 * @sssec: the sk_security_struct
170 *
171 * Description:
172 * Free all of the memory in the NetLabel fields of a sk_security_struct.
173 *
174 */
175void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
176{
177 if (ssec->nlbl_secattr != NULL)
178 netlbl_secattr_free(ssec->nlbl_secattr);
179}
180
181/**
109 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
110 * @ssec: the sk_security_struct 183 * @ssec: the sk_security_struct
111 * @family: the socket family 184 * @family: the socket family
@@ -163,35 +236,118 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
163} 236}
164 237
165/** 238/**
166 * selinux_netlbl_sock_graft - Netlabel the new socket 239 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
240 * @skb: the packet
241 * @family: protocol family
242 * @sid: the SID
243 *
244 * Description
245 * Call the NetLabel mechanism to set the label of a packet using @sid.
246 * Returns zero on auccess, negative values on failure.
247 *
248 */
249int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
250 u16 family,
251 u32 sid)
252{
253 int rc;
254 struct netlbl_lsm_secattr secattr_storage;
255 struct netlbl_lsm_secattr *secattr = NULL;
256 struct sock *sk;
257
258 /* if this is a locally generated packet check to see if it is already
259 * being labeled by it's parent socket, if it is just exit */
260 sk = skb->sk;
261 if (sk != NULL) {
262 struct sk_security_struct *sksec = sk->sk_security;
263 if (sksec->nlbl_state != NLBL_REQSKB)
264 return 0;
265 secattr = sksec->nlbl_secattr;
266 }
267 if (secattr == NULL) {
268 secattr = &secattr_storage;
269 netlbl_secattr_init(secattr);
270 rc = security_netlbl_sid_to_secattr(sid, secattr);
271 if (rc != 0)
272 goto skbuff_setsid_return;
273 }
274
275 rc = netlbl_skbuff_setattr(skb, family, secattr);
276
277skbuff_setsid_return:
278 if (secattr == &secattr_storage)
279 netlbl_secattr_destroy(secattr);
280 return rc;
281}
282
283/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
167 * @sk: the new connection 285 * @sk: the new connection
168 * @sock: the new socket
169 * 286 *
170 * Description: 287 * Description:
171 * The connection represented by @sk is being grafted onto @sock so set the 288 * A new connection has been established on @sk so make sure it is labeled
172 * socket's NetLabel to match the SID of @sk. 289 * correctly with the NetLabel susbsystem.
173 * 290 *
174 */ 291 */
175void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) 292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
176{ 293{
294 int rc;
177 struct sk_security_struct *sksec = sk->sk_security; 295 struct sk_security_struct *sksec = sk->sk_security;
178 struct netlbl_lsm_secattr secattr; 296 struct netlbl_lsm_secattr *secattr;
179 u32 nlbl_peer_sid; 297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
180 299
181 if (sksec->nlbl_state != NLBL_REQUIRE) 300 if (sksec->nlbl_state != NLBL_REQUIRE)
182 return; 301 return;
183 302
184 netlbl_secattr_init(&secattr); 303 secattr = selinux_netlbl_sock_genattr(sk);
185 if (netlbl_sock_getattr(sk, &secattr) == 0 && 304 if (secattr == NULL)
186 secattr.flags != NETLBL_SECATTR_NONE && 305 return;
187 security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
188 sksec->peer_sid = nlbl_peer_sid;
189 netlbl_secattr_destroy(&secattr);
190 306
191 /* Try to set the NetLabel on the socket to save time later, if we fail 307 rc = netlbl_sock_setattr(sk, secattr);
192 * here we will pick up the pieces in later calls to 308 switch (rc) {
193 * selinux_netlbl_inode_permission(). */ 309 case 0:
194 selinux_netlbl_sock_setsid(sk, sksec->sid); 310 sksec->nlbl_state = NLBL_LABELED;
311 break;
312 case -EDESTADDRREQ:
313 /* no PF_INET6 support yet because we don't support any IPv6
314 * labeling protocols */
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
195} 351}
196 352
197/** 353/**
@@ -205,13 +361,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
205 */ 361 */
206int selinux_netlbl_socket_post_create(struct socket *sock) 362int selinux_netlbl_socket_post_create(struct socket *sock)
207{ 363{
208 struct sock *sk = sock->sk; 364 return selinux_netlbl_sock_setsid(sock->sk);
209 struct sk_security_struct *sksec = sk->sk_security;
210
211 if (sksec->nlbl_state != NLBL_REQUIRE)
212 return 0;
213
214 return selinux_netlbl_sock_setsid(sk, sksec->sid);
215} 365}
216 366
217/** 367/**
@@ -246,7 +396,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
246 local_bh_disable(); 396 local_bh_disable();
247 bh_lock_sock_nested(sk); 397 bh_lock_sock_nested(sk);
248 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 398 if (likely(sksec->nlbl_state == NLBL_REQUIRE))
249 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 399 rc = selinux_netlbl_sock_setsid(sk);
250 else 400 else
251 rc = 0; 401 rc = 0;
252 bh_unlock_sock(sk); 402 bh_unlock_sock(sk);
@@ -307,7 +457,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
307 return 0; 457 return 0;
308 458
309 if (nlbl_sid != SECINITSID_UNLABELED) 459 if (nlbl_sid != SECINITSID_UNLABELED)
310 netlbl_skbuff_err(skb, rc); 460 netlbl_skbuff_err(skb, rc, 0);
311 return rc; 461 return rc;
312} 462}
313 463
@@ -334,7 +484,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
334 struct netlbl_lsm_secattr secattr; 484 struct netlbl_lsm_secattr secattr;
335 485
336 if (level == IPPROTO_IP && optname == IP_OPTIONS && 486 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
337 sksec->nlbl_state == NLBL_LABELED) { 487 (sksec->nlbl_state == NLBL_LABELED ||
488 sksec->nlbl_state == NLBL_CONNLABELED)) {
338 netlbl_secattr_init(&secattr); 489 netlbl_secattr_init(&secattr);
339 lock_sock(sk); 490 lock_sock(sk);
340 rc = netlbl_sock_getattr(sk, &secattr); 491 rc = netlbl_sock_getattr(sk, &secattr);
@@ -346,3 +497,50 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
346 497
347 return rc; 498 return rc;
348} 499}
500
501/**
502 * selinux_netlbl_socket_connect - Label a client-side socket on connect
503 * @sk: the socket to label
504 * @addr: the destination address
505 *
506 * Description:
507 * Attempt to label a connected socket with NetLabel using the given address.
508 * Returns zero values on success, negative values on failure.
509 *
510 */
511int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
512{
513 int rc;
514 struct sk_security_struct *sksec = sk->sk_security;
515 struct netlbl_lsm_secattr *secattr;
516
517 if (sksec->nlbl_state != NLBL_REQSKB &&
518 sksec->nlbl_state != NLBL_CONNLABELED)
519 return 0;
520
521 local_bh_disable();
522 bh_lock_sock_nested(sk);
523
524 /* connected sockets are allowed to disconnect when the address family
525 * is set to AF_UNSPEC, if that is what is happening we want to reset
526 * the socket */
527 if (addr->sa_family == AF_UNSPEC) {
528 netlbl_sock_delattr(sk);
529 sksec->nlbl_state = NLBL_REQSKB;
530 rc = 0;
531 goto socket_connect_return;
532 }
533 secattr = selinux_netlbl_sock_genattr(sk);
534 if (secattr == NULL) {
535 rc = -ENOMEM;
536 goto socket_connect_return;
537 }
538 rc = netlbl_conn_setattr(sk, addr, secattr);
539 if (rc == 0)
540 sksec->nlbl_state = NLBL_CONNLABELED;
541
542socket_connect_return:
543 bh_unlock_sock(sk);
544 local_bh_enable();
545 return rc;
546}
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a1be97f8beea..1215b8e47dba 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -98,7 +98,7 @@ struct avtab_node *
98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) 98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
99{ 99{
100 int hvalue; 100 int hvalue;
101 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
103 103
104 if (!h || !h->htable) 104 if (!h || !h->htable)
@@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
122 key->target_class < cur->key.target_class) 122 key->target_class < cur->key.target_class)
123 break; 123 break;
124 } 124 }
125 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 125 return avtab_insert_node(h, hvalue, prev, cur, key, datum);
126
127 return newnode;
128} 126}
129 127
130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) 128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
@@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h)
231 229
232 for (i = 0; i < h->nslot; i++) { 230 for (i = 0; i < h->nslot; i++) {
233 cur = h->htable[i]; 231 cur = h->htable[i];
234 while (cur != NULL) { 232 while (cur) {
235 temp = cur; 233 temp = cur;
236 cur = cur->next; 234 cur = cur->next;
237 kmem_cache_free(avtab_node_cachep, temp); 235 kmem_cache_free(avtab_node_cachep, temp);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index fb4efe4f4bc8..4a4e35cac22b 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
29 int s[COND_EXPR_MAXDEPTH]; 29 int s[COND_EXPR_MAXDEPTH];
30 int sp = -1; 30 int sp = -1;
31 31
32 for (cur = expr; cur != NULL; cur = cur->next) { 32 for (cur = expr; cur; cur = cur->next) {
33 switch (cur->expr_type) { 33 switch (cur->expr_type) {
34 case COND_BOOL: 34 case COND_BOOL:
35 if (sp == (COND_EXPR_MAXDEPTH - 1)) 35 if (sp == (COND_EXPR_MAXDEPTH - 1))
@@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
97 if (new_state == -1) 97 if (new_state == -1)
98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); 98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
99 /* turn the rules on or off */ 99 /* turn the rules on or off */
100 for (cur = node->true_list; cur != NULL; cur = cur->next) { 100 for (cur = node->true_list; cur; cur = cur->next) {
101 if (new_state <= 0) 101 if (new_state <= 0)
102 cur->node->key.specified &= ~AVTAB_ENABLED; 102 cur->node->key.specified &= ~AVTAB_ENABLED;
103 else 103 else
104 cur->node->key.specified |= AVTAB_ENABLED; 104 cur->node->key.specified |= AVTAB_ENABLED;
105 } 105 }
106 106
107 for (cur = node->false_list; cur != NULL; cur = cur->next) { 107 for (cur = node->false_list; cur; cur = cur->next) {
108 /* -1 or 1 */ 108 /* -1 or 1 */
109 if (new_state) 109 if (new_state)
110 cur->node->key.specified &= ~AVTAB_ENABLED; 110 cur->node->key.specified &= ~AVTAB_ENABLED;
@@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p)
128static void cond_av_list_destroy(struct cond_av_list *list) 128static void cond_av_list_destroy(struct cond_av_list *list)
129{ 129{
130 struct cond_av_list *cur, *next; 130 struct cond_av_list *cur, *next;
131 for (cur = list; cur != NULL; cur = next) { 131 for (cur = list; cur; cur = next) {
132 next = cur->next; 132 next = cur->next;
133 /* the avtab_ptr_t node is destroy by the avtab */ 133 /* the avtab_ptr_t node is destroy by the avtab */
134 kfree(cur); 134 kfree(cur);
@@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node)
139{ 139{
140 struct cond_expr *cur_expr, *next_expr; 140 struct cond_expr *cur_expr, *next_expr;
141 141
142 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { 142 for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
143 next_expr = cur_expr->next; 143 next_expr = cur_expr->next;
144 kfree(cur_expr); 144 kfree(cur_expr);
145 } 145 }
@@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list)
155 if (list == NULL) 155 if (list == NULL)
156 return; 156 return;
157 157
158 for (cur = list; cur != NULL; cur = next) { 158 for (cur = list; cur; cur = next) {
159 next = cur->next; 159 next = cur->next;
160 cond_node_destroy(cur); 160 cond_node_destroy(cur);
161 } 161 }
@@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
239 rc = next_entry(key, fp, len); 239 rc = next_entry(key, fp, len);
240 if (rc < 0) 240 if (rc < 0)
241 goto err; 241 goto err;
242 key[len] = 0; 242 key[len] = '\0';
243 if (hashtab_insert(h, key, booldatum)) 243 if (hashtab_insert(h, key, booldatum))
244 goto err; 244 goto err;
245 245
@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
291 goto err; 291 goto err;
292 } 292 }
293 found = 0; 293 found = 0;
294 for (cur = other; cur != NULL; cur = cur->next) { 294 for (cur = other; cur; cur = cur->next) {
295 if (cur->node == node_ptr) { 295 if (cur->node == node_ptr) {
296 found = 1; 296 found = 1;
297 break; 297 break;
@@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
485 if (!ctab || !key || !avd) 485 if (!ctab || !key || !avd)
486 return; 486 return;
487 487
488 for (node = avtab_search_node(ctab, key); node != NULL; 488 for (node = avtab_search_node(ctab, key); node;
489 node = avtab_search_node_next(node, key->specified)) { 489 node = avtab_search_node_next(node, key->specified)) {
490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index 65b9f8366e9c..53ddb013ae57 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -28,7 +28,7 @@ struct cond_expr {
28#define COND_XOR 5 /* bool ^ bool */ 28#define COND_XOR 5 /* bool ^ bool */
29#define COND_EQ 6 /* bool == bool */ 29#define COND_EQ 6 /* bool == bool */
30#define COND_NEQ 7 /* bool != bool */ 30#define COND_NEQ 7 /* bool != bool */
31#define COND_LAST 8 31#define COND_LAST COND_NEQ
32 __u32 expr_type; 32 __u32 expr_type;
33 __u32 bool; 33 __u32 bool;
34 struct cond_expr *next; 34 struct cond_expr *next;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ddc275490af8..68c7348d1acc 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
109 *catmap = c_iter; 109 *catmap = c_iter;
110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); 110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
111 111
112 while (e_iter != NULL) { 112 while (e_iter) {
113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { 113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
114 unsigned int delta, e_startbit, c_endbit; 114 unsigned int delta, e_startbit, c_endbit;
115 115
@@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
197 } 197 }
198 } 198 }
199 c_iter = c_iter->next; 199 c_iter = c_iter->next;
200 } while (c_iter != NULL); 200 } while (c_iter);
201 if (e_iter != NULL) 201 if (e_iter != NULL)
202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; 202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
203 else 203 else
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 2e7788e13213..933e735bb185 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
81 81
82 hvalue = h->hash_value(h, key); 82 hvalue = h->hash_value(h, key);
83 cur = h->htable[hvalue]; 83 cur = h->htable[hvalue];
84 while (cur != NULL && h->keycmp(h, key, cur->key) > 0) 84 while (cur && h->keycmp(h, key, cur->key) > 0)
85 cur = cur->next; 85 cur = cur->next;
86 86
87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) 87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
@@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h)
100 100
101 for (i = 0; i < h->size; i++) { 101 for (i = 0; i < h->size; i++) {
102 cur = h->htable[i]; 102 cur = h->htable[i];
103 while (cur != NULL) { 103 while (cur) {
104 temp = cur; 104 temp = cur;
105 cur = cur->next; 105 cur = cur->next;
106 kfree(temp); 106 kfree(temp);
@@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h,
127 127
128 for (i = 0; i < h->size; i++) { 128 for (i = 0; i < h->size; i++) {
129 cur = h->htable[i]; 129 cur = h->htable[i];
130 while (cur != NULL) { 130 while (cur) {
131 ret = apply(cur->key, cur->datum, args); 131 ret = apply(cur->key, cur->datum, args);
132 if (ret) 132 if (ret)
133 return ret; 133 return ret;
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 77d745da48bb..b5407f16c2a4 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol,
283 p++; 283 p++;
284 284
285 delim = *p; 285 delim = *p;
286 if (delim != 0) 286 if (delim != '\0')
287 *p++ = 0; 287 *p++ = '\0';
288 288
289 for (l = 0; l < 2; l++) { 289 for (l = 0; l < 2; l++) {
290 levdatum = hashtab_search(pol->p_levels.table, scontextp); 290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
@@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol,
302 while (*p && *p != ',' && *p != '-') 302 while (*p && *p != ',' && *p != '-')
303 p++; 303 p++;
304 delim = *p; 304 delim = *p;
305 if (delim != 0) 305 if (delim != '\0')
306 *p++ = 0; 306 *p++ = '\0';
307 307
308 /* Separate into range if exists */ 308 /* Separate into range if exists */
309 rngptr = strchr(scontextp, '.'); 309 rngptr = strchr(scontextp, '.');
310 if (rngptr != NULL) { 310 if (rngptr != NULL) {
311 /* Remove '.' */ 311 /* Remove '.' */
312 *rngptr++ = 0; 312 *rngptr++ = '\0';
313 } 313 }
314 314
315 catdatum = hashtab_search(pol->p_cats.table, 315 catdatum = hashtab_search(pol->p_cats.table,
@@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol,
357 p++; 357 p++;
358 358
359 delim = *p; 359 delim = *p;
360 if (delim != 0) 360 if (delim != '\0')
361 *p++ = 0; 361 *p++ = '\0';
362 } else 362 } else
363 break; 363 break;
364 } 364 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 2391761ae422..72e4a54973aa 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/audit.h>
33#include "security.h" 34#include "security.h"
34 35
35#include "policydb.h" 36#include "policydb.h"
@@ -116,7 +117,12 @@ static struct policydb_compat_info policydb_compat[] = {
116 .version = POLICYDB_VERSION_PERMISSIVE, 117 .version = POLICYDB_VERSION_PERMISSIVE,
117 .sym_num = SYM_NUM, 118 .sym_num = SYM_NUM,
118 .ocon_num = OCON_NUM, 119 .ocon_num = OCON_NUM,
119 } 120 },
121 {
122 .version = POLICYDB_VERSION_BOUNDARY,
123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM,
125 },
120}; 126};
121 127
122static struct policydb_compat_info *policydb_lookup_compat(int version) 128static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -254,7 +260,9 @@ static int role_index(void *key, void *datum, void *datap)
254 260
255 role = datum; 261 role = datum;
256 p = datap; 262 p = datap;
257 if (!role->value || role->value > p->p_roles.nprim) 263 if (!role->value
264 || role->value > p->p_roles.nprim
265 || role->bounds > p->p_roles.nprim)
258 return -EINVAL; 266 return -EINVAL;
259 p->p_role_val_to_name[role->value - 1] = key; 267 p->p_role_val_to_name[role->value - 1] = key;
260 p->role_val_to_struct[role->value - 1] = role; 268 p->role_val_to_struct[role->value - 1] = role;
@@ -270,9 +278,12 @@ static int type_index(void *key, void *datum, void *datap)
270 p = datap; 278 p = datap;
271 279
272 if (typdatum->primary) { 280 if (typdatum->primary) {
273 if (!typdatum->value || typdatum->value > p->p_types.nprim) 281 if (!typdatum->value
282 || typdatum->value > p->p_types.nprim
283 || typdatum->bounds > p->p_types.nprim)
274 return -EINVAL; 284 return -EINVAL;
275 p->p_type_val_to_name[typdatum->value - 1] = key; 285 p->p_type_val_to_name[typdatum->value - 1] = key;
286 p->type_val_to_struct[typdatum->value - 1] = typdatum;
276 } 287 }
277 288
278 return 0; 289 return 0;
@@ -285,7 +296,9 @@ static int user_index(void *key, void *datum, void *datap)
285 296
286 usrdatum = datum; 297 usrdatum = datum;
287 p = datap; 298 p = datap;
288 if (!usrdatum->value || usrdatum->value > p->p_users.nprim) 299 if (!usrdatum->value
300 || usrdatum->value > p->p_users.nprim
301 || usrdatum->bounds > p->p_users.nprim)
289 return -EINVAL; 302 return -EINVAL;
290 p->p_user_val_to_name[usrdatum->value - 1] = key; 303 p->p_user_val_to_name[usrdatum->value - 1] = key;
291 p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 304 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
@@ -438,6 +451,14 @@ static int policydb_index_others(struct policydb *p)
438 goto out; 451 goto out;
439 } 452 }
440 453
454 p->type_val_to_struct =
455 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
456 GFP_KERNEL);
457 if (!p->type_val_to_struct) {
458 rc = -ENOMEM;
459 goto out;
460 }
461
441 if (cond_init_bool_indexes(p)) { 462 if (cond_init_bool_indexes(p)) {
442 rc = -ENOMEM; 463 rc = -ENOMEM;
443 goto out; 464 goto out;
@@ -625,6 +646,7 @@ void policydb_destroy(struct policydb *p)
625 kfree(p->class_val_to_struct); 646 kfree(p->class_val_to_struct);
626 kfree(p->role_val_to_struct); 647 kfree(p->role_val_to_struct);
627 kfree(p->user_val_to_struct); 648 kfree(p->user_val_to_struct);
649 kfree(p->type_val_to_struct);
628 650
629 avtab_destroy(&p->te_avtab); 651 avtab_destroy(&p->te_avtab);
630 652
@@ -932,7 +954,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
932 rc = next_entry(key, fp, len); 954 rc = next_entry(key, fp, len);
933 if (rc < 0) 955 if (rc < 0)
934 goto bad; 956 goto bad;
935 key[len] = 0; 957 key[len] = '\0';
936 958
937 rc = hashtab_insert(h, key, perdatum); 959 rc = hashtab_insert(h, key, perdatum);
938 if (rc) 960 if (rc)
@@ -979,7 +1001,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
979 rc = next_entry(key, fp, len); 1001 rc = next_entry(key, fp, len);
980 if (rc < 0) 1002 if (rc < 0)
981 goto bad; 1003 goto bad;
982 key[len] = 0; 1004 key[len] = '\0';
983 1005
984 for (i = 0; i < nel; i++) { 1006 for (i = 0; i < nel; i++) {
985 rc = perm_read(p, comdatum->permissions.table, fp); 1007 rc = perm_read(p, comdatum->permissions.table, fp);
@@ -1117,7 +1139,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1117 rc = next_entry(key, fp, len); 1139 rc = next_entry(key, fp, len);
1118 if (rc < 0) 1140 if (rc < 0)
1119 goto bad; 1141 goto bad;
1120 key[len] = 0; 1142 key[len] = '\0';
1121 1143
1122 if (len2) { 1144 if (len2) {
1123 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); 1145 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
@@ -1128,7 +1150,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1128 rc = next_entry(cladatum->comkey, fp, len2); 1150 rc = next_entry(cladatum->comkey, fp, len2);
1129 if (rc < 0) 1151 if (rc < 0)
1130 goto bad; 1152 goto bad;
1131 cladatum->comkey[len2] = 0; 1153 cladatum->comkey[len2] = '\0';
1132 1154
1133 cladatum->comdatum = hashtab_search(p->p_commons.table, 1155 cladatum->comdatum = hashtab_search(p->p_commons.table,
1134 cladatum->comkey); 1156 cladatum->comkey);
@@ -1176,8 +1198,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1176{ 1198{
1177 char *key = NULL; 1199 char *key = NULL;
1178 struct role_datum *role; 1200 struct role_datum *role;
1179 int rc; 1201 int rc, to_read = 2;
1180 __le32 buf[2]; 1202 __le32 buf[3];
1181 u32 len; 1203 u32 len;
1182 1204
1183 role = kzalloc(sizeof(*role), GFP_KERNEL); 1205 role = kzalloc(sizeof(*role), GFP_KERNEL);
@@ -1186,12 +1208,17 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1186 goto out; 1208 goto out;
1187 } 1209 }
1188 1210
1189 rc = next_entry(buf, fp, sizeof buf); 1211 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1212 to_read = 3;
1213
1214 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1190 if (rc < 0) 1215 if (rc < 0)
1191 goto bad; 1216 goto bad;
1192 1217
1193 len = le32_to_cpu(buf[0]); 1218 len = le32_to_cpu(buf[0]);
1194 role->value = le32_to_cpu(buf[1]); 1219 role->value = le32_to_cpu(buf[1]);
1220 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1221 role->bounds = le32_to_cpu(buf[2]);
1195 1222
1196 key = kmalloc(len + 1, GFP_KERNEL); 1223 key = kmalloc(len + 1, GFP_KERNEL);
1197 if (!key) { 1224 if (!key) {
@@ -1201,7 +1228,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1201 rc = next_entry(key, fp, len); 1228 rc = next_entry(key, fp, len);
1202 if (rc < 0) 1229 if (rc < 0)
1203 goto bad; 1230 goto bad;
1204 key[len] = 0; 1231 key[len] = '\0';
1205 1232
1206 rc = ebitmap_read(&role->dominates, fp); 1233 rc = ebitmap_read(&role->dominates, fp);
1207 if (rc) 1234 if (rc)
@@ -1236,8 +1263,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1236{ 1263{
1237 char *key = NULL; 1264 char *key = NULL;
1238 struct type_datum *typdatum; 1265 struct type_datum *typdatum;
1239 int rc; 1266 int rc, to_read = 3;
1240 __le32 buf[3]; 1267 __le32 buf[4];
1241 u32 len; 1268 u32 len;
1242 1269
1243 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); 1270 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
@@ -1246,13 +1273,27 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1246 return rc; 1273 return rc;
1247 } 1274 }
1248 1275
1249 rc = next_entry(buf, fp, sizeof buf); 1276 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1277 to_read = 4;
1278
1279 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1250 if (rc < 0) 1280 if (rc < 0)
1251 goto bad; 1281 goto bad;
1252 1282
1253 len = le32_to_cpu(buf[0]); 1283 len = le32_to_cpu(buf[0]);
1254 typdatum->value = le32_to_cpu(buf[1]); 1284 typdatum->value = le32_to_cpu(buf[1]);
1255 typdatum->primary = le32_to_cpu(buf[2]); 1285 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1286 u32 prop = le32_to_cpu(buf[2]);
1287
1288 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1289 typdatum->primary = 1;
1290 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1291 typdatum->attribute = 1;
1292
1293 typdatum->bounds = le32_to_cpu(buf[3]);
1294 } else {
1295 typdatum->primary = le32_to_cpu(buf[2]);
1296 }
1256 1297
1257 key = kmalloc(len + 1, GFP_KERNEL); 1298 key = kmalloc(len + 1, GFP_KERNEL);
1258 if (!key) { 1299 if (!key) {
@@ -1262,7 +1303,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1262 rc = next_entry(key, fp, len); 1303 rc = next_entry(key, fp, len);
1263 if (rc < 0) 1304 if (rc < 0)
1264 goto bad; 1305 goto bad;
1265 key[len] = 0; 1306 key[len] = '\0';
1266 1307
1267 rc = hashtab_insert(h, key, typdatum); 1308 rc = hashtab_insert(h, key, typdatum);
1268 if (rc) 1309 if (rc)
@@ -1309,8 +1350,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1309{ 1350{
1310 char *key = NULL; 1351 char *key = NULL;
1311 struct user_datum *usrdatum; 1352 struct user_datum *usrdatum;
1312 int rc; 1353 int rc, to_read = 2;
1313 __le32 buf[2]; 1354 __le32 buf[3];
1314 u32 len; 1355 u32 len;
1315 1356
1316 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); 1357 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
@@ -1319,12 +1360,17 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1319 goto out; 1360 goto out;
1320 } 1361 }
1321 1362
1322 rc = next_entry(buf, fp, sizeof buf); 1363 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1364 to_read = 3;
1365
1366 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1323 if (rc < 0) 1367 if (rc < 0)
1324 goto bad; 1368 goto bad;
1325 1369
1326 len = le32_to_cpu(buf[0]); 1370 len = le32_to_cpu(buf[0]);
1327 usrdatum->value = le32_to_cpu(buf[1]); 1371 usrdatum->value = le32_to_cpu(buf[1]);
1372 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1373 usrdatum->bounds = le32_to_cpu(buf[2]);
1328 1374
1329 key = kmalloc(len + 1, GFP_KERNEL); 1375 key = kmalloc(len + 1, GFP_KERNEL);
1330 if (!key) { 1376 if (!key) {
@@ -1334,7 +1380,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1334 rc = next_entry(key, fp, len); 1380 rc = next_entry(key, fp, len);
1335 if (rc < 0) 1381 if (rc < 0)
1336 goto bad; 1382 goto bad;
1337 key[len] = 0; 1383 key[len] = '\0';
1338 1384
1339 rc = ebitmap_read(&usrdatum->roles, fp); 1385 rc = ebitmap_read(&usrdatum->roles, fp);
1340 if (rc) 1386 if (rc)
@@ -1388,7 +1434,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1388 rc = next_entry(key, fp, len); 1434 rc = next_entry(key, fp, len);
1389 if (rc < 0) 1435 if (rc < 0)
1390 goto bad; 1436 goto bad;
1391 key[len] = 0; 1437 key[len] = '\0';
1392 1438
1393 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); 1439 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1394 if (!levdatum->level) { 1440 if (!levdatum->level) {
@@ -1440,7 +1486,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1440 rc = next_entry(key, fp, len); 1486 rc = next_entry(key, fp, len);
1441 if (rc < 0) 1487 if (rc < 0)
1442 goto bad; 1488 goto bad;
1443 key[len] = 0; 1489 key[len] = '\0';
1444 1490
1445 rc = hashtab_insert(h, key, catdatum); 1491 rc = hashtab_insert(h, key, catdatum);
1446 if (rc) 1492 if (rc)
@@ -1465,6 +1511,133 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp)
1465 cat_read, 1511 cat_read,
1466}; 1512};
1467 1513
1514static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1515{
1516 struct user_datum *upper, *user;
1517 struct policydb *p = datap;
1518 int depth = 0;
1519
1520 upper = user = datum;
1521 while (upper->bounds) {
1522 struct ebitmap_node *node;
1523 unsigned long bit;
1524
1525 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1526 printk(KERN_ERR "SELinux: user %s: "
1527 "too deep or looped boundary",
1528 (char *) key);
1529 return -EINVAL;
1530 }
1531
1532 upper = p->user_val_to_struct[upper->bounds - 1];
1533 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1534 if (ebitmap_get_bit(&upper->roles, bit))
1535 continue;
1536
1537 printk(KERN_ERR
1538 "SELinux: boundary violated policy: "
1539 "user=%s role=%s bounds=%s\n",
1540 p->p_user_val_to_name[user->value - 1],
1541 p->p_role_val_to_name[bit],
1542 p->p_user_val_to_name[upper->value - 1]);
1543
1544 return -EINVAL;
1545 }
1546 }
1547
1548 return 0;
1549}
1550
1551static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1552{
1553 struct role_datum *upper, *role;
1554 struct policydb *p = datap;
1555 int depth = 0;
1556
1557 upper = role = datum;
1558 while (upper->bounds) {
1559 struct ebitmap_node *node;
1560 unsigned long bit;
1561
1562 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1563 printk(KERN_ERR "SELinux: role %s: "
1564 "too deep or looped bounds\n",
1565 (char *) key);
1566 return -EINVAL;
1567 }
1568
1569 upper = p->role_val_to_struct[upper->bounds - 1];
1570 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1571 if (ebitmap_get_bit(&upper->types, bit))
1572 continue;
1573
1574 printk(KERN_ERR
1575 "SELinux: boundary violated policy: "
1576 "role=%s type=%s bounds=%s\n",
1577 p->p_role_val_to_name[role->value - 1],
1578 p->p_type_val_to_name[bit],
1579 p->p_role_val_to_name[upper->value - 1]);
1580
1581 return -EINVAL;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1589{
1590 struct type_datum *upper, *type;
1591 struct policydb *p = datap;
1592 int depth = 0;
1593
1594 upper = type = datum;
1595 while (upper->bounds) {
1596 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1597 printk(KERN_ERR "SELinux: type %s: "
1598 "too deep or looped boundary\n",
1599 (char *) key);
1600 return -EINVAL;
1601 }
1602
1603 upper = p->type_val_to_struct[upper->bounds - 1];
1604 if (upper->attribute) {
1605 printk(KERN_ERR "SELinux: type %s: "
1606 "bounded by attribute %s",
1607 (char *) key,
1608 p->p_type_val_to_name[upper->value - 1]);
1609 return -EINVAL;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
1616static int policydb_bounds_sanity_check(struct policydb *p)
1617{
1618 int rc;
1619
1620 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1621 return 0;
1622
1623 rc = hashtab_map(p->p_users.table,
1624 user_bounds_sanity_check, p);
1625 if (rc)
1626 return rc;
1627
1628 rc = hashtab_map(p->p_roles.table,
1629 role_bounds_sanity_check, p);
1630 if (rc)
1631 return rc;
1632
1633 rc = hashtab_map(p->p_types.table,
1634 type_bounds_sanity_check, p);
1635 if (rc)
1636 return rc;
1637
1638 return 0;
1639}
1640
1468extern int ss_initialized; 1641extern int ss_initialized;
1469 1642
1470/* 1643/*
@@ -1523,7 +1696,7 @@ int policydb_read(struct policydb *p, void *fp)
1523 kfree(policydb_str); 1696 kfree(policydb_str);
1524 goto bad; 1697 goto bad;
1525 } 1698 }
1526 policydb_str[len] = 0; 1699 policydb_str[len] = '\0';
1527 if (strcmp(policydb_str, POLICYDB_STRING)) { 1700 if (strcmp(policydb_str, POLICYDB_STRING)) {
1528 printk(KERN_ERR "SELinux: policydb string %s does not match " 1701 printk(KERN_ERR "SELinux: policydb string %s does not match "
1529 "my string %s\n", policydb_str, POLICYDB_STRING); 1702 "my string %s\n", policydb_str, POLICYDB_STRING);
@@ -1961,6 +2134,10 @@ int policydb_read(struct policydb *p, void *fp)
1961 goto bad; 2134 goto bad;
1962 } 2135 }
1963 2136
2137 rc = policydb_bounds_sanity_check(p);
2138 if (rc)
2139 goto bad;
2140
1964 rc = 0; 2141 rc = 0;
1965out: 2142out:
1966 return rc; 2143 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4253370fda6a..55152d498b53 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -61,6 +61,7 @@ struct class_datum {
61/* Role attributes */ 61/* Role attributes */
62struct role_datum { 62struct role_datum {
63 u32 value; /* internal role value */ 63 u32 value; /* internal role value */
64 u32 bounds; /* boundary of role */
64 struct ebitmap dominates; /* set of roles dominated by this role */ 65 struct ebitmap dominates; /* set of roles dominated by this role */
65 struct ebitmap types; /* set of authorized types for role */ 66 struct ebitmap types; /* set of authorized types for role */
66}; 67};
@@ -81,12 +82,15 @@ struct role_allow {
81/* Type attributes */ 82/* Type attributes */
82struct type_datum { 83struct type_datum {
83 u32 value; /* internal type value */ 84 u32 value; /* internal type value */
85 u32 bounds; /* boundary of type */
84 unsigned char primary; /* primary name? */ 86 unsigned char primary; /* primary name? */
87 unsigned char attribute;/* attribute ?*/
85}; 88};
86 89
87/* User attributes */ 90/* User attributes */
88struct user_datum { 91struct user_datum {
89 u32 value; /* internal user value */ 92 u32 value; /* internal user value */
93 u32 bounds; /* bounds of user */
90 struct ebitmap roles; /* set of authorized roles for user */ 94 struct ebitmap roles; /* set of authorized roles for user */
91 struct mls_range range; /* MLS range (min - max) for user */ 95 struct mls_range range; /* MLS range (min - max) for user */
92 struct mls_level dfltlevel; /* default login MLS level for user */ 96 struct mls_level dfltlevel; /* default login MLS level for user */
@@ -209,6 +213,7 @@ struct policydb {
209 struct class_datum **class_val_to_struct; 213 struct class_datum **class_val_to_struct;
210 struct role_datum **role_val_to_struct; 214 struct role_datum **role_val_to_struct;
211 struct user_datum **user_val_to_struct; 215 struct user_datum **user_val_to_struct;
216 struct type_datum **type_val_to_struct;
212 217
213 /* type enforcement access vectors and transitions */ 218 /* type enforcement access vectors and transitions */
214 struct avtab te_avtab; 219 struct avtab te_avtab;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d11a8154500f..343c8ab14af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -88,6 +88,11 @@ static u32 latest_granting;
88static int context_struct_to_string(struct context *context, char **scontext, 88static int context_struct_to_string(struct context *context, char **scontext,
89 u32 *scontext_len); 89 u32 *scontext_len);
90 90
91static int context_struct_compute_av(struct context *scontext,
92 struct context *tcontext,
93 u16 tclass,
94 u32 requested,
95 struct av_decision *avd);
91/* 96/*
92 * Return the boolean value of a constraint expression 97 * Return the boolean value of a constraint expression
93 * when it is applied to the specified source and target 98 * when it is applied to the specified source and target
@@ -274,6 +279,100 @@ mls_ops:
274} 279}
275 280
276/* 281/*
282 * security_boundary_permission - drops violated permissions
283 * on boundary constraint.
284 */
285static void type_attribute_bounds_av(struct context *scontext,
286 struct context *tcontext,
287 u16 tclass,
288 u32 requested,
289 struct av_decision *avd)
290{
291 struct context lo_scontext;
292 struct context lo_tcontext;
293 struct av_decision lo_avd;
294 struct type_datum *source
295 = policydb.type_val_to_struct[scontext->type - 1];
296 struct type_datum *target
297 = policydb.type_val_to_struct[tcontext->type - 1];
298 u32 masked = 0;
299
300 if (source->bounds) {
301 memset(&lo_avd, 0, sizeof(lo_avd));
302
303 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
304 lo_scontext.type = source->bounds;
305
306 context_struct_compute_av(&lo_scontext,
307 tcontext,
308 tclass,
309 requested,
310 &lo_avd);
311 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
312 return; /* no masked permission */
313 masked = ~lo_avd.allowed & avd->allowed;
314 }
315
316 if (target->bounds) {
317 memset(&lo_avd, 0, sizeof(lo_avd));
318
319 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
320 lo_tcontext.type = target->bounds;
321
322 context_struct_compute_av(scontext,
323 &lo_tcontext,
324 tclass,
325 requested,
326 &lo_avd);
327 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
328 return; /* no masked permission */
329 masked = ~lo_avd.allowed & avd->allowed;
330 }
331
332 if (source->bounds && target->bounds) {
333 memset(&lo_avd, 0, sizeof(lo_avd));
334 /*
335 * lo_scontext and lo_tcontext are already
336 * set up.
337 */
338
339 context_struct_compute_av(&lo_scontext,
340 &lo_tcontext,
341 tclass,
342 requested,
343 &lo_avd);
344 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
345 return; /* no masked permission */
346 masked = ~lo_avd.allowed & avd->allowed;
347 }
348
349 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */
359 avd->allowed &= ~masked;
360
361 /* notice to userspace via audit message */
362 ab = audit_log_start(current->audit_context,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR);
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 }
373}
374
375/*
277 * Compute access vectors based on a context structure pair for 376 * Compute access vectors based on a context structure pair for
278 * the permissions in a particular class. 377 * the permissions in a particular class.
279 */ 378 */
@@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext,
356 avkey.source_type = i + 1; 455 avkey.source_type = i + 1;
357 avkey.target_type = j + 1; 456 avkey.target_type = j + 1;
358 for (node = avtab_search_node(&policydb.te_avtab, &avkey); 457 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
359 node != NULL; 458 node;
360 node = avtab_search_node_next(node, avkey.specified)) { 459 node = avtab_search_node_next(node, avkey.specified)) {
361 if (node->key.specified == AVTAB_ALLOWED) 460 if (node->key.specified == AVTAB_ALLOWED)
362 avd->allowed |= node->datum.data; 461 avd->allowed |= node->datum.data;
@@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext,
404 PROCESS__DYNTRANSITION); 503 PROCESS__DYNTRANSITION);
405 } 504 }
406 505
506 /*
507 * If the given source and target types have boundary
508 * constraint, lazy checks have to mask any violated
509 * permission and notice it to userspace via audit.
510 */
511 type_attribute_bounds_av(scontext, tcontext,
512 tclass, requested, avd);
513
407 return 0; 514 return 0;
408 515
409inval_class: 516inval_class:
@@ -549,6 +656,69 @@ out:
549 return rc; 656 return rc;
550} 657}
551 658
659/*
660 * security_bounded_transition - check whether the given
661 * transition is directed to bounded, or not.
662 * It returns 0, if @newsid is bounded by @oldsid.
663 * Otherwise, it returns error code.
664 *
665 * @oldsid : current security identifier
666 * @newsid : destinated security identifier
667 */
668int security_bounded_transition(u32 old_sid, u32 new_sid)
669{
670 struct context *old_context, *new_context;
671 struct type_datum *type;
672 int index;
673 int rc = -EINVAL;
674
675 read_lock(&policy_rwlock);
676
677 old_context = sidtab_search(&sidtab, old_sid);
678 if (!old_context) {
679 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
680 __func__, old_sid);
681 goto out;
682 }
683
684 new_context = sidtab_search(&sidtab, new_sid);
685 if (!new_context) {
686 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
687 __func__, new_sid);
688 goto out;
689 }
690
691 /* type/domain unchaned */
692 if (old_context->type == new_context->type) {
693 rc = 0;
694 goto out;
695 }
696
697 index = new_context->type;
698 while (true) {
699 type = policydb.type_val_to_struct[index - 1];
700 BUG_ON(!type);
701
702 /* not bounded anymore */
703 if (!type->bounds) {
704 rc = -EPERM;
705 break;
706 }
707
708 /* @newsid is bounded by @oldsid */
709 if (type->bounds == old_context->type) {
710 rc = 0;
711 break;
712 }
713 index = type->bounds;
714 }
715out:
716 read_unlock(&policy_rwlock);
717
718 return rc;
719}
720
721
552/** 722/**
553 * security_compute_av - Compute access vector decisions. 723 * security_compute_av - Compute access vector decisions.
554 * @ssid: source security identifier 724 * @ssid: source security identifier
@@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol,
794 *p++ = 0; 964 *p++ = 0;
795 965
796 typdatum = hashtab_search(pol->p_types.table, scontextp); 966 typdatum = hashtab_search(pol->p_types.table, scontextp);
797 if (!typdatum) 967 if (!typdatum || typdatum->attribute)
798 goto out; 968 goto out;
799 969
800 ctx->type = typdatum->value; 970 ctx->type = typdatum->value;
@@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid,
1037 /* If no permanent rule, also check for enabled conditional rules */ 1207 /* If no permanent rule, also check for enabled conditional rules */
1038 if (!avdatum) { 1208 if (!avdatum) {
1039 node = avtab_search_node(&policydb.te_cond_avtab, &avkey); 1209 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1040 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 1210 for (; node; node = avtab_search_node_next(node, specified)) {
1041 if (node->key.specified & AVTAB_ENABLED) { 1211 if (node->key.specified & AVTAB_ENABLED) {
1042 avdatum = &node->datum; 1212 avdatum = &node->datum;
1043 break; 1213 break;
@@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values)
2050 policydb.bool_val_to_struct[i]->state = 0; 2220 policydb.bool_val_to_struct[i]->state = 0;
2051 } 2221 }
2052 2222
2053 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 2223 for (cur = policydb.cond_list; cur; cur = cur->next) {
2054 rc = evaluate_cond_node(&policydb, cur); 2224 rc = evaluate_cond_node(&policydb, cur);
2055 if (rc) 2225 if (rc)
2056 goto out; 2226 goto out;
@@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p)
2102 if (booldatum) 2272 if (booldatum)
2103 booldatum->state = bvalues[i]; 2273 booldatum->state = bvalues[i];
2104 } 2274 }
2105 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 2275 for (cur = p->cond_list; cur; cur = cur->next) {
2106 rc = evaluate_cond_node(p, cur); 2276 rc = evaluate_cond_node(p, cur);
2107 if (rc) 2277 if (rc)
2108 goto out; 2278 goto out;
@@ -2737,6 +2907,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2737 if (ctx == NULL) 2907 if (ctx == NULL)
2738 goto netlbl_secattr_to_sid_return; 2908 goto netlbl_secattr_to_sid_return;
2739 2909
2910 context_init(&ctx_new);
2740 ctx_new.user = ctx->user; 2911 ctx_new.user = ctx->user;
2741 ctx_new.role = ctx->role; 2912 ctx_new.role = ctx->role;
2742 ctx_new.type = ctx->type; 2913 ctx_new.type = ctx->type;
@@ -2745,13 +2916,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2745 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, 2916 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2746 secattr->attr.mls.cat) != 0) 2917 secattr->attr.mls.cat) != 0)
2747 goto netlbl_secattr_to_sid_return; 2918 goto netlbl_secattr_to_sid_return;
2748 ctx_new.range.level[1].cat.highbit = 2919 memcpy(&ctx_new.range.level[1].cat,
2749 ctx_new.range.level[0].cat.highbit; 2920 &ctx_new.range.level[0].cat,
2750 ctx_new.range.level[1].cat.node = 2921 sizeof(ctx_new.range.level[0].cat));
2751 ctx_new.range.level[0].cat.node;
2752 } else {
2753 ebitmap_init(&ctx_new.range.level[0].cat);
2754 ebitmap_init(&ctx_new.range.level[1].cat);
2755 } 2922 }
2756 if (mls_context_isvalid(&policydb, &ctx_new) != 1) 2923 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2757 goto netlbl_secattr_to_sid_return_cleanup; 2924 goto netlbl_secattr_to_sid_return_cleanup;
@@ -2788,7 +2955,7 @@ netlbl_secattr_to_sid_return_cleanup:
2788 */ 2955 */
2789int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) 2956int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2790{ 2957{
2791 int rc = -ENOENT; 2958 int rc;
2792 struct context *ctx; 2959 struct context *ctx;
2793 2960
2794 if (!ss_initialized) 2961 if (!ss_initialized)
@@ -2796,11 +2963,18 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2796 2963
2797 read_lock(&policy_rwlock); 2964 read_lock(&policy_rwlock);
2798 ctx = sidtab_search(&sidtab, sid); 2965 ctx = sidtab_search(&sidtab, sid);
2799 if (ctx == NULL) 2966 if (ctx == NULL) {
2967 rc = -ENOENT;
2800 goto netlbl_sid_to_secattr_failure; 2968 goto netlbl_sid_to_secattr_failure;
2969 }
2801 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2970 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2802 GFP_ATOMIC); 2971 GFP_ATOMIC);
2803 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; 2972 if (secattr->domain == NULL) {
2973 rc = -ENOMEM;
2974 goto netlbl_sid_to_secattr_failure;
2975 }
2976 secattr->attr.secid = sid;
2977 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
2804 mls_export_netlbl_lvl(ctx, secattr); 2978 mls_export_netlbl_lvl(ctx, secattr);
2805 rc = mls_export_netlbl_cat(ctx, secattr); 2979 rc = mls_export_netlbl_cat(ctx, secattr);
2806 if (rc != 0) 2980 if (rc != 0)
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index a81ded104129..e817989764cd 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
43 hvalue = SIDTAB_HASH(sid); 43 hvalue = SIDTAB_HASH(sid);
44 prev = NULL; 44 prev = NULL;
45 cur = s->htable[hvalue]; 45 cur = s->htable[hvalue];
46 while (cur != NULL && sid > cur->sid) { 46 while (cur && sid > cur->sid) {
47 prev = cur; 47 prev = cur;
48 cur = cur->next; 48 cur = cur->next;
49 } 49 }
@@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
92 92
93 hvalue = SIDTAB_HASH(sid); 93 hvalue = SIDTAB_HASH(sid);
94 cur = s->htable[hvalue]; 94 cur = s->htable[hvalue];
95 while (cur != NULL && sid > cur->sid) 95 while (cur && sid > cur->sid)
96 cur = cur->next; 96 cur = cur->next;
97 97
98 if (force && cur && sid == cur->sid && cur->context.len) 98 if (force && cur && sid == cur->sid && cur->context.len)
@@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
103 sid = SECINITSID_UNLABELED; 103 sid = SECINITSID_UNLABELED;
104 hvalue = SIDTAB_HASH(sid); 104 hvalue = SIDTAB_HASH(sid);
105 cur = s->htable[hvalue]; 105 cur = s->htable[hvalue];
106 while (cur != NULL && sid > cur->sid) 106 while (cur && sid > cur->sid)
107 cur = cur->next; 107 cur = cur->next;
108 if (!cur || sid != cur->sid) 108 if (!cur || sid != cur->sid)
109 return NULL; 109 return NULL;
@@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s,
136 136
137 for (i = 0; i < SIDTAB_SIZE; i++) { 137 for (i = 0; i < SIDTAB_SIZE; i++) {
138 cur = s->htable[i]; 138 cur = s->htable[i];
139 while (cur != NULL) { 139 while (cur) {
140 rc = apply(cur->sid, &cur->context, args); 140 rc = apply(cur->sid, &cur->context, args);
141 if (rc) 141 if (rc)
142 goto out; 142 goto out;
@@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s,
155 155
156 for (i = 0; i < SIDTAB_SIZE; i++) { 156 for (i = 0; i < SIDTAB_SIZE; i++) {
157 cur = s->htable[i]; 157 cur = s->htable[i];
158 while (cur != NULL) { 158 while (cur) {
159 if (context_cmp(&cur->context, context)) 159 if (context_cmp(&cur->context, context))
160 return cur->sid; 160 return cur->sid;
161 cur = cur->next; 161 cur = cur->next;
@@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s)
242 242
243 for (i = 0; i < SIDTAB_SIZE; i++) { 243 for (i = 0; i < SIDTAB_SIZE; i++) {
244 cur = s->htable[i]; 244 cur = s->htable[i];
245 while (cur != NULL) { 245 while (cur) {
246 temp = cur; 246 temp = cur;
247 cur = cur->next; 247 cur = cur->next;
248 context_destroy(&temp->context); 248 context_destroy(&temp->context);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 4a4477f5afdc..31dce559595a 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -178,6 +178,7 @@ u32 smack_to_secid(const char *);
178extern int smack_cipso_direct; 178extern int smack_cipso_direct;
179extern int smack_net_nltype; 179extern int smack_net_nltype;
180extern char *smack_net_ambient; 180extern char *smack_net_ambient;
181extern char *smack_onlycap;
181 182
182extern struct smack_known *smack_known; 183extern struct smack_known *smack_known;
183extern struct smack_known smack_known_floor; 184extern struct smack_known smack_known_floor;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index f6b5f6eed6dd..79ff21ed4c3b 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request)
157 * 157 *
158 * This function checks the current subject label/object label pair 158 * This function checks the current subject label/object label pair
159 * in the access rule list and returns 0 if the access is permitted, 159 * in the access rule list and returns 0 if the access is permitted,
160 * non zero otherwise. It allows that current my have the capability 160 * non zero otherwise. It allows that current may have the capability
161 * to override the rules. 161 * to override the rules.
162 */ 162 */
163int smk_curacc(char *obj_label, u32 mode) 163int smk_curacc(char *obj_label, u32 mode)
@@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode)
168 if (rc == 0) 168 if (rc == 0)
169 return 0; 169 return 0;
170 170
171 /*
172 * Return if a specific label has been designated as the
173 * only one that gets privilege and current does not
174 * have that label.
175 */
176 if (smack_onlycap != NULL && smack_onlycap != current->security)
177 return rc;
178
171 if (capable(CAP_MAC_OVERRIDE)) 179 if (capable(CAP_MAC_OVERRIDE))
172 return 0; 180 return 0;
173 181
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 87d75417ea93..6e2dc0bab70d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2179,7 +2179,10 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2179 * This is the simplist possible security model 2179 * This is the simplist possible security model
2180 * for networking. 2180 * for networking.
2181 */ 2181 */
2182 return smk_access(smack, ssp->smk_in, MAY_WRITE); 2182 rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
2183 if (rc != 0)
2184 netlbl_skbuff_err(skb, rc, 0);
2185 return rc;
2183} 2186}
2184 2187
2185/** 2188/**
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 271a835fbbe3..c21d8c8bf0c7 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -39,6 +39,7 @@ enum smk_inos {
39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */ 39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
40 SMK_AMBIENT = 7, /* internet ambient label */ 40 SMK_AMBIENT = 7, /* internet ambient label */
41 SMK_NLTYPE = 8, /* label scheme to use by default */ 41 SMK_NLTYPE = 8, /* label scheme to use by default */
42 SMK_ONLYCAP = 9, /* the only "capable" label */
42}; 43};
43 44
44/* 45/*
@@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
68 */ 69 */
69int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; 70int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
70 71
72/*
73 * Unless a process is running with this label even
74 * having CAP_MAC_OVERRIDE isn't enough to grant
75 * privilege to violate MAC policy. If no label is
76 * designated (the NULL case) capabilities apply to
77 * everyone. It is expected that the hat (^) label
78 * will be used if any label is used.
79 */
80char *smack_onlycap;
81
71static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 82static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
72struct smk_list_entry *smack_list; 83struct smk_list_entry *smack_list;
73 84
@@ -343,9 +354,11 @@ static void smk_cipso_doi(void)
343 doip->tags[rc] = CIPSO_V4_TAG_INVALID; 354 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
344 355
345 rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); 356 rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
346 if (rc != 0) 357 if (rc != 0) {
347 printk(KERN_WARNING "%s:%d add rc = %d\n", 358 printk(KERN_WARNING "%s:%d add rc = %d\n",
348 __func__, __LINE__, rc); 359 __func__, __LINE__, rc);
360 kfree(doip);
361 }
349} 362}
350 363
351/** 364/**
@@ -787,6 +800,85 @@ static const struct file_operations smk_ambient_ops = {
787 .write = smk_write_ambient, 800 .write = smk_write_ambient,
788}; 801};
789 802
803/**
804 * smk_read_onlycap - read() for /smack/onlycap
805 * @filp: file pointer, not actually used
806 * @buf: where to put the result
807 * @cn: maximum to send along
808 * @ppos: where to start
809 *
810 * Returns number of bytes read or error code, as appropriate
811 */
812static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
813 size_t cn, loff_t *ppos)
814{
815 char *smack = "";
816 ssize_t rc = -EINVAL;
817 int asize;
818
819 if (*ppos != 0)
820 return 0;
821
822 if (smack_onlycap != NULL)
823 smack = smack_onlycap;
824
825 asize = strlen(smack) + 1;
826
827 if (cn >= asize)
828 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
829
830 return rc;
831}
832
833/**
834 * smk_write_onlycap - write() for /smack/onlycap
835 * @filp: file pointer, not actually used
836 * @buf: where to get the data from
837 * @count: bytes sent
838 * @ppos: where to start
839 *
840 * Returns number of bytes written or error code, as appropriate
841 */
842static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
843 size_t count, loff_t *ppos)
844{
845 char in[SMK_LABELLEN];
846 char *sp = current->security;
847
848 if (!capable(CAP_MAC_ADMIN))
849 return -EPERM;
850
851 /*
852 * This can be done using smk_access() but is done
853 * explicitly for clarity. The smk_access() implementation
854 * would use smk_access(smack_onlycap, MAY_WRITE)
855 */
856 if (smack_onlycap != NULL && smack_onlycap != sp)
857 return -EPERM;
858
859 if (count >= SMK_LABELLEN)
860 return -EINVAL;
861
862 if (copy_from_user(in, buf, count) != 0)
863 return -EFAULT;
864
865 /*
866 * Should the null string be passed in unset the onlycap value.
867 * This seems like something to be careful with as usually
868 * smk_import only expects to return NULL for errors. It
869 * is usually the case that a nullstring or "\n" would be
870 * bad to pass to smk_import but in fact this is useful here.
871 */
872 smack_onlycap = smk_import(in, count);
873
874 return count;
875}
876
877static const struct file_operations smk_onlycap_ops = {
878 .read = smk_read_onlycap,
879 .write = smk_write_onlycap,
880};
881
790struct option_names { 882struct option_names {
791 int o_number; 883 int o_number;
792 char *o_name; 884 char *o_name;
@@ -919,6 +1011,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
919 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1011 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
920 [SMK_NLTYPE] = 1012 [SMK_NLTYPE] =
921 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, 1013 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
1014 [SMK_ONLYCAP] =
1015 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
922 /* last one */ {""} 1016 /* last one */ {""}
923 }; 1017 };
924 1018