aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/keys/keyctl.c56
1 files changed, 26 insertions, 30 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index eff88a5f5d40..4743d71e4aa6 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -26,6 +26,8 @@
26#include <asm/uaccess.h> 26#include <asm/uaccess.h>
27#include "internal.h" 27#include "internal.h"
28 28
29#define KEY_MAX_DESC_SIZE 4096
30
29static int key_get_type_from_user(char *type, 31static int key_get_type_from_user(char *type,
30 const char __user *_type, 32 const char __user *_type,
31 unsigned len) 33 unsigned len)
@@ -78,7 +80,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
78 80
79 description = NULL; 81 description = NULL;
80 if (_description) { 82 if (_description) {
81 description = strndup_user(_description, PAGE_SIZE); 83 description = strndup_user(_description, KEY_MAX_DESC_SIZE);
82 if (IS_ERR(description)) { 84 if (IS_ERR(description)) {
83 ret = PTR_ERR(description); 85 ret = PTR_ERR(description);
84 goto error; 86 goto error;
@@ -177,7 +179,7 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
177 goto error; 179 goto error;
178 180
179 /* pull the description into kernel space */ 181 /* pull the description into kernel space */
180 description = strndup_user(_description, PAGE_SIZE); 182 description = strndup_user(_description, KEY_MAX_DESC_SIZE);
181 if (IS_ERR(description)) { 183 if (IS_ERR(description)) {
182 ret = PTR_ERR(description); 184 ret = PTR_ERR(description);
183 goto error; 185 goto error;
@@ -287,7 +289,7 @@ long keyctl_join_session_keyring(const char __user *_name)
287 /* fetch the name from userspace */ 289 /* fetch the name from userspace */
288 name = NULL; 290 name = NULL;
289 if (_name) { 291 if (_name) {
290 name = strndup_user(_name, PAGE_SIZE); 292 name = strndup_user(_name, KEY_MAX_DESC_SIZE);
291 if (IS_ERR(name)) { 293 if (IS_ERR(name)) {
292 ret = PTR_ERR(name); 294 ret = PTR_ERR(name);
293 goto error; 295 goto error;
@@ -562,8 +564,9 @@ long keyctl_describe_key(key_serial_t keyid,
562{ 564{
563 struct key *key, *instkey; 565 struct key *key, *instkey;
564 key_ref_t key_ref; 566 key_ref_t key_ref;
565 char *tmpbuf; 567 char *infobuf;
566 long ret; 568 long ret;
569 int desclen, infolen;
567 570
568 key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW); 571 key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
569 if (IS_ERR(key_ref)) { 572 if (IS_ERR(key_ref)) {
@@ -586,38 +589,31 @@ long keyctl_describe_key(key_serial_t keyid,
586 } 589 }
587 590
588okay: 591okay:
589 /* calculate how much description we're going to return */
590 ret = -ENOMEM;
591 tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
592 if (!tmpbuf)
593 goto error2;
594
595 key = key_ref_to_ptr(key_ref); 592 key = key_ref_to_ptr(key_ref);
593 desclen = strlen(key->description);
596 594
597 ret = snprintf(tmpbuf, PAGE_SIZE - 1, 595 /* calculate how much information we're going to return */
598 "%s;%d;%d;%08x;%s", 596 ret = -ENOMEM;
599 key->type->name, 597 infobuf = kasprintf(GFP_KERNEL,
600 from_kuid_munged(current_user_ns(), key->uid), 598 "%s;%d;%d;%08x;",
601 from_kgid_munged(current_user_ns(), key->gid), 599 key->type->name,
602 key->perm, 600 from_kuid_munged(current_user_ns(), key->uid),
603 key->description ?: ""); 601 from_kgid_munged(current_user_ns(), key->gid),
604 602 key->perm);
605 /* include a NUL char at the end of the data */ 603 if (!infobuf)
606 if (ret > PAGE_SIZE - 1) 604 goto error2;
607 ret = PAGE_SIZE - 1; 605 infolen = strlen(infobuf);
608 tmpbuf[ret] = 0; 606 ret = infolen + desclen + 1;
609 ret++;
610 607
611 /* consider returning the data */ 608 /* consider returning the data */
612 if (buffer && buflen > 0) { 609 if (buffer && buflen >= ret) {
613 if (buflen > ret) 610 if (copy_to_user(buffer, infobuf, infolen) != 0 ||
614 buflen = ret; 611 copy_to_user(buffer + infolen, key->description,
615 612 desclen + 1) != 0)
616 if (copy_to_user(buffer, tmpbuf, buflen) != 0)
617 ret = -EFAULT; 613 ret = -EFAULT;
618 } 614 }
619 615
620 kfree(tmpbuf); 616 kfree(infobuf);
621error2: 617error2:
622 key_ref_put(key_ref); 618 key_ref_put(key_ref);
623error: 619error:
@@ -649,7 +645,7 @@ long keyctl_keyring_search(key_serial_t ringid,
649 if (ret < 0) 645 if (ret < 0)
650 goto error; 646 goto error;
651 647
652 description = strndup_user(_description, PAGE_SIZE); 648 description = strndup_user(_description, KEY_MAX_DESC_SIZE);
653 if (IS_ERR(description)) { 649 if (IS_ERR(description)) {
654 ret = PTR_ERR(description); 650 ret = PTR_ERR(description);
655 goto error; 651 goto error;