aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c4
-rw-r--r--security/dummy.c13
-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.c60
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/nlmsgtab.c7
-rw-r--r--security/selinux/selinuxfs.c112
-rw-r--r--security/selinux/ss/services.c9
-rw-r--r--security/selinux/xfrm.c68
13 files changed, 380 insertions, 318 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 0a553d39729f..fd99429278e9 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -773,8 +773,14 @@ static int dummy_socket_sock_rcv_skb (struct sock *sk, struct sk_buff *skb)
773 return 0; 773 return 0;
774} 774}
775 775
776static int dummy_socket_getpeersec(struct socket *sock, char __user *optval, 776static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optval,
777 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)
778{ 784{
779 return -ENOPROTOOPT; 785 return -ENOPROTOOPT;
780} 786}
@@ -1014,7 +1020,8 @@ void security_fixup_ops (struct security_operations *ops)
1014 set_to_dummy_if_null(ops, socket_getsockopt); 1020 set_to_dummy_if_null(ops, socket_getsockopt);
1015 set_to_dummy_if_null(ops, socket_shutdown); 1021 set_to_dummy_if_null(ops, socket_shutdown);
1016 set_to_dummy_if_null(ops, socket_sock_rcv_skb); 1022 set_to_dummy_if_null(ops, socket_sock_rcv_skb);
1017 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);
1018 set_to_dummy_if_null(ops, sk_alloc_security); 1025 set_to_dummy_if_null(ops, sk_alloc_security);
1019 set_to_dummy_if_null(ops, sk_free_security); 1026 set_to_dummy_if_null(ops, sk_free_security);
1020 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 81b726b1a419..b61b9554bc27 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -117,6 +117,8 @@ 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
120/* Return security context for a given sid or just the context 122/* Return security context for a given sid or just the context
121 length if the buffer is null or length is 0 */ 123 length if the buffer is null or length is 0 */
122static int selinux_getsecurity(u32 sid, void *buffer, size_t size) 124static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
@@ -172,10 +174,11 @@ static int inode_alloc_security(struct inode *inode)
172 struct task_security_struct *tsec = current->security; 174 struct task_security_struct *tsec = current->security;
173 struct inode_security_struct *isec; 175 struct inode_security_struct *isec;
174 176
175 isec = kzalloc(sizeof(struct inode_security_struct), GFP_KERNEL); 177 isec = kmem_cache_alloc(sel_inode_cache, SLAB_KERNEL);
176 if (!isec) 178 if (!isec)
177 return -ENOMEM; 179 return -ENOMEM;
178 180
181 memset(isec, 0, sizeof(*isec));
179 init_MUTEX(&isec->sem); 182 init_MUTEX(&isec->sem);
180 INIT_LIST_HEAD(&isec->list); 183 INIT_LIST_HEAD(&isec->list);
181 isec->inode = inode; 184 isec->inode = inode;
@@ -198,7 +201,7 @@ static void inode_free_security(struct inode *inode)
198 spin_unlock(&sbsec->isec_lock); 201 spin_unlock(&sbsec->isec_lock);
199 202
200 inode->i_security = NULL; 203 inode->i_security = NULL;
201 kfree(isec); 204 kmem_cache_free(sel_inode_cache, isec);
202} 205}
203 206
204static int file_alloc_security(struct file *file) 207static int file_alloc_security(struct file *file)
@@ -1955,7 +1958,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1955 struct task_security_struct *tsec; 1958 struct task_security_struct *tsec;
1956 struct inode_security_struct *dsec; 1959 struct inode_security_struct *dsec;
1957 struct superblock_security_struct *sbsec; 1960 struct superblock_security_struct *sbsec;
1958 struct inode_security_struct *isec;
1959 u32 newsid, clen; 1961 u32 newsid, clen;
1960 int rc; 1962 int rc;
1961 char *namep = NULL, *context; 1963 char *namep = NULL, *context;
@@ -1963,7 +1965,6 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1963 tsec = current->security; 1965 tsec = current->security;
1964 dsec = dir->i_security; 1966 dsec = dir->i_security;
1965 sbsec = dir->i_sb->s_security; 1967 sbsec = dir->i_sb->s_security;
1966 isec = inode->i_security;
1967 1968
1968 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { 1969 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
1969 newsid = tsec->create_sid; 1970 newsid = tsec->create_sid;
@@ -1983,7 +1984,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
1983 1984
1984 inode_security_set_sid(inode, newsid); 1985 inode_security_set_sid(inode, newsid);
1985 1986
1986 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 1987 if (!ss_initialized || sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
1987 return -EOPNOTSUPP; 1988 return -EOPNOTSUPP;
1988 1989
1989 if (name) { 1990 if (name) {
@@ -3316,24 +3317,38 @@ out:
3316 return err; 3317 return err;
3317} 3318}
3318 3319
3319static int selinux_socket_getpeersec(struct socket *sock, char __user *optval, 3320static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
3320 int __user *optlen, unsigned len) 3321 int __user *optlen, unsigned len)
3321{ 3322{
3322 int err = 0; 3323 int err = 0;
3323 char *scontext; 3324 char *scontext;
3324 u32 scontext_len; 3325 u32 scontext_len;
3325 struct sk_security_struct *ssec; 3326 struct sk_security_struct *ssec;
3326 struct inode_security_struct *isec; 3327 struct inode_security_struct *isec;
3328 u32 peer_sid = 0;
3327 3329
3328 isec = SOCK_INODE(sock)->i_security; 3330 isec = SOCK_INODE(sock)->i_security;
3329 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 {
3330 err = -ENOPROTOOPT; 3346 err = -ENOPROTOOPT;
3331 goto out; 3347 goto out;
3332 } 3348 }
3333 3349
3334 ssec = sock->sk->sk_security; 3350 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
3335 3351
3336 err = security_sid_to_context(ssec->peer_sid, &scontext, &scontext_len);
3337 if (err) 3352 if (err)
3338 goto out; 3353 goto out;
3339 3354
@@ -3354,6 +3369,23 @@ out:
3354 return err; 3369 return err;
3355} 3370}
3356 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
3357static 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)
3358{ 3390{
3359 return sk_alloc_security(sk, family, priority); 3391 return sk_alloc_security(sk, family, priority);
@@ -4338,7 +4370,8 @@ static struct security_operations selinux_ops = {
4338 .socket_setsockopt = selinux_socket_setsockopt, 4370 .socket_setsockopt = selinux_socket_setsockopt,
4339 .socket_shutdown = selinux_socket_shutdown, 4371 .socket_shutdown = selinux_socket_shutdown,
4340 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb, 4372 .socket_sock_rcv_skb = selinux_socket_sock_rcv_skb,
4341 .socket_getpeersec = selinux_socket_getpeersec, 4373 .socket_getpeersec_stream = selinux_socket_getpeersec_stream,
4374 .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram,
4342 .sk_alloc_security = selinux_sk_alloc_security, 4375 .sk_alloc_security = selinux_sk_alloc_security,
4343 .sk_free_security = selinux_sk_free_security, 4376 .sk_free_security = selinux_sk_free_security,
4344 .sk_getsid = selinux_sk_getsid_security, 4377 .sk_getsid = selinux_sk_getsid_security,
@@ -4370,6 +4403,9 @@ static __init int selinux_init(void)
4370 tsec = current->security; 4403 tsec = current->security;
4371 tsec->osid = tsec->sid = SECINITSID_KERNEL; 4404 tsec->osid = tsec->sid = SECINITSID_KERNEL;
4372 4405
4406 sel_inode_cache = kmem_cache_create("selinux_inode_security",
4407 sizeof(struct inode_security_struct),
4408 0, SLAB_PANIC, NULL, NULL);
4373 avc_init(); 4409 avc_init();
4374 4410
4375 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 73158244cf8c..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[] =
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 5eba6664eac0..a4efc966f065 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -15,6 +15,7 @@
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>
@@ -45,7 +46,7 @@ static int __init checkreqprot_setup(char *str)
45__setup("checkreqprot=", checkreqprot_setup); 46__setup("checkreqprot=", checkreqprot_setup);
46 47
47 48
48static DECLARE_MUTEX(sel_sem); 49static DEFINE_MUTEX(sel_mutex);
49 50
50/* global data for booleans */ 51/* global data for booleans */
51static struct dentry *bool_dir = NULL; 52static struct dentry *bool_dir = NULL;
@@ -238,7 +239,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
238 ssize_t length; 239 ssize_t length;
239 void *data = NULL; 240 void *data = NULL;
240 241
241 down(&sel_sem); 242 mutex_lock(&sel_mutex);
242 243
243 length = task_has_security(current, SECURITY__LOAD_POLICY); 244 length = task_has_security(current, SECURITY__LOAD_POLICY);
244 if (length) 245 if (length)
@@ -273,7 +274,7 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
273 "policy loaded auid=%u", 274 "policy loaded auid=%u",
274 audit_get_loginuid(current->audit_context)); 275 audit_get_loginuid(current->audit_context));
275out: 276out:
276 up(&sel_sem); 277 mutex_unlock(&sel_mutex);
277 vfree(data); 278 vfree(data);
278 return length; 279 return length;
279} 280}
@@ -720,12 +721,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
720{ 721{
721 char *page = NULL; 722 char *page = NULL;
722 ssize_t length; 723 ssize_t length;
723 ssize_t end;
724 ssize_t ret; 724 ssize_t ret;
725 int cur_enforcing; 725 int cur_enforcing;
726 struct inode *inode; 726 struct inode *inode;
727 727
728 down(&sel_sem); 728 mutex_lock(&sel_mutex);
729 729
730 ret = -EFAULT; 730 ret = -EFAULT;
731 731
@@ -751,26 +751,9 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
751 751
752 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, 752 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
753 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]); 753 bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
754 if (length < 0) { 754 ret = simple_read_from_buffer(buf, count, ppos, page, length);
755 ret = length;
756 goto out;
757 }
758
759 if (*ppos >= length) {
760 ret = 0;
761 goto out;
762 }
763 if (count + *ppos > length)
764 count = length - *ppos;
765 end = count + *ppos;
766 if (copy_to_user(buf, (char *) page + *ppos, count)) {
767 ret = -EFAULT;
768 goto out;
769 }
770 *ppos = end;
771 ret = count;
772out: 755out:
773 up(&sel_sem); 756 mutex_unlock(&sel_mutex);
774 if (page) 757 if (page)
775 free_page((unsigned long)page); 758 free_page((unsigned long)page);
776 return ret; 759 return ret;
@@ -784,7 +767,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
784 int new_value; 767 int new_value;
785 struct inode *inode; 768 struct inode *inode;
786 769
787 down(&sel_sem); 770 mutex_lock(&sel_mutex);
788 771
789 length = task_has_security(current, SECURITY__SETBOOL); 772 length = task_has_security(current, SECURITY__SETBOOL);
790 if (length) 773 if (length)
@@ -823,7 +806,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
823 length = count; 806 length = count;
824 807
825out: 808out:
826 up(&sel_sem); 809 mutex_unlock(&sel_mutex);
827 if (page) 810 if (page)
828 free_page((unsigned long) page); 811 free_page((unsigned long) page);
829 return length; 812 return length;
@@ -842,7 +825,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
842 ssize_t length = -EFAULT; 825 ssize_t length = -EFAULT;
843 int new_value; 826 int new_value;
844 827
845 down(&sel_sem); 828 mutex_lock(&sel_mutex);
846 829
847 length = task_has_security(current, SECURITY__SETBOOL); 830 length = task_has_security(current, SECURITY__SETBOOL);
848 if (length) 831 if (length)
@@ -880,7 +863,7 @@ static ssize_t sel_commit_bools_write(struct file *filep,
880 length = count; 863 length = count;
881 864
882out: 865out:
883 up(&sel_sem); 866 mutex_unlock(&sel_mutex);
884 if (page) 867 if (page)
885 free_page((unsigned long) page); 868 free_page((unsigned long) page);
886 return length; 869 return length;
@@ -998,7 +981,7 @@ out:
998 return ret; 981 return ret;
999err: 982err:
1000 kfree(values); 983 kfree(values);
1001 d_genocide(dir); 984 sel_remove_bools(dir);
1002 ret = -ENOMEM; 985 ret = -ENOMEM;
1003 goto out; 986 goto out;
1004} 987}
@@ -1179,37 +1162,38 @@ static int sel_make_avc_files(struct dentry *dir)
1179 dentry = d_alloc_name(dir, files[i].name); 1162 dentry = d_alloc_name(dir, files[i].name);
1180 if (!dentry) { 1163 if (!dentry) {
1181 ret = -ENOMEM; 1164 ret = -ENOMEM;
1182 goto err; 1165 goto out;
1183 } 1166 }
1184 1167
1185 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);
1186 if (!inode) { 1169 if (!inode) {
1187 ret = -ENOMEM; 1170 ret = -ENOMEM;
1188 goto err; 1171 goto out;
1189 } 1172 }
1190 inode->i_fop = files[i].ops; 1173 inode->i_fop = files[i].ops;
1191 d_add(dentry, inode); 1174 d_add(dentry, inode);
1192 } 1175 }
1193out: 1176out:
1194 return ret; 1177 return ret;
1195err:
1196 d_genocide(dir);
1197 goto out;
1198} 1178}
1199 1179
1200static int sel_make_dir(struct super_block *sb, struct dentry *dentry) 1180static int sel_make_dir(struct inode *dir, struct dentry *dentry)
1201{ 1181{
1202 int ret = 0; 1182 int ret = 0;
1203 struct inode *inode; 1183 struct inode *inode;
1204 1184
1205 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);
1206 if (!inode) { 1186 if (!inode) {
1207 ret = -ENOMEM; 1187 ret = -ENOMEM;
1208 goto out; 1188 goto out;
1209 } 1189 }
1210 inode->i_op = &simple_dir_inode_operations; 1190 inode->i_op = &simple_dir_inode_operations;
1211 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++;
1212 d_add(dentry, inode); 1194 d_add(dentry, inode);
1195 /* bump link count on parent directory, too */
1196 dir->i_nlink++;
1213out: 1197out:
1214 return ret; 1198 return ret;
1215} 1199}
@@ -1218,7 +1202,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1218{ 1202{
1219 int ret; 1203 int ret;
1220 struct dentry *dentry; 1204 struct dentry *dentry;
1221 struct inode *inode; 1205 struct inode *inode, *root_inode;
1222 struct inode_security_struct *isec; 1206 struct inode_security_struct *isec;
1223 1207
1224 static struct tree_descr selinux_files[] = { 1208 static struct tree_descr selinux_files[] = {
@@ -1239,30 +1223,33 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1239 }; 1223 };
1240 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1224 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
1241 if (ret) 1225 if (ret)
1242 return ret; 1226 goto err;
1227
1228 root_inode = sb->s_root->d_inode;
1243 1229
1244 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME); 1230 dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
1245 if (!dentry) 1231 if (!dentry) {
1246 return -ENOMEM; 1232 ret = -ENOMEM;
1233 goto err;
1234 }
1247 1235
1248 inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); 1236 ret = sel_make_dir(root_inode, dentry);
1249 if (!inode)
1250 goto out;
1251 inode->i_op = &simple_dir_inode_operations;
1252 inode->i_fop = &simple_dir_operations;
1253 d_add(dentry, inode);
1254 bool_dir = dentry;
1255 ret = sel_make_bools();
1256 if (ret) 1237 if (ret)
1257 goto out; 1238 goto err;
1239
1240 bool_dir = dentry;
1258 1241
1259 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME); 1242 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
1260 if (!dentry) 1243 if (!dentry) {
1261 return -ENOMEM; 1244 ret = -ENOMEM;
1245 goto err;
1246 }
1262 1247
1263 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); 1248 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
1264 if (!inode) 1249 if (!inode) {
1265 goto out; 1250 ret = -ENOMEM;
1251 goto err;
1252 }
1266 isec = (struct inode_security_struct*)inode->i_security; 1253 isec = (struct inode_security_struct*)inode->i_security;
1267 isec->sid = SECINITSID_DEVNULL; 1254 isec->sid = SECINITSID_DEVNULL;
1268 isec->sclass = SECCLASS_CHR_FILE; 1255 isec->sclass = SECCLASS_CHR_FILE;
@@ -1273,22 +1260,23 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1273 selinux_null = dentry; 1260 selinux_null = dentry;
1274 1261
1275 dentry = d_alloc_name(sb->s_root, "avc"); 1262 dentry = d_alloc_name(sb->s_root, "avc");
1276 if (!dentry) 1263 if (!dentry) {
1277 return -ENOMEM; 1264 ret = -ENOMEM;
1265 goto err;
1266 }
1278 1267
1279 ret = sel_make_dir(sb, dentry); 1268 ret = sel_make_dir(root_inode, dentry);
1280 if (ret) 1269 if (ret)
1281 goto out; 1270 goto err;
1282 1271
1283 ret = sel_make_avc_files(dentry); 1272 ret = sel_make_avc_files(dentry);
1284 if (ret) 1273 if (ret)
1285 goto out; 1274 goto err;
1286
1287 return 0;
1288out: 1275out:
1289 dput(dentry); 1276 return ret;
1277err:
1290 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); 1278 printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__);
1291 return -ENOMEM; 1279 goto out;
1292} 1280}
1293 1281
1294static 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 d877cd16a813..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;
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