diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/keyctl.c | 155 |
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 | ||
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); |