aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/keyctl.c155
1 files changed, 50 insertions, 105 deletions
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);