From: David Howells 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 Cc: Paul Moore Cc: Chris Wright Cc: Stephen Smalley Cc: James Morris Cc: Kevin Coffman Cc: Steven French Signed-off-by: Andrew Morton --- security/keys/keyctl.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff -puN security/keys/keyctl.c~keys-increase-the-payload-size-when-instantiating-a-key security/keys/keyctl.c --- a/security/keys/keyctl.c~keys-increase-the-payload-size-when-instantiating-a-key +++ a/security/keys/keyctl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "internal.h" @@ -62,9 +63,10 @@ asmlinkage long sys_add_key(const char _ 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 _ /* 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 _ 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 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 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 } error2: - kfree(payload); + if (!vm) + kfree(payload); + else + vfree(payload); error: return ret; _