diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 4 | ||||
-rw-r--r-- | security/keys/key.c | 18 | ||||
-rw-r--r-- | security/keys/keyctl.c | 155 | ||||
-rw-r--r-- | security/security.c | 23 |
4 files changed, 63 insertions, 137 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) | |||
60 | int cap_ptrace (struct task_struct *parent, struct task_struct *child) | 60 | int 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/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 | ||
25 | static 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) | |||
264 | long keyctl_join_session_keyring(const char __user *_name) | 238 | long 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/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 | */ | ||
187 | int 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 | |||
199 | EXPORT_SYMBOL_GPL(register_security); | 177 | EXPORT_SYMBOL_GPL(register_security); |
200 | EXPORT_SYMBOL_GPL(unregister_security); | 178 | EXPORT_SYMBOL_GPL(unregister_security); |
201 | EXPORT_SYMBOL_GPL(mod_reg_security); | 179 | EXPORT_SYMBOL_GPL(mod_reg_security); |
202 | EXPORT_SYMBOL_GPL(mod_unreg_security); | 180 | EXPORT_SYMBOL_GPL(mod_unreg_security); |
203 | EXPORT_SYMBOL(capable); | ||
204 | EXPORT_SYMBOL(security_ops); | 181 | EXPORT_SYMBOL(security_ops); |