Increase the size of a payload that can be used to instantiate a key in
add_key() and keyctl_instantiate_key().  This permits huge CIFS SPNEGO blobs to
be passed around.  The limit is raised to 1MB.  If kmalloc() can't allocate a
buffer of sufficient size, vmalloc() will be tried instead.

Signed-off-by: David Howells <[EMAIL PROTECTED]>
---

 security/keys/keyctl.c |   38 ++++++++++++++++++++++++++++++--------
 1 files changed, 30 insertions(+), 8 deletions(-)


diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d9ca15c..8ec8432 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -19,6 +19,7 @@
 #include <linux/capability.h>
 #include <linux/string.h>
 #include <linux/err.h>
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -62,9 +63,10 @@ asmlinkage long sys_add_key(const char __user *_type,
        char type[32], *description;
        void *payload;
        long ret;
+       bool vm;
 
        ret = -EINVAL;
-       if (plen > 32767)
+       if (plen > 1024 * 1024 - 1)
                goto error;
 
        /* draw all the data into kernel space */
@@ -81,11 +83,18 @@ asmlinkage long sys_add_key(const char __user *_type,
        /* pull the payload in if one was supplied */
        payload = NULL;
 
+       vm = false;
        if (_payload) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
-               if (!payload)
-                       goto error2;
+               if (!payload) {
+                       if (plen <= PAGE_SIZE)
+                               goto error2;
+                       vm = true;
+                       payload = vmalloc(plen);
+                       if (!payload)
+                               goto error2;
+               }
 
                ret = -EFAULT;
                if (copy_from_user(payload, _payload, plen) != 0)
@@ -113,7 +122,10 @@ asmlinkage long sys_add_key(const char __user *_type,
 
        key_ref_put(keyring_ref);
  error3:
-       kfree(payload);
+       if (!vm)
+               kfree(payload);
+       else
+               vfree(payload);
  error2:
        kfree(description);
  error:
@@ -821,9 +833,10 @@ long keyctl_instantiate_key(key_serial_t id,
        key_ref_t keyring_ref;
        void *payload;
        long ret;
+       bool vm = false;
 
        ret = -EINVAL;
-       if (plen > 32767)
+       if (plen > 1024 * 1024 - 1)
                goto error;
 
        /* the appropriate instantiation authorisation key must have been
@@ -843,8 +856,14 @@ long keyctl_instantiate_key(key_serial_t id,
        if (_payload) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
-               if (!payload)
-                       goto error;
+               if (!payload) {
+                       if (plen <= PAGE_SIZE)
+                               goto error;
+                       vm = true;
+                       payload = vmalloc(plen);
+                       if (!payload)
+                               goto error;
+               }
 
                ret = -EFAULT;
                if (copy_from_user(payload, _payload, plen) != 0)
@@ -877,7 +896,10 @@ long keyctl_instantiate_key(key_serial_t id,
        }
 
 error2:
-       kfree(payload);
+       if (!vm)
+               kfree(payload);
+       else
+               vfree(payload);
 error:
        return ret;
 

-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to