aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c4
-rw-r--r--security/keys/key.c18
-rw-r--r--security/keys/keyctl.c155
-rw-r--r--security/security.c23
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)
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/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/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);