keys: increase the payload size when instantiating a key

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 <dhowells@redhat.com>
Cc: Paul Moore <paul.moore@hp.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: James Morris <jmorris@namei.org>
Cc: Kevin Coffman <kwc@citi.umich.edu>
Cc: Steven French <sfrench@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
David Howells 2008-04-29 01:01:19 -07:00 committed by Linus Torvalds
parent 4220b7fe89
commit 38bbca6b6f
1 changed files with 30 additions and 8 deletions

View File

@ -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;