aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c4
-rw-r--r--security/dummy.c27
-rw-r--r--security/keys/key.c18
-rw-r--r--security/keys/keyctl.c155
-rw-r--r--security/keys/process_keys.c7
-rw-r--r--security/seclvl.c210
-rw-r--r--security/security.c23
-rw-r--r--security/selinux/hooks.c158
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/nlmsgtab.c16
-rw-r--r--security/selinux/selinuxfs.c123
-rw-r--r--security/selinux/ss/services.c24
-rw-r--r--security/selinux/xfrm.c68
13 files changed, 466 insertions, 379 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 8a6e097f99ea..841eb4e5c62b 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -60,8 +60,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
60int cap_ptrace (struct task_struct *parent, struct task_struct *child) 60int cap_ptrace (struct task_struct *parent, struct task_struct *child)
61{ 61{
62 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 62 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
63 if (!cap_issubset (child->cap_permitted, current->cap_permitted) && 63 if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
64 !capable(CAP_SYS_PTRACE)) 64 !__capable(parent, CAP_SYS_PTRACE))
65 return -EPERM; 65 return -EPERM;
66 return 0; 66 return 0;
67} 67}
diff --git a/security/dummy.c b/security/dummy.c
index f1a5bd98bf10..fd99429278e9 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -378,7 +378,7 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
378 return 0; 378 return 0;
379} 379}
380 380
381static int dummy_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) 381static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
382{ 382{
383 return -EOPNOTSUPP; 383 return -EOPNOTSUPP;
384} 384}
@@ -393,6 +393,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
393 return 0; 393 return 0;
394} 394}
395 395
396static const char *dummy_inode_xattr_getsuffix(void)
397{
398 return NULL;
399}
400
396static int dummy_file_permission (struct file *file, int mask) 401static int dummy_file_permission (struct file *file, int mask)
397{ 402{
398 return 0; 403 return 0;
@@ -558,6 +563,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
558 return 0; 563 return 0;
559} 564}
560 565
566static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
567{
568 return -EOPNOTSUPP;
569}
570
561static int dummy_msg_msg_alloc_security (struct msg_msg *msg) 571static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
562{ 572{
563 return 0; 573 return 0;
@@ -763,8 +773,14 @@ static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
763 return 0; 773 return 0;
764} 774}
765 775
766static int dummy_socket_getpeersec(struct socket *sock, char __user *optval, 776static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optval,
767 int __user *optlen, unsigned len) 777 int __user *optlen, unsigned len)
778{
779 return -ENOPROTOOPT;
780}
781
782static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
783 u32 *seclen)
768{ 784{
769 return -ENOPROTOOPT; 785 return -ENOPROTOOPT;
770} 786}
@@ -925,6 +941,7 @@ void security_fixup_ops (struct security_operations *ops)
925 set_to_dummy_if_null(ops, inode_getxattr); 941 set_to_dummy_if_null(ops, inode_getxattr);
926 set_to_dummy_if_null(ops, inode_listxattr); 942 set_to_dummy_if_null(ops, inode_listxattr);
927 set_to_dummy_if_null(ops, inode_removexattr); 943 set_to_dummy_if_null(ops, inode_removexattr);
944 set_to_dummy_if_null(ops, inode_xattr_getsuffix);
928 set_to_dummy_if_null(ops, inode_getsecurity); 945 set_to_dummy_if_null(ops, inode_getsecurity);
929 set_to_dummy_if_null(ops, inode_setsecurity); 946 set_to_dummy_if_null(ops, inode_setsecurity);
930 set_to_dummy_if_null(ops, inode_listsecurity); 947 set_to_dummy_if_null(ops, inode_listsecurity);
@@ -959,6 +976,7 @@ void security_fixup_ops (struct security_operations *ops)
959 set_to_dummy_if_null(ops, task_reparent_to_init); 976 set_to_dummy_if_null(ops, task_reparent_to_init);
960 set_to_dummy_if_null(ops, task_to_inode); 977 set_to_dummy_if_null(ops, task_to_inode);
961 set_to_dummy_if_null(ops, ipc_permission); 978 set_to_dummy_if_null(ops, ipc_permission);
979 set_to_dummy_if_null(ops, ipc_getsecurity);
962 set_to_dummy_if_null(ops, msg_msg_alloc_security); 980 set_to_dummy_if_null(ops, msg_msg_alloc_security);
963 set_to_dummy_if_null(ops, msg_msg_free_security); 981 set_to_dummy_if_null(ops, msg_msg_free_security);
964 set_to_dummy_if_null(ops, msg_queue_alloc_security); 982 set_to_dummy_if_null(ops, msg_queue_alloc_security);
@@ -1002,7 +1020,8 @@ void security_fixup_ops (struct security_operations *ops)
1002 set_to_dummy_if_null(ops, socket_getsockopt); 1020 set_to_dummy_if_null(ops, socket_getsockopt);
1003 set_to_dummy_if_null(ops, socket_shutdown); 1021 set_to_dummy_if_null(ops, socket_shutdown);
1004 set_to_dummy_if_null(ops, socket_sock_rcv_skb); 1022 set_to_dummy_if_null(ops, socket_sock_rcv_skb);
1005 set_to_dummy_if_null(ops, socket_getpeersec); 1023 set_to_dummy_if_null(ops, socket_getpeersec_stream);
1024 set_to_dummy_if_null(ops, socket_getpeersec_dgram);
1006 set_to_dummy_if_null(ops, sk_alloc_security); 1025 set_to_dummy_if_null(ops, sk_alloc_security);
1007 set_to_dummy_if_null(ops, sk_free_security); 1026 set_to_dummy_if_null(ops, sk_free_security);
1008 set_to_dummy_if_null(ops, sk_getsid); 1027 set_to_dummy_if_null(ops, sk_getsid);
diff --git a/security/keys/key.c b/security/keys/key.c
index 99781b798312..a057e3311aad 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
1/* key.c: basic authentication token and access key management 1/* key.c: basic authentication token and access key management
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -271,7 +271,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
271 * its description */ 271 * its description */
272 if (!not_in_quota) { 272 if (!not_in_quota) {
273 spin_lock(&user->lock); 273 spin_lock(&user->lock);
274 if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS && 274 if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
275 user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES 275 user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
276 ) 276 )
277 goto no_quota; 277 goto no_quota;
@@ -795,12 +795,16 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
795 goto error_3; 795 goto error_3;
796 } 796 }
797 797
798 /* search for an existing key of the same type and description in the 798 /* if it's possible to update this type of key, search for an existing
799 * destination keyring 799 * key of the same type and description in the destination keyring and
800 * update that instead if possible
800 */ 801 */
801 key_ref = __keyring_search_one(keyring_ref, ktype, description, 0); 802 if (ktype->update) {
802 if (!IS_ERR(key_ref)) 803 key_ref = __keyring_search_one(keyring_ref, ktype, description,
803 goto found_matching_key; 804 0);
805 if (!IS_ERR(key_ref))
806 goto found_matching_key;
807 }
804 808
805 /* decide on the permissions we want */ 809 /* decide on the permissions we want */
806 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; 810 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 0c62798ac7d8..ed71d86d2ce2 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -17,10 +17,33 @@
17#include <linux/keyctl.h> 17#include <linux/keyctl.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/capability.h> 19#include <linux/capability.h>
20#include <linux/string.h>
20#include <linux/err.h> 21#include <linux/err.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
22#include "internal.h" 23#include "internal.h"
23 24
25static int key_get_type_from_user(char *type,
26 const char __user *_type,
27 unsigned len)
28{
29 int ret;
30
31 ret = strncpy_from_user(type, _type, len);
32
33 if (ret < 0)
34 return -EFAULT;
35
36 if (ret == 0 || ret >= len)
37 return -EINVAL;
38
39 if (type[0] == '.')
40 return -EPERM;
41
42 type[len - 1] = '\0';
43
44 return 0;
45}
46
24/*****************************************************************************/ 47/*****************************************************************************/
25/* 48/*
26 * extract the description of a new key from userspace and either add it as a 49 * extract the description of a new key from userspace and either add it as a
@@ -38,40 +61,22 @@ asmlinkage long sys_add_key(const char __user *_type,
38 key_ref_t keyring_ref, key_ref; 61 key_ref_t keyring_ref, key_ref;
39 char type[32], *description; 62 char type[32], *description;
40 void *payload; 63 void *payload;
41 long dlen, ret; 64 long ret;
42 65
43 ret = -EINVAL; 66 ret = -EINVAL;
44 if (plen > 32767) 67 if (plen > 32767)
45 goto error; 68 goto error;
46 69
47 /* draw all the data into kernel space */ 70 /* draw all the data into kernel space */
48 ret = strncpy_from_user(type, _type, sizeof(type) - 1); 71 ret = key_get_type_from_user(type, _type, sizeof(type));
49 if (ret < 0) 72 if (ret < 0)
50 goto error; 73 goto error;
51 type[31] = '\0';
52
53 ret = -EPERM;
54 if (type[0] == '.')
55 goto error;
56
57 ret = -EFAULT;
58 dlen = strnlen_user(_description, PAGE_SIZE - 1);
59 if (dlen <= 0)
60 goto error;
61 74
62 ret = -EINVAL; 75 description = strndup_user(_description, PAGE_SIZE);
63 if (dlen > PAGE_SIZE - 1) 76 if (IS_ERR(description)) {
64 goto error; 77 ret = PTR_ERR(description);
65
66 ret = -ENOMEM;
67 description = kmalloc(dlen + 1, GFP_KERNEL);
68 if (!description)
69 goto error; 78 goto error;
70 description[dlen] = '\0'; 79 }
71
72 ret = -EFAULT;
73 if (copy_from_user(description, _description, dlen) != 0)
74 goto error2;
75 80
76 /* pull the payload in if one was supplied */ 81 /* pull the payload in if one was supplied */
77 payload = NULL; 82 payload = NULL;
@@ -136,59 +141,28 @@ asmlinkage long sys_request_key(const char __user *_type,
136 struct key *key; 141 struct key *key;
137 key_ref_t dest_ref; 142 key_ref_t dest_ref;
138 char type[32], *description, *callout_info; 143 char type[32], *description, *callout_info;
139 long dlen, ret; 144 long ret;
140 145
141 /* pull the type into kernel space */ 146 /* pull the type into kernel space */
142 ret = strncpy_from_user(type, _type, sizeof(type) - 1); 147 ret = key_get_type_from_user(type, _type, sizeof(type));
143 if (ret < 0) 148 if (ret < 0)
144 goto error; 149 goto error;
145 type[31] = '\0';
146
147 ret = -EPERM;
148 if (type[0] == '.')
149 goto error;
150 150
151 /* pull the description into kernel space */ 151 /* pull the description into kernel space */
152 ret = -EFAULT; 152 description = strndup_user(_description, PAGE_SIZE);
153 dlen = strnlen_user(_description, PAGE_SIZE - 1); 153 if (IS_ERR(description)) {
154 if (dlen <= 0) 154 ret = PTR_ERR(description);
155 goto error;
156
157 ret = -EINVAL;
158 if (dlen > PAGE_SIZE - 1)
159 goto error;
160
161 ret = -ENOMEM;
162 description = kmalloc(dlen + 1, GFP_KERNEL);
163 if (!description)
164 goto error; 155 goto error;
165 description[dlen] = '\0'; 156 }
166
167 ret = -EFAULT;
168 if (copy_from_user(description, _description, dlen) != 0)
169 goto error2;
170 157
171 /* pull the callout info into kernel space */ 158 /* pull the callout info into kernel space */
172 callout_info = NULL; 159 callout_info = NULL;
173 if (_callout_info) { 160 if (_callout_info) {
174 ret = -EFAULT; 161 callout_info = strndup_user(_callout_info, PAGE_SIZE);
175 dlen = strnlen_user(_callout_info, PAGE_SIZE - 1); 162 if (IS_ERR(callout_info)) {
176 if (dlen <= 0) 163 ret = PTR_ERR(callout_info);
177 goto error2;
178
179 ret = -EINVAL;
180 if (dlen > PAGE_SIZE - 1)
181 goto error2;
182
183 ret = -ENOMEM;
184 callout_info = kmalloc(dlen + 1, GFP_KERNEL);
185 if (!callout_info)
186 goto error2; 164 goto error2;
187 callout_info[dlen] = '\0'; 165 }
188
189 ret = -EFAULT;
190 if (copy_from_user(callout_info, _callout_info, dlen) != 0)
191 goto error3;
192 } 166 }
193 167
194 /* get the destination keyring if specified */ 168 /* get the destination keyring if specified */
@@ -264,36 +238,21 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
264long keyctl_join_session_keyring(const char __user *_name) 238long keyctl_join_session_keyring(const char __user *_name)
265{ 239{
266 char *name; 240 char *name;
267 long nlen, ret; 241 long ret;
268 242
269 /* fetch the name from userspace */ 243 /* fetch the name from userspace */
270 name = NULL; 244 name = NULL;
271 if (_name) { 245 if (_name) {
272 ret = -EFAULT; 246 name = strndup_user(_name, PAGE_SIZE);
273 nlen = strnlen_user(_name, PAGE_SIZE - 1); 247 if (IS_ERR(name)) {
274 if (nlen <= 0) 248 ret = PTR_ERR(name);
275 goto error;
276
277 ret = -EINVAL;
278 if (nlen > PAGE_SIZE - 1)
279 goto error; 249 goto error;
280 250 }
281 ret = -ENOMEM;
282 name = kmalloc(nlen + 1, GFP_KERNEL);
283 if (!name)
284 goto error;
285 name[nlen] = '\0';
286
287 ret = -EFAULT;
288 if (copy_from_user(name, _name, nlen) != 0)
289 goto error2;
290 } 251 }
291 252
292 /* join the session */ 253 /* join the session */
293 ret = join_session_keyring(name); 254 ret = join_session_keyring(name);
294 255
295 error2:
296 kfree(name);
297 error: 256 error:
298 return ret; 257 return ret;
299 258
@@ -566,32 +525,18 @@ long keyctl_keyring_search(key_serial_t ringid,
566 struct key_type *ktype; 525 struct key_type *ktype;
567 key_ref_t keyring_ref, key_ref, dest_ref; 526 key_ref_t keyring_ref, key_ref, dest_ref;
568 char type[32], *description; 527 char type[32], *description;
569 long dlen, ret; 528 long ret;
570 529
571 /* pull the type and description into kernel space */ 530 /* pull the type and description into kernel space */
572 ret = strncpy_from_user(type, _type, sizeof(type) - 1); 531 ret = key_get_type_from_user(type, _type, sizeof(type));
573 if (ret < 0) 532 if (ret < 0)
574 goto error; 533 goto error;
575 type[31] = '\0';
576 534
577 ret = -EFAULT; 535 description = strndup_user(_description, PAGE_SIZE);
578 dlen = strnlen_user(_description, PAGE_SIZE - 1); 536 if (IS_ERR(description)) {
579 if (dlen <= 0) 537 ret = PTR_ERR(description);
580 goto error; 538 goto error;
581 539 }
582 ret = -EINVAL;
583 if (dlen > PAGE_SIZE - 1)
584 goto error;
585
586 ret = -ENOMEM;
587 description = kmalloc(dlen + 1, GFP_KERNEL);
588 if (!description)
589 goto error;
590 description[dlen] = '\0';
591
592 ret = -EFAULT;
593 if (copy_from_user(description, _description, dlen) != 0)
594 goto error2;
595 540
596 /* get the keyring at which to begin the search */ 541 /* get the keyring at which to begin the search */
597 keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); 542 keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 74cb79eb917e..f6940618e345 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -16,11 +16,12 @@
16#include <linux/keyctl.h> 16#include <linux/keyctl.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/mutex.h>
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
20#include "internal.h" 21#include "internal.h"
21 22
22/* session keyring create vs join semaphore */ 23/* session keyring create vs join semaphore */
23static DECLARE_MUTEX(key_session_sem); 24static DEFINE_MUTEX(key_session_mutex);
24 25
25/* the root user's tracking struct */ 26/* the root user's tracking struct */
26struct key_user root_key_user = { 27struct key_user root_key_user = {
@@ -711,7 +712,7 @@ long join_session_keyring(const char *name)
711 } 712 }
712 713
713 /* allow the user to join or create a named keyring */ 714 /* allow the user to join or create a named keyring */
714 down(&key_session_sem); 715 mutex_lock(&key_session_mutex);
715 716
716 /* look for an existing keyring of this name */ 717 /* look for an existing keyring of this name */
717 keyring = find_keyring_by_name(name, 0); 718 keyring = find_keyring_by_name(name, 0);
@@ -737,7 +738,7 @@ long join_session_keyring(const char *name)
737 key_put(keyring); 738 key_put(keyring);
738 739
739error2: 740error2:
740 up(&key_session_sem); 741 mutex_unlock(&key_session_mutex);
741error: 742error:
742 return ret; 743 return ret;
743 744
diff --git a/security/seclvl.c b/security/seclvl.c
index 8529ea6f7aa8..441beaf1bbc1 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -8,6 +8,7 @@
8 * Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com> 8 * Copyright (c) 2001 WireX Communications, Inc <chris@wirex.com>
9 * Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com> 9 * Copyright (c) 2001 Greg Kroah-Hartman <greg@kroah.com>
10 * Copyright (c) 2002 International Business Machines <robb@austin.ibm.com> 10 * Copyright (c) 2002 International Business Machines <robb@austin.ibm.com>
11 * Copyright (c) 2006 Davi E. M. Arnaut <davi.arnaut@gmail.com>
11 * 12 *
12 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
@@ -31,6 +32,7 @@
31#include <linux/kobject.h> 32#include <linux/kobject.h>
32#include <linux/crypto.h> 33#include <linux/crypto.h>
33#include <asm/scatterlist.h> 34#include <asm/scatterlist.h>
35#include <linux/scatterlist.h>
34#include <linux/gfp.h> 36#include <linux/gfp.h>
35#include <linux/sysfs.h> 37#include <linux/sysfs.h>
36 38
@@ -194,35 +196,27 @@ static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
194 * people... 196 * people...
195 */ 197 */
196static int 198static int
197plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len) 199plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len)
198{ 200{
199 char *pgVirtAddr;
200 struct crypto_tfm *tfm; 201 struct crypto_tfm *tfm;
201 struct scatterlist sg[1]; 202 struct scatterlist sg;
202 if (len > PAGE_SIZE) { 203 if (len > PAGE_SIZE) {
203 seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d " 204 seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d "
204 "characters). Largest possible is %lu " 205 "characters). Largest possible is %lu "
205 "bytes.\n", len, PAGE_SIZE); 206 "bytes.\n", len, PAGE_SIZE);
206 return -ENOMEM; 207 return -EINVAL;
207 } 208 }
208 tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP); 209 tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP);
209 if (tfm == NULL) { 210 if (tfm == NULL) {
210 seclvl_printk(0, KERN_ERR, 211 seclvl_printk(0, KERN_ERR,
211 "Failed to load transform for SHA1\n"); 212 "Failed to load transform for SHA1\n");
212 return -ENOSYS; 213 return -EINVAL;
213 } 214 }
214 // Just get a new page; don't play around with page boundaries 215 sg_init_one(&sg, (u8 *)plaintext, len);
215 // and scatterlists.
216 pgVirtAddr = (char *)__get_free_page(GFP_KERNEL);
217 sg[0].page = virt_to_page(pgVirtAddr);
218 sg[0].offset = 0;
219 sg[0].length = len;
220 strncpy(pgVirtAddr, plaintext, len);
221 crypto_digest_init(tfm); 216 crypto_digest_init(tfm);
222 crypto_digest_update(tfm, sg, 1); 217 crypto_digest_update(tfm, &sg, 1);
223 crypto_digest_final(tfm, hash); 218 crypto_digest_final(tfm, hash);
224 crypto_free_tfm(tfm); 219 crypto_free_tfm(tfm);
225 free_page((unsigned long)pgVirtAddr);
226 return 0; 220 return 0;
227} 221}
228 222
@@ -234,11 +228,9 @@ static ssize_t
234passwd_write_file(struct file * file, const char __user * buf, 228passwd_write_file(struct file * file, const char __user * buf,
235 size_t count, loff_t *ppos) 229 size_t count, loff_t *ppos)
236{ 230{
237 int i; 231 char *p;
238 unsigned char tmp[SHA1_DIGEST_SIZE];
239 char *page;
240 int rc;
241 int len; 232 int len;
233 unsigned char tmp[SHA1_DIGEST_SIZE];
242 234
243 if (!*passwd && !*sha1_passwd) { 235 if (!*passwd && !*sha1_passwd) {
244 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the " 236 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
@@ -251,38 +243,39 @@ passwd_write_file(struct file * file, const char __user * buf,
251 return -EINVAL; 243 return -EINVAL;
252 } 244 }
253 245
254 if (count < 0 || count >= PAGE_SIZE) 246 if (count >= PAGE_SIZE)
255 return -EINVAL; 247 return -EINVAL;
256 if (*ppos != 0) 248 if (*ppos != 0)
257 return -EINVAL; 249 return -EINVAL;
258 page = (char *)get_zeroed_page(GFP_KERNEL); 250 p = kmalloc(count, GFP_KERNEL);
259 if (!page) 251 if (!p)
260 return -ENOMEM; 252 return -ENOMEM;
261 len = -EFAULT; 253 len = -EFAULT;
262 if (copy_from_user(page, buf, count)) 254 if (copy_from_user(p, buf, count))
263 goto out; 255 goto out;
264 256
265 len = strlen(page); 257 len = count;
266 /* ``echo "secret" > seclvl/passwd'' includes a newline */ 258 /* ``echo "secret" > seclvl/passwd'' includes a newline */
267 if (page[len - 1] == '\n') 259 if (p[len - 1] == '\n')
268 len--; 260 len--;
269 /* Hash the password, then compare the hashed values */ 261 /* Hash the password, then compare the hashed values */
270 if ((rc = plaintext_to_sha1(tmp, page, len))) { 262 if ((len = plaintext_to_sha1(tmp, p, len))) {
271 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " 263 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
272 "[%d]\n", rc); 264 "[%d]\n", len);
273 return rc; 265 goto out;
274 }
275 for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
276 if (hashedPassword[i] != tmp[i])
277 return -EPERM;
278 } 266 }
267
268 len = -EPERM;
269 if (memcmp(hashedPassword, tmp, SHA1_DIGEST_SIZE))
270 goto out;
271
279 seclvl_printk(0, KERN_INFO, 272 seclvl_printk(0, KERN_INFO,
280 "Password accepted; seclvl reduced to 0.\n"); 273 "Password accepted; seclvl reduced to 0.\n");
281 seclvl = 0; 274 seclvl = 0;
282 len = count; 275 len = count;
283 276
284out: 277out:
285 free_page((unsigned long)page); 278 kfree (p);
286 return len; 279 return len;
287} 280}
288 281
@@ -295,13 +288,11 @@ static struct file_operations passwd_file_ops = {
295 */ 288 */
296static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child) 289static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child)
297{ 290{
298 if (seclvl >= 0) { 291 if (seclvl >= 0 && child->pid == 1) {
299 if (child->pid == 1) { 292 seclvl_printk(1, KERN_WARNING, "Attempt to ptrace "
300 seclvl_printk(1, KERN_WARNING, "Attempt to ptrace " 293 "the init process dissallowed in "
301 "the init process dissallowed in " 294 "secure level %d\n", seclvl);
302 "secure level %d\n", seclvl); 295 return -EPERM;
303 return -EPERM;
304 }
305 } 296 }
306 return 0; 297 return 0;
307} 298}
@@ -312,55 +303,54 @@ static int seclvl_ptrace(struct task_struct *parent, struct task_struct *child)
312 */ 303 */
313static int seclvl_capable(struct task_struct *tsk, int cap) 304static int seclvl_capable(struct task_struct *tsk, int cap)
314{ 305{
306 int rc = 0;
307
315 /* init can do anything it wants */ 308 /* init can do anything it wants */
316 if (tsk->pid == 1) 309 if (tsk->pid == 1)
317 return 0; 310 return 0;
318 311
319 switch (seclvl) { 312 if (seclvl > 0) {
320 case 2: 313 rc = -EPERM;
321 /* fall through */ 314
322 case 1: 315 if (cap == CAP_LINUX_IMMUTABLE)
323 if (cap == CAP_LINUX_IMMUTABLE) {
324 seclvl_printk(1, KERN_WARNING, "Attempt to modify " 316 seclvl_printk(1, KERN_WARNING, "Attempt to modify "
325 "the IMMUTABLE and/or APPEND extended " 317 "the IMMUTABLE and/or APPEND extended "
326 "attribute on a file with the IMMUTABLE " 318 "attribute on a file with the IMMUTABLE "
327 "and/or APPEND extended attribute set " 319 "and/or APPEND extended attribute set "
328 "denied in seclvl [%d]\n", seclvl); 320 "denied in seclvl [%d]\n", seclvl);
329 return -EPERM; 321 else if (cap == CAP_SYS_RAWIO)
330 } else if (cap == CAP_SYS_RAWIO) { // Somewhat broad...
331 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 322 seclvl_printk(1, KERN_WARNING, "Attempt to perform "
332 "raw I/O while in secure level [%d] " 323 "raw I/O while in secure level [%d] "
333 "denied\n", seclvl); 324 "denied\n", seclvl);
334 return -EPERM; 325 else if (cap == CAP_NET_ADMIN)
335 } else if (cap == CAP_NET_ADMIN) {
336 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 326 seclvl_printk(1, KERN_WARNING, "Attempt to perform "
337 "network administrative task while " 327 "network administrative task while "
338 "in secure level [%d] denied\n", seclvl); 328 "in secure level [%d] denied\n", seclvl);
339 return -EPERM; 329 else if (cap == CAP_SETUID)
340 } else if (cap == CAP_SETUID) {
341 seclvl_printk(1, KERN_WARNING, "Attempt to setuid " 330 seclvl_printk(1, KERN_WARNING, "Attempt to setuid "
342 "while in secure level [%d] denied\n", 331 "while in secure level [%d] denied\n",
343 seclvl); 332 seclvl);
344 return -EPERM; 333 else if (cap == CAP_SETGID)
345 } else if (cap == CAP_SETGID) {
346 seclvl_printk(1, KERN_WARNING, "Attempt to setgid " 334 seclvl_printk(1, KERN_WARNING, "Attempt to setgid "
347 "while in secure level [%d] denied\n", 335 "while in secure level [%d] denied\n",
348 seclvl); 336 seclvl);
349 } else if (cap == CAP_SYS_MODULE) { 337 else if (cap == CAP_SYS_MODULE)
350 seclvl_printk(1, KERN_WARNING, "Attempt to perform " 338 seclvl_printk(1, KERN_WARNING, "Attempt to perform "
351 "a module operation while in secure " 339 "a module operation while in secure "
352 "level [%d] denied\n", seclvl); 340 "level [%d] denied\n", seclvl);
353 return -EPERM; 341 else
354 } 342 rc = 0;
355 break;
356 default:
357 break;
358 } 343 }
359 /* from dummy.c */ 344
360 if (cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0) 345 if (!rc) {
361 return 0; /* capability granted */ 346 if (!(cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0))
362 seclvl_printk(1, KERN_WARNING, "Capability denied\n"); 347 rc = -EPERM;
363 return -EPERM; /* capability denied */ 348 }
349
350 if (rc)
351 seclvl_printk(1, KERN_WARNING, "Capability denied\n");
352
353 return rc;
364} 354}
365 355
366/** 356/**
@@ -466,12 +456,9 @@ static int seclvl_inode_setattr(struct dentry *dentry, struct iattr *iattr)
466static void seclvl_file_free_security(struct file *filp) 456static void seclvl_file_free_security(struct file *filp)
467{ 457{
468 struct dentry *dentry = filp->f_dentry; 458 struct dentry *dentry = filp->f_dentry;
469 struct inode *inode = NULL;
470 459
471 if (dentry) { 460 if (dentry)
472 inode = dentry->d_inode; 461 seclvl_bd_release(dentry->d_inode);
473 seclvl_bd_release(inode);
474 }
475} 462}
476 463
477/** 464/**
@@ -479,9 +466,7 @@ static void seclvl_file_free_security(struct file *filp)
479 */ 466 */
480static int seclvl_umount(struct vfsmount *mnt, int flags) 467static int seclvl_umount(struct vfsmount *mnt, int flags)
481{ 468{
482 if (current->pid == 1) 469 if (current->pid != 1 && seclvl == 2) {
483 return 0;
484 if (seclvl == 2) {
485 seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " 470 seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure "
486 "level %d\n", seclvl); 471 "level %d\n", seclvl);
487 return -EPERM; 472 return -EPERM;
@@ -505,8 +490,9 @@ static struct security_operations seclvl_ops = {
505static int processPassword(void) 490static int processPassword(void)
506{ 491{
507 int rc = 0; 492 int rc = 0;
508 hashedPassword[0] = '\0';
509 if (*passwd) { 493 if (*passwd) {
494 char *p;
495
510 if (*sha1_passwd) { 496 if (*sha1_passwd) {
511 seclvl_printk(0, KERN_ERR, "Error: Both " 497 seclvl_printk(0, KERN_ERR, "Error: Both "
512 "passwd and sha1_passwd " 498 "passwd and sha1_passwd "
@@ -514,12 +500,16 @@ static int processPassword(void)
514 "exclusive.\n"); 500 "exclusive.\n");
515 return -EINVAL; 501 return -EINVAL;
516 } 502 }
517 if ((rc = plaintext_to_sha1(hashedPassword, passwd, 503
518 strlen(passwd)))) { 504 p = kstrdup(passwd, GFP_KERNEL);
505 if (p == NULL)
506 return -ENOMEM;
507
508 if ((rc = plaintext_to_sha1(hashedPassword, p, strlen(p))))
519 seclvl_printk(0, KERN_ERR, "Error: SHA1 support not " 509 seclvl_printk(0, KERN_ERR, "Error: SHA1 support not "
520 "in kernel\n"); 510 "in kernel\n");
521 return rc; 511
522 } 512 kfree (p);
523 /* All static data goes to the BSS, which zero's the 513 /* All static data goes to the BSS, which zero's the
524 * plaintext password out for us. */ 514 * plaintext password out for us. */
525 } else if (*sha1_passwd) { // Base 16 515 } else if (*sha1_passwd) { // Base 16
@@ -542,7 +532,7 @@ static int processPassword(void)
542 sha1_passwd[i + 2] = tmp; 532 sha1_passwd[i + 2] = tmp;
543 } 533 }
544 } 534 }
545 return 0; 535 return rc;
546} 536}
547 537
548/** 538/**
@@ -552,28 +542,46 @@ struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
552 542
553static int seclvlfs_register(void) 543static int seclvlfs_register(void)
554{ 544{
545 int rc = 0;
546
555 dir_ino = securityfs_create_dir("seclvl", NULL); 547 dir_ino = securityfs_create_dir("seclvl", NULL);
556 if (!dir_ino) 548
557 return -EFAULT; 549 if (IS_ERR(dir_ino))
550 return PTR_ERR(dir_ino);
558 551
559 seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR, 552 seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
560 dir_ino, &seclvl, &seclvl_file_ops); 553 dir_ino, &seclvl, &seclvl_file_ops);
561 if (!seclvl_ino) 554 if (IS_ERR(seclvl_ino)) {
555 rc = PTR_ERR(seclvl_ino);
562 goto out_deldir; 556 goto out_deldir;
557 }
563 if (*passwd || *sha1_passwd) { 558 if (*passwd || *sha1_passwd) {
564 passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR, 559 passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
565 dir_ino, NULL, &passwd_file_ops); 560 dir_ino, NULL, &passwd_file_ops);
566 if (!passwd_ino) 561 if (IS_ERR(passwd_ino)) {
562 rc = PTR_ERR(passwd_ino);
567 goto out_delf; 563 goto out_delf;
564 }
568 } 565 }
569 return 0; 566 return rc;
567
568out_delf:
569 securityfs_remove(seclvl_ino);
570 570
571out_deldir: 571out_deldir:
572 securityfs_remove(dir_ino); 572 securityfs_remove(dir_ino);
573out_delf: 573
574 return rc;
575}
576
577static void seclvlfs_unregister(void)
578{
574 securityfs_remove(seclvl_ino); 579 securityfs_remove(seclvl_ino);
575 580
576 return -EFAULT; 581 if (*passwd || *sha1_passwd)
582 securityfs_remove(passwd_ino);
583
584 securityfs_remove(dir_ino);
577} 585}
578 586
579/** 587/**
@@ -582,6 +590,8 @@ out_delf:
582static int __init seclvl_init(void) 590static int __init seclvl_init(void)
583{ 591{
584 int rc = 0; 592 int rc = 0;
593 static char once;
594
585 if (verbosity < 0 || verbosity > 1) { 595 if (verbosity < 0 || verbosity > 1) {
586 printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 " 596 printk(KERN_ERR "Error: bad verbosity [%d]; only 0 or 1 "
587 "are valid values\n", verbosity); 597 "are valid values\n", verbosity);
@@ -600,6 +610,11 @@ static int __init seclvl_init(void)
600 "module parameter(s): rc = [%d]\n", rc); 610 "module parameter(s): rc = [%d]\n", rc);
601 goto exit; 611 goto exit;
602 } 612 }
613
614 if ((rc = seclvlfs_register())) {
615 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
616 goto exit;
617 }
603 /* register ourselves with the security framework */ 618 /* register ourselves with the security framework */
604 if (register_security(&seclvl_ops)) { 619 if (register_security(&seclvl_ops)) {
605 seclvl_printk(0, KERN_ERR, 620 seclvl_printk(0, KERN_ERR,
@@ -611,20 +626,24 @@ static int __init seclvl_init(void)
611 seclvl_printk(0, KERN_ERR, "seclvl: Failure " 626 seclvl_printk(0, KERN_ERR, "seclvl: Failure "
612 "registering with primary security " 627 "registering with primary security "
613 "module.\n"); 628 "module.\n");
629 seclvlfs_unregister();
614 goto exit; 630 goto exit;
615 } /* if primary module registered */ 631 } /* if primary module registered */
616 secondary = 1; 632 secondary = 1;
617 } /* if we registered ourselves with the security framework */ 633 } /* if we registered ourselves with the security framework */
618 if ((rc = seclvlfs_register())) { 634
619 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
620 goto exit;
621 }
622 seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n"); 635 seclvl_printk(0, KERN_INFO, "seclvl: Successfully initialized.\n");
636
637 if (once) {
638 once = 1;
639 seclvl_printk(0, KERN_INFO, "seclvl is going away. It has been "
640 "buggy for ages. Also, be warned that "
641 "Securelevels are useless.");
642 }
623 exit: 643 exit:
624 if (rc) { 644 if (rc)
625 printk(KERN_ERR "seclvl: Error during initialization: rc = " 645 printk(KERN_ERR "seclvl: Error during initialization: rc = "
626 "[%d]\n", rc); 646 "[%d]\n", rc);
627 }
628 return rc; 647 return rc;
629} 648}
630 649
@@ -633,17 +652,14 @@ static int __init seclvl_init(void)
633 */ 652 */
634static void __exit seclvl_exit(void) 653static void __exit seclvl_exit(void)
635{ 654{
636 securityfs_remove(seclvl_ino); 655 seclvlfs_unregister();
637 if (*passwd || *sha1_passwd) 656
638 securityfs_remove(passwd_ino); 657 if (secondary)
639 securityfs_remove(dir_ino);
640 if (secondary == 1) {
641 mod_unreg_security(MY_NAME, &seclvl_ops); 658 mod_unreg_security(MY_NAME, &seclvl_ops);
642 } else if (unregister_security(&seclvl_ops)) { 659 else if (unregister_security(&seclvl_ops))
643 seclvl_printk(0, KERN_INFO, 660 seclvl_printk(0, KERN_INFO,
644 "seclvl: Failure unregistering with the " 661 "seclvl: Failure unregistering with the "
645 "kernel\n"); 662 "kernel\n");
646 }
647} 663}
648 664
649module_init(seclvl_init); 665module_init(seclvl_init);
diff --git a/security/security.c b/security/security.c
index f693e1f66b98..51ef509710b9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -174,31 +174,8 @@ int mod_unreg_security(const char *name, struct security_operations *ops)
174 return security_ops->unregister_security(name, ops); 174 return security_ops->unregister_security(name, ops);
175} 175}
176 176
177/**
178 * capable - calls the currently loaded security module's capable() function with the specified capability
179 * @cap: the requested capability level.
180 *
181 * This function calls the currently loaded security module's capable()
182 * function with a pointer to the current task and the specified @cap value.
183 *
184 * This allows the security module to implement the capable function call
185 * however it chooses to.
186 */
187int capable(int cap)
188{
189 if (security_ops->capable(current, cap)) {
190 /* capability denied */
191 return 0;
192 }
193
194 /* capability granted */
195 current->flags |= PF_SUPERPRIV;
196 return 1;
197}
198
199EXPORT_SYMBOL_GPL(register_security); 177EXPORT_SYMBOL_GPL(register_security);
200EXPORT_SYMBOL_GPL(unregister_security); 178EXPORT_SYMBOL_GPL(unregister_security);
201EXPORT_SYMBOL_GPL(mod_reg_security); 179EXPORT_SYMBOL_GPL(mod_reg_security);
202EXPORT_SYMBOL_GPL(mod_unreg_security); 180EXPORT_SYMBOL_GPL(mod_unreg_security);
203EXPORT_SYMBOL(capable);
204EXPORT_SYMBOL(security_ops); 181EXPORT_SYMBOL(security_ops);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b65c201e9ff5..b61b9554bc27 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -117,6 +117,34 @@ static struct security_operations *secondary_ops = NULL;
117static LIST_HEAD(superblock_security_head); 117static LIST_HEAD(superblock_security_head);
118static DEFINE_SPINLOCK(sb_security_lock); 118static DEFINE_SPINLOCK(sb_security_lock);
119 119
120static kmem_cache_t *sel_inode_cache;
121
122/* Return security context for a given sid or just the context
123 length if the buffer is null or length is 0 */
124static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
125{
126 char *context;
127 unsigned len;
128 int rc;
129
130 rc = security_sid_to_context(sid, &context, &len);
131 if (rc)
132 return rc;
133
134 if (!buffer || !size)
135 goto getsecurity_exit;
136
137 if (size < len) {
138 len = -ERANGE;
139 goto getsecurity_exit;
140 }
141 memcpy(buffer, context, len);
142
143getsecurity_exit:
144 kfree(context);
145 return len;
146}
147
120/* Allocate and free functions for each kind of security blob. */ 148/* Allocate and free functions for each kind of security blob. */
121 149
122static int task_alloc_security(struct task_struct *task) 150static int task_alloc_security(struct task_struct *task)
@@ -146,10 +174,11 @@ static int inode_alloc_security(struct inode *inode)
146 struct task_security_struct *tsec = current->security; 174 struct task_security_struct *tsec = current->security;
147 struct inode_security_struct *isec; 175 struct inode_security_struct *isec;
148 176
149 isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL); 177 isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL);
150 if (!isec) 178 if (!isec)
151 return -ENOMEM; 179 return -ENOMEM;
152 180
181 memset(isec, 0, sizeof(*isec));
153 init_MUTEX(&isec->sem); 182 init_MUTEX(&isec->sem);
154 INIT_LIST_HEAD(&isec->list); 183 INIT_LIST_HEAD(&isec->list);
155 isec->inode = inode; 184 isec->inode = inode;
@@ -172,7 +201,7 @@ static void inode_free_security(struct inode *inode)
172 spin_unlock(&sbsec->isec_lock); 201 spin_unlock(&sbsec->isec_lock);
173 202
174 inode->i_security = NULL; 203 inode->i_security = NULL;
175 kfree(isec); 204 kmem_cache_free(sel_inode_cache, isec);
176} 205}
177 206
178static int file_alloc_security(struct file *file) 207static int file_alloc_security(struct file *file)
@@ -1929,7 +1958,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1929 struct task_security_struct *tsec; 1958 struct task_security_struct *tsec;
1930 struct inode_security_struct *dsec; 1959 struct inode_security_struct *dsec;
1931 struct superblock_security_struct *sbsec; 1960 struct superblock_security_struct *sbsec;
1932 struct inode_security_struct *isec;
1933 u32 newsid, clen; 1961 u32 newsid, clen;
1934 int rc; 1962 int rc;
1935 char *namep = NULL, *context; 1963 char *namep = NULL, *context;
@@ -1937,7 +1965,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1937 tsec = current->security; 1965 tsec = current->security;
1938 dsec = dir->i_security; 1966 dsec = dir->i_security;
1939 sbsec = dir->i_sb->s_security; 1967 sbsec = dir->i_sb->s_security;
1940 isec = inode->i_security;
1941 1968
1942 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { 1969 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1943 newsid = tsec->create_sid; 1970 newsid = tsec->create_sid;
@@ -1957,7 +1984,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1957 1984
1958 inode_security_set_sid(inode, newsid); 1985 inode_security_set_sid(inode, newsid);
1959 1986
1960 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 1987 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
1961 return -EOPNOTSUPP; 1988 return -EOPNOTSUPP;
1962 1989
1963 if (name) { 1990 if (name) {
@@ -2209,6 +2236,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2209 return -EACCES; 2236 return -EACCES;
2210} 2237}
2211 2238
2239static const char *selinux_inode_xattr_getsuffix(void)
2240{
2241 return XATTR_SELINUX_SUFFIX;
2242}
2243
2212/* 2244/*
2213 * Copy the in-core inode security context value to the user. If the 2245 * Copy the in-core inode security context value to the user. If the
2214 * getxattr() prior to this succeeded, check to see if we need to 2246 * getxattr() prior to this succeeded, check to see if we need to
@@ -2216,47 +2248,14 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2216 * 2248 *
2217 * Permission check is handled by selinux_inode_getxattr hook. 2249 * Permission check is handled by selinux_inode_getxattr hook.
2218 */ 2250 */
2219static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) 2251static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
2220{ 2252{
2221 struct inode_security_struct *isec = inode->i_security; 2253 struct inode_security_struct *isec = inode->i_security;
2222 char *context;
2223 unsigned len;
2224 int rc;
2225 2254
2226 if (strcmp(name, XATTR_SELINUX_SUFFIX)) { 2255 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2227 rc = -EOPNOTSUPP; 2256 return -EOPNOTSUPP;
2228 goto out;
2229 }
2230
2231 rc = security_sid_to_context(isec->sid, &context, &len);
2232 if (rc)
2233 goto out;
2234
2235 /* Probe for required buffer size */
2236 if (!buffer || !size) {
2237 rc = len;
2238 goto out_free;
2239 }
2240
2241 if (size < len) {
2242 rc = -ERANGE;
2243 goto out_free;
2244 }
2245 2257
2246 if (err > 0) { 2258 return selinux_getsecurity(isec->sid, buffer, size);
2247 if ((len == err) && !(memcmp(context, buffer, len))) {
2248 /* Don't need to canonicalize value */
2249 rc = err;
2250 goto out_free;
2251 }
2252 memset(buffer, 0, size);
2253 }
2254 memcpy(buffer, context, len);
2255 rc = len;
2256out_free:
2257 kfree(context);
2258out:
2259 return rc;
2260} 2259}
2261 2260
2262static int selinux_inode_setsecurity(struct inode *inode, const char *name, 2261static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -3318,24 +3317,38 @@ out:
3318 return err; 3317 return err;
3319} 3318}
3320 3319
3321static int selinux_socket_getpeersec(struct socket *sock, char __user *optval, 3320static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
3322 int __user *optlen, unsigned len) 3321 int __user *optlen, unsigned len)
3323{ 3322{
3324 int err = 0; 3323 int err = 0;
3325 char *scontext; 3324 char *scontext;
3326 u32 scontext_len; 3325 u32 scontext_len;
3327 struct sk_security_struct *ssec; 3326 struct sk_security_struct *ssec;
3328 struct inode_security_struct *isec; 3327 struct inode_security_struct *isec;
3328 u32 peer_sid = 0;
3329 3329
3330 isec = SOCK_INODE(sock)->i_security; 3330 isec = SOCK_INODE(sock)->i_security;
3331 if (isec->sclass != SECCLASS_UNIX_STREAM_SOCKET) { 3331
3332 /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */
3333 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) {
3334 ssec = sock->sk->sk_security;
3335 peer_sid = ssec->peer_sid;
3336 }
3337 else if (isec->sclass == SECCLASS_TCP_SOCKET) {
3338 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3339
3340 if (peer_sid == SECSID_NULL) {
3341 err = -ENOPROTOOPT;
3342 goto out;
3343 }
3344 }
3345 else {
3332 err = -ENOPROTOOPT; 3346 err = -ENOPROTOOPT;
3333 goto out; 3347 goto out;
3334 } 3348 }
3335 3349
3336 ssec = sock->sk->sk_security; 3350 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
3337 3351
3338 err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
3339 if (err) 3352 if (err)
3340 goto out; 3353 goto out;
3341 3354
@@ -3356,6 +3369,23 @@ out:
3356 return err; 3369 return err;
3357} 3370}
3358 3371
3372static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
3373{
3374 int err = 0;
3375 u32 peer_sid = selinux_socket_getpeer_dgram(skb);
3376
3377 if (peer_sid == SECSID_NULL)
3378 return -EINVAL;
3379
3380 err = security_sid_to_context(peer_sid, secdata, seclen);
3381 if (err)
3382 return err;
3383
3384 return 0;
3385}
3386
3387
3388
3359static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 3389static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
3360{ 3390{
3361 return sk_alloc_security(sk, family, priority); 3391 return sk_alloc_security(sk, family, priority);
@@ -4022,6 +4052,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4022 return ipc_has_perm(ipcp, av); 4052 return ipc_has_perm(ipcp, av);
4023} 4053}
4024 4054
4055static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
4056{
4057 struct ipc_security_struct *isec = ipcp->security;
4058
4059 return selinux_getsecurity(isec->sid, buffer, size);
4060}
4061
4025/* module stacking operations */ 4062/* module stacking operations */
4026static int selinux_register_security (const char *name, struct security_operations *ops) 4063static int selinux_register_security (const char *name, struct security_operations *ops)
4027{ 4064{
@@ -4063,8 +4100,7 @@ static int selinux_getprocattr(struct task_struct *p,
4063 char *name, void *value, size_t size) 4100 char *name, void *value, size_t size)
4064{ 4101{
4065 struct task_security_struct *tsec; 4102 struct task_security_struct *tsec;
4066 u32 sid, len; 4103 u32 sid;
4067 char *context;
4068 int error; 4104 int error;
4069 4105
4070 if (current != p) { 4106 if (current != p) {
@@ -4073,9 +4109,6 @@ static int selinux_getprocattr(struct task_struct *p,
4073 return error; 4109 return error;
4074 } 4110 }
4075 4111
4076 if (!size)
4077 return -ERANGE;
4078
4079 tsec = p->security; 4112 tsec = p->security;
4080 4113
4081 if (!strcmp(name, "current")) 4114 if (!strcmp(name, "current"))
@@ -4092,16 +4125,7 @@ static int selinux_getprocattr(struct task_struct *p,
4092 if (!sid) 4125 if (!sid)
4093 return 0; 4126 return 0;
4094 4127
4095 error = security_sid_to_context(sid, &context, &len); 4128 return selinux_getsecurity(sid, value, size);
4096 if (error)
4097 return error;
4098 if (len > size) {
4099 kfree(context);
4100 return -ERANGE;
4101 }
4102 memcpy(value, context, len);
4103 kfree(context);
4104 return len;
4105} 4129}
4106 4130
4107static int selinux_setprocattr(struct task_struct *p, 4131static int selinux_setprocattr(struct task_struct *p,
@@ -4259,6 +4283,7 @@ static struct security_operations selinux_ops = {
4259 .inode_getxattr = selinux_inode_getxattr, 4283 .inode_getxattr = selinux_inode_getxattr,
4260 .inode_listxattr = selinux_inode_listxattr, 4284 .inode_listxattr = selinux_inode_listxattr,
4261 .inode_removexattr = selinux_inode_removexattr, 4285 .inode_removexattr = selinux_inode_removexattr,
4286 .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
4262 .inode_getsecurity = selinux_inode_getsecurity, 4287 .inode_getsecurity = selinux_inode_getsecurity,
4263 .inode_setsecurity = selinux_inode_setsecurity, 4288 .inode_setsecurity = selinux_inode_setsecurity,
4264 .inode_listsecurity = selinux_inode_listsecurity, 4289 .inode_listsecurity = selinux_inode_listsecurity,
@@ -4296,6 +4321,7 @@ static struct security_operations selinux_ops = {
4296 .task_to_inode = selinux_task_to_inode, 4321 .task_to_inode = selinux_task_to_inode,
4297 4322
4298 .ipc_permission = selinux_ipc_permission, 4323 .ipc_permission = selinux_ipc_permission,
4324 .ipc_getsecurity = selinux_ipc_getsecurity,
4299 4325
4300 .msg_msg_alloc_security = selinux_msg_msg_alloc_security, 4326 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
4301 .msg_msg_free_security = selinux_msg_msg_free_security, 4327 .msg_msg_free_security = selinux_msg_msg_free_security,
@@ -4344,7 +4370,8 @@ static struct security_operations selinux_ops = {
4344 .socket_setsockopt = selinux_socket_setsockopt, 4370 .socket_setsockopt = selinux_socket_setsockopt,
4345 .socket_shutdown = selinux_socket_shutdown, 4371 .socket_shutdown = selinux_socket_shutdown,
4346 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, 4372 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
4347 .socket_getpeersec = selinux_socket_getpeersec, 4373 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
4374 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
4348 .sk_alloc_security = selinux_sk_alloc_security, 4375 .sk_alloc_security = selinux_sk_alloc_security,
4349 .sk_free_security = selinux_sk_free_security, 4376 .sk_free_security = selinux_sk_free_security,
4350 .sk_getsid = selinux_sk_getsid_security, 4377 .sk_getsid = selinux_sk_getsid_security,
@@ -4376,6 +4403,9 @@ static __init int selinux_init(void)
4376 tsec = current->security; 4403 tsec = current->security;
4377 tsec->osid = tsec->sid = SECINITSID_KERNEL; 4404 tsec->osid = tsec->sid = SECINITSID_KERNEL;
4378 4405
4406 sel_inode_cache = kmem_cache_create("selinux_inode_security",
4407 sizeof(struct inode_security_struct),
4408 0, SLAB_PANIC, NULL, NULL);
4379 avc_init(); 4409 avc_init();
4380 4410
4381 original_ops = secondary_ops = security_ops; 4411 original_ops = secondary_ops = security_ops;
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 8e87996c6dd5..c10f1fc41502 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -39,6 +39,8 @@ static inline u32 selinux_no_sk_sid(struct flowi *fl)
39#ifdef CONFIG_SECURITY_NETWORK_XFRM 39#ifdef CONFIG_SECURITY_NETWORK_XFRM
40int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb); 40int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
41int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb); 41int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
42u32 selinux_socket_getpeer_stream(struct sock *sk);
43u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
42#else 44#else
43static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) 45static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
44{ 46{
@@ -49,6 +51,16 @@ static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
49{ 51{
50 return NF_ACCEPT; 52 return NF_ACCEPT;
51} 53}
54
55static inline int selinux_socket_getpeer_stream(struct sock *sk)
56{
57 return SECSID_NULL;
58}
59
60static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
61{
62 return SECSID_NULL;
63}
52#endif 64#endif
53 65
54#endif /* _SELINUX_XFRM_H_ */ 66#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 69b9329b2054..b8f4d25cf335 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -88,8 +88,15 @@ static struct nlmsg_perm nlmsg_xfrm_perms[] =
88 { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 88 { XFRM_MSG_DELPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
89 { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ }, 89 { XFRM_MSG_GETPOLICY, NETLINK_XFRM_SOCKET__NLMSG_READ },
90 { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 90 { XFRM_MSG_ALLOCSPI, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
91 { XFRM_MSG_ACQUIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
92 { XFRM_MSG_EXPIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
91 { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 93 { XFRM_MSG_UPDPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
92 { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE }, 94 { XFRM_MSG_UPDSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
95 { XFRM_MSG_POLEXPIRE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
96 { XFRM_MSG_FLUSHSA, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
97 { XFRM_MSG_FLUSHPOLICY, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
98 { XFRM_MSG_NEWAE, NETLINK_XFRM_SOCKET__NLMSG_WRITE },
99 { XFRM_MSG_GETAE, NETLINK_XFRM_SOCKET__NLMSG_READ },
93}; 100};
94 101
95static struct nlmsg_perm nlmsg_audit_perms[] = 102static struct nlmsg_perm nlmsg_audit_perms[] =
@@ -99,6 +106,9 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
99 { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV }, 106 { AUDIT_LIST, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
100 { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, 107 { AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
101 { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, 108 { AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
109 { AUDIT_LIST_RULES, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
110 { AUDIT_ADD_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
111 { AUDIT_DEL_RULE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
102 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY }, 112 { AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
103 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ }, 113 { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
104}; 114};
@@ -145,8 +155,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
145 break; 155 break;
146 156
147 case SECCLASS_NETLINK_AUDIT_SOCKET: 157 case SECCLASS_NETLINK_AUDIT_SOCKET:
148 if (nlmsg_type >= AUDIT_FIRST_USER_MSG && 158 if ((nlmsg_type >= AUDIT_FIRST_USER_MSG &&
149 nlmsg_type <= AUDIT_LAST_USER_MSG) { 159 nlmsg_type <= AUDIT_LAST_USER_MSG) ||
160 (nlmsg_type >= AUDIT_FIRST_USER_MSG2 &&
161 nlmsg_type <= AUDIT_LAST_USER_MSG2)) {
150 *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY; 162 *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
151 } else { 163 } else {
152 err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms, 164 err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index b5fa02d17b1e..a4efc966f065 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -15,12 +15,14 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/vmalloc.h> 16#include <linux/vmalloc.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18#include <linux/mutex.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/string.h> 20#include <linux/string.h>
20#include <linux/security.h> 21#include <linux/security.h>
21#include <linux/major.h> 22#include <linux/major.h>
22#include <linux/seq_file.h> 23#include <linux/seq_file.h>
23#include <linux/percpu.h> 24#include <linux/percpu.h>
25#include <linux/audit.h>
24#include <asm/uaccess.h> 26#include <asm/uaccess.h>
25#include <asm/semaphore.h> 27#include <asm/semaphore.h>
26 28
@@ -44,7 +46,7 @@ static int __init checkreqprot_setup(char *str)
44__setup("checkreqprot=", checkreqprot_setup); 46__setup("checkreqprot=", checkreqprot_setup);
45 47
46 48
47static DECLARE_MUTEX(sel_sem); 49static DEFINE_MUTEX(sel_mutex);
48 50
49/* global data for booleans */ 51/* global data for booleans */
50static struct dentry *bool_dir = NULL; 52static struct dentry *bool_dir = NULL;
@@ -126,6 +128,10 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
126 length = task_has_security(current, SECURITY__SETENFORCE); 128 length = task_has_security(current, SECURITY__SETENFORCE);
127 if (length) 129 if (length)
128 goto out; 130 goto out;
131 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
132 "enforcing=%d old_enforcing=%d auid=%u", new_value,
133 selinux_enforcing,
134 audit_get_loginuid(current->audit_context));
129 selinux_enforcing = new_value; 135 selinux_enforcing = new_value;
130 if (selinux_enforcing) 136 if (selinux_enforcing)
131 avc_ss_reset(0); 137 avc_ss_reset(0);
@@ -176,6 +182,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
176 length = selinux_disable(); 182 length = selinux_disable();
177 if (length < 0) 183 if (length < 0)
178 goto out; 184 goto out;
185 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
186 "selinux=0 auid=%u",
187 audit_get_loginuid(current->audit_context));
179 } 188 }
180 189
181 length = count; 190 length = count;
@@ -230,7 +239,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
230 ssize_t length; 239 ssize_t length;
231 void *data = NULL; 240 void *data = NULL;
232 241
233 down(&sel_sem); 242 mutex_lock(&sel_mutex);
234 243
235 length = task_has_security(current, SECURITY__LOAD_POLICY); 244 length = task_has_security(current, SECURITY__LOAD_POLICY);
236 if (length) 245 if (length)
@@ -261,8 +270,11 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
261 length = ret; 270 length = ret;
262 else 271 else
263 length = count; 272 length = count;
273 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
274 "policy loaded auid=%u",
275 audit_get_loginuid(current->audit_context));
264out: 276out:
265 up(&sel_sem); 277 mutex_unlock(&sel_mutex);
266 vfree(data); 278 vfree(data);
267 return length; 279 return length;
268} 280}
@@ -709,12 +721,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
709{ 721{
710 char *page = NULL; 722 char *page = NULL;
711 ssize_t length; 723 ssize_t length;
712 ssize_t end;
713 ssize_t ret; 724 ssize_t ret;
714 int cur_enforcing; 725 int cur_enforcing;
715 struct inode *inode; 726 struct inode *inode;
716 727
717 down(&sel_sem); 728 mutex_lock(&sel_mutex);
718 729
719 ret = -EFAULT; 730 ret = -EFAULT;
720 731
@@ -740,26 +751,9 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
740 751
741 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, 752 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
742 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); 753 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
743 if (length < 0) { 754 ret = simple_read_from_buffer(buf, count, ppos, page, length);
744 ret = length;
745 goto out;
746 }
747
748 if (*ppos >= length) {
749 ret = 0;
750 goto out;
751 }
752 if (count + *ppos > length)
753 count = length - *ppos;
754 end = count + *ppos;
755 if (copy_to_user(buf, (char *) page + *ppos, count)) {
756 ret = -EFAULT;
757 goto out;
758 }
759 *ppos = end;
760 ret = count;
761out: 755out:
762 up(&sel_sem); 756 mutex_unlock(&sel_mutex);
763 if (page) 757 if (page)
764 free_page((unsigned long)page); 758 free_page((unsigned long)page);
765 return ret; 759 return ret;
@@ -773,7 +767,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
773 int new_value; 767 int new_value;
774 struct inode *inode; 768 struct inode *inode;
775 769
776 down(&sel_sem); 770 mutex_lock(&sel_mutex);
777 771
778 length = task_has_security(current, SECURITY__SETBOOL); 772 length = task_has_security(current, SECURITY__SETBOOL);
779 if (length) 773 if (length)
@@ -812,7 +806,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
812 length = count; 806 length = count;
813 807
814out: 808out:
815 up(&sel_sem); 809 mutex_unlock(&sel_mutex);
816 if (page) 810 if (page)
817 free_page((unsigned long) page); 811 free_page((unsigned long) page);
818 return length; 812 return length;
@@ -831,7 +825,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
831 ssize_t length = -EFAULT; 825 ssize_t length = -EFAULT;
832 int new_value; 826 int new_value;
833 827
834 down(&sel_sem); 828 mutex_lock(&sel_mutex);
835 829
836 length = task_has_security(current, SECURITY__SETBOOL); 830 length = task_has_security(current, SECURITY__SETBOOL);
837 if (length) 831 if (length)
@@ -869,7 +863,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
869 length = count; 863 length = count;
870 864
871out: 865out:
872 up(&sel_sem); 866 mutex_unlock(&sel_mutex);
873 if (page) 867 if (page)
874 free_page((unsigned long) page); 868 free_page((unsigned long) page);
875 return length; 869 return length;
@@ -987,7 +981,7 @@ out:
987 return ret; 981 return ret;
988err: 982err:
989 kfree(values); 983 kfree(values);
990 d_genocide(dir); 984 sel_remove_bools(dir);
991 ret = -ENOMEM; 985 ret = -ENOMEM;
992 goto out; 986 goto out;
993} 987}
@@ -1168,37 +1162,38 @@ static int sel_make_avc_files(struct dentry *dir)
1168 dentry = d_alloc_name(dir, files[i].name); 1162 dentry = d_alloc_name(dir, files[i].name);
1169 if (!dentry) { 1163 if (!dentry) {
1170 ret = -ENOMEM; 1164 ret = -ENOMEM;
1171 goto err; 1165 goto out;
1172 } 1166 }
1173 1167
1174 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode); 1168 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
1175 if (!inode) { 1169 if (!inode) {
1176 ret = -ENOMEM; 1170 ret = -ENOMEM;
1177 goto err; 1171 goto out;
1178 } 1172 }
1179 inode->i_fop = files[i].ops; 1173 inode->i_fop = files[i].ops;
1180 d_add(dentry, inode); 1174 d_add(dentry, inode);
1181 } 1175 }
1182out: 1176out:
1183 return ret; 1177 return ret;
1184err:
1185 d_genocide(dir);
1186 goto out;
1187} 1178}
1188 1179
1189static int sel_make_dir(struct super_block *sb, struct dentry *dentry) 1180static int sel_make_dir(struct inode *dir, struct dentry *dentry)
1190{ 1181{
1191 int ret = 0; 1182 int ret = 0;
1192 struct inode *inode; 1183 struct inode *inode;
1193 1184
1194 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1185 inode = sel_make_inode(dir->i_sb, S_IFDIR | S_IRUGO | S_IXUGO);
1195 if (!inode) { 1186 if (!inode) {
1196 ret = -ENOMEM; 1187 ret = -ENOMEM;
1197 goto out; 1188 goto out;
1198 } 1189 }
1199 inode->i_op = &simple_dir_inode_operations; 1190 inode->i_op = &simple_dir_inode_operations;
1200 inode->i_fop = &simple_dir_operations; 1191 inode->i_fop = &simple_dir_operations;
1192 /* directory inodes start off with i_nlink == 2 (for "." entry) */
1193 inode->i_nlink++;
1201 d_add(dentry, inode); 1194 d_add(dentry, inode);
1195 /* bump link count on parent directory, too */
1196 dir->i_nlink++;
1202out: 1197out:
1203 return ret; 1198 return ret;
1204} 1199}
@@ -1207,7 +1202,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1207{ 1202{
1208 int ret; 1203 int ret;
1209 struct dentry *dentry; 1204 struct dentry *dentry;
1210 struct inode *inode; 1205 struct inode *inode, *root_inode;
1211 struct inode_security_struct *isec; 1206 struct inode_security_struct *isec;
1212 1207
1213 static struct tree_descr selinux_files[] = { 1208 static struct tree_descr selinux_files[] = {
@@ -1228,30 +1223,33 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1228 }; 1223 };
1229 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1224 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
1230 if (ret) 1225 if (ret)
1231 return ret; 1226 goto err;
1227
1228 root_inode = sb->s_root->d_inode;
1232 1229
1233 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); 1230 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
1234 if (!dentry) 1231 if (!dentry) {
1235 return -ENOMEM; 1232 ret = -ENOMEM;
1233 goto err;
1234 }
1236 1235
1237 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1236 ret = sel_make_dir(root_inode, dentry);
1238 if (!inode)
1239 goto out;
1240 inode->i_op = &simple_dir_inode_operations;
1241 inode->i_fop = &simple_dir_operations;
1242 d_add(dentry, inode);
1243 bool_dir = dentry;
1244 ret = sel_make_bools();
1245 if (ret) 1237 if (ret)
1246 goto out; 1238 goto err;
1239
1240 bool_dir = dentry;
1247 1241
1248 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); 1242 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
1249 if (!dentry) 1243 if (!dentry) {
1250 return -ENOMEM; 1244 ret = -ENOMEM;
1245 goto err;
1246 }
1251 1247
1252 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); 1248 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
1253 if (!inode) 1249 if (!inode) {
1254 goto out; 1250 ret = -ENOMEM;
1251 goto err;
1252 }
1255 isec = (struct inode_security_struct*)inode->i_security; 1253 isec = (struct inode_security_struct*)inode->i_security;
1256 isec->sid = SECINITSID_DEVNULL; 1254 isec->sid = SECINITSID_DEVNULL;
1257 isec->sclass = SECCLASS_CHR_FILE; 1255 isec->sclass = SECCLASS_CHR_FILE;
@@ -1262,22 +1260,23 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1262 selinux_null = dentry; 1260 selinux_null = dentry;
1263 1261
1264 dentry = d_alloc_name(sb->s_root, "avc"); 1262 dentry = d_alloc_name(sb->s_root, "avc");
1265 if (!dentry) 1263 if (!dentry) {
1266 return -ENOMEM; 1264 ret = -ENOMEM;
1265 goto err;
1266 }
1267 1267
1268 ret = sel_make_dir(sb, dentry); 1268 ret = sel_make_dir(root_inode, dentry);
1269 if (ret) 1269 if (ret)
1270 goto out; 1270 goto err;
1271 1271
1272 ret = sel_make_avc_files(dentry); 1272 ret = sel_make_avc_files(dentry);
1273 if (ret) 1273 if (ret)
1274 goto out; 1274 goto err;
1275
1276 return 0;
1277out: 1275out:
1278 dput(dentry); 1276 return ret;
1277err:
1279 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); 1278 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
1280 return -ENOMEM; 1279 goto out;
1281} 1280}
1282 1281
1283static struct super_block *sel_get_sb(struct file_system_type *fs_type, 1282static struct super_block *sel_get_sb(struct file_system_type *fs_type,
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 8a764928ff4b..61492485de84 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -27,7 +27,8 @@
27#include <linux/in.h> 27#include <linux/in.h>
28#include <linux/sched.h> 28#include <linux/sched.h>
29#include <linux/audit.h> 29#include <linux/audit.h>
30#include <asm/semaphore.h> 30#include <linux/mutex.h>
31
31#include "flask.h" 32#include "flask.h"
32#include "avc.h" 33#include "avc.h"
33#include "avc_ss.h" 34#include "avc_ss.h"
@@ -48,9 +49,9 @@ static DEFINE_RWLOCK(policy_rwlock);
48#define POLICY_RDUNLOCK read_unlock(&policy_rwlock) 49#define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
49#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock) 50#define POLICY_WRUNLOCK write_unlock_irq(&policy_rwlock)
50 51
51static DECLARE_MUTEX(load_sem); 52static DEFINE_MUTEX(load_mutex);
52#define LOAD_LOCK down(&load_sem) 53#define LOAD_LOCK mutex_lock(&load_mutex)
53#define LOAD_UNLOCK up(&load_sem) 54#define LOAD_UNLOCK mutex_unlock(&load_mutex)
54 55
55static struct sidtab sidtab; 56static struct sidtab sidtab;
56struct policydb policydb; 57struct policydb policydb;
@@ -1758,19 +1759,22 @@ int security_set_bools(int len, int *values)
1758 goto out; 1759 goto out;
1759 } 1760 }
1760 1761
1761 printk(KERN_INFO "security: committed booleans { ");
1762 for (i = 0; i < len; i++) { 1762 for (i = 0; i < len; i++) {
1763 if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
1764 audit_log(current->audit_context, GFP_ATOMIC,
1765 AUDIT_MAC_CONFIG_CHANGE,
1766 "bool=%s val=%d old_val=%d auid=%u",
1767 policydb.p_bool_val_to_name[i],
1768 !!values[i],
1769 policydb.bool_val_to_struct[i]->state,
1770 audit_get_loginuid(current->audit_context));
1771 }
1763 if (values[i]) { 1772 if (values[i]) {
1764 policydb.bool_val_to_struct[i]->state = 1; 1773 policydb.bool_val_to_struct[i]->state = 1;
1765 } else { 1774 } else {
1766 policydb.bool_val_to_struct[i]->state = 0; 1775 policydb.bool_val_to_struct[i]->state = 0;
1767 } 1776 }
1768 if (i != 0)
1769 printk(", ");
1770 printk("%s:%d", policydb.p_bool_val_to_name[i],
1771 policydb.bool_val_to_struct[i]->state);
1772 } 1777 }
1773 printk(" }\n");
1774 1778
1775 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 1779 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
1776 rc = evaluate_cond_node(&policydb, cur); 1780 rc = evaluate_cond_node(&policydb, cur);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index b2af7ca496c1..dfab6c886698 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -225,6 +225,74 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
225} 225}
226 226
227/* 227/*
228 * SELinux internal function to retrieve the context of a connected
229 * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
230 * association used to connect to the remote socket.
231 *
232 * Retrieve via getsockopt SO_PEERSEC.
233 */
234u32 selinux_socket_getpeer_stream(struct sock *sk)
235{
236 struct dst_entry *dst, *dst_test;
237 u32 peer_sid = SECSID_NULL;
238
239 if (sk->sk_state != TCP_ESTABLISHED)
240 goto out;
241
242 dst = sk_dst_get(sk);
243 if (!dst)
244 goto out;
245
246 for (dst_test = dst; dst_test != 0;
247 dst_test = dst_test->child) {
248 struct xfrm_state *x = dst_test->xfrm;
249
250 if (x && selinux_authorizable_xfrm(x)) {
251 struct xfrm_sec_ctx *ctx = x->security;
252 peer_sid = ctx->ctx_sid;
253 break;
254 }
255 }
256 dst_release(dst);
257
258out:
259 return peer_sid;
260}
261
262/*
263 * SELinux internal function to retrieve the context of a UDP packet
264 * based on its security association used to connect to the remote socket.
265 *
266 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
267 * type SCM_SECURITY.
268 */
269u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
270{
271 struct sec_path *sp;
272
273 if (skb == NULL)
274 return SECSID_NULL;
275
276 if (skb->sk->sk_protocol != IPPROTO_UDP)
277 return SECSID_NULL;
278
279 sp = skb->sp;
280 if (sp) {
281 int i;
282
283 for (i = sp->len-1; i >= 0; i--) {
284 struct xfrm_state *x = sp->x[i].xvec;
285 if (selinux_authorizable_xfrm(x)) {
286 struct xfrm_sec_ctx *ctx = x->security;
287 return ctx->ctx_sid;
288 }
289 }
290 }
291
292 return SECSID_NULL;
293}
294
295/*
228 * LSM hook that controls access to unlabelled packets. If 296 * LSM hook that controls access to unlabelled packets. If
229 * a xfrm_state is authorizable (defined by macro) then it was 297 * a xfrm_state is authorizable (defined by macro) then it was
230 * already authorized by the IPSec process. If not, then 298 * already authorized by the IPSec process. If not, then