diff options
| -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); |
