Commit 0cb409d9 authored by Davi Arnaut's avatar Davi Arnaut Committed by Linus Torvalds

[PATCH] strndup_user: convert keyctl

Copies user-space string with strndup_user() and moves the type string
duplication code to a function (thus fixing a wrong check on the length of the
type.)
Signed-off-by: default avatarDavi Arnaut <davi.arnaut@gmail.com>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 24277dda
...@@ -17,10 +17,33 @@ ...@@ -17,10 +17,33 @@
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <linux/string.h>
#include <linux/err.h> #include <linux/err.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "internal.h" #include "internal.h"
static int key_get_type_from_user(char *type,
const char __user *_type,
unsigned len)
{
int ret;
ret = strncpy_from_user(type, _type, len);
if (ret < 0)
return -EFAULT;
if (ret == 0 || ret >= len)
return -EINVAL;
if (type[0] == '.')
return -EPERM;
type[len - 1] = '\0';
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
/* /*
* extract the description of a new key from userspace and either add it as a * 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,40 +61,22 @@ asmlinkage long sys_add_key(const char __user *_type,
key_ref_t keyring_ref, key_ref; key_ref_t keyring_ref, key_ref;
char type[32], *description; char type[32], *description;
void *payload; void *payload;
long dlen, ret; long ret;
ret = -EINVAL; ret = -EINVAL;
if (plen > 32767) if (plen > 32767)
goto error; goto error;
/* draw all the data into kernel space */ /* draw all the data into kernel space */
ret = strncpy_from_user(type, _type, sizeof(type) - 1); ret = key_get_type_from_user(type, _type, sizeof(type));
if (ret < 0) if (ret < 0)
goto error; goto error;
type[31] = '\0';
ret = -EPERM;
if (type[0] == '.')
goto error;
ret = -EFAULT; description = strndup_user(_description, PAGE_SIZE);
dlen = strnlen_user(_description, PAGE_SIZE - 1); if (IS_ERR(description)) {
if (dlen <= 0) ret = PTR_ERR(description);
goto error; goto error;
}
ret = -EINVAL;
if (dlen > PAGE_SIZE - 1)
goto error;
ret = -ENOMEM;
description = kmalloc(dlen + 1, GFP_KERNEL);
if (!description)
goto error;
description[dlen] = '\0';
ret = -EFAULT;
if (copy_from_user(description, _description, dlen) != 0)
goto error2;
/* pull the payload in if one was supplied */ /* pull the payload in if one was supplied */
payload = NULL; payload = NULL;
...@@ -136,59 +141,28 @@ asmlinkage long sys_request_key(const char __user *_type, ...@@ -136,59 +141,28 @@ asmlinkage long sys_request_key(const char __user *_type,
struct key *key; struct key *key;
key_ref_t dest_ref; key_ref_t dest_ref;
char type[32], *description, *callout_info; char type[32], *description, *callout_info;
long dlen, ret; long ret;
/* pull the type into kernel space */ /* pull the type into kernel space */
ret = strncpy_from_user(type, _type, sizeof(type) - 1); ret = key_get_type_from_user(type, _type, sizeof(type));
if (ret < 0) if (ret < 0)
goto error; goto error;
type[31] = '\0';
ret = -EPERM;
if (type[0] == '.')
goto error;
/* pull the description into kernel space */ /* pull the description into kernel space */
ret = -EFAULT; description = strndup_user(_description, PAGE_SIZE);
dlen = strnlen_user(_description, PAGE_SIZE - 1); if (IS_ERR(description)) {
if (dlen <= 0) ret = PTR_ERR(description);
goto error;
ret = -EINVAL;
if (dlen > PAGE_SIZE - 1)
goto error;
ret = -ENOMEM;
description = kmalloc(dlen + 1, GFP_KERNEL);
if (!description)
goto error; goto error;
description[dlen] = '\0'; }
ret = -EFAULT;
if (copy_from_user(description, _description, dlen) != 0)
goto error2;
/* pull the callout info into kernel space */ /* pull the callout info into kernel space */
callout_info = NULL; callout_info = NULL;
if (_callout_info) { if (_callout_info) {
ret = -EFAULT; callout_info = strndup_user(_callout_info, PAGE_SIZE);
dlen = strnlen_user(_callout_info, PAGE_SIZE - 1); if (IS_ERR(callout_info)) {
if (dlen <= 0) ret = PTR_ERR(callout_info);
goto error2;
ret = -EINVAL;
if (dlen > PAGE_SIZE - 1)
goto error2;
ret = -ENOMEM;
callout_info = kmalloc(dlen + 1, GFP_KERNEL);
if (!callout_info)
goto error2; goto error2;
callout_info[dlen] = '\0'; }
ret = -EFAULT;
if (copy_from_user(callout_info, _callout_info, dlen) != 0)
goto error3;
} }
/* get the destination keyring if specified */ /* get the destination keyring if specified */
...@@ -264,36 +238,21 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) ...@@ -264,36 +238,21 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
long keyctl_join_session_keyring(const char __user *_name) long keyctl_join_session_keyring(const char __user *_name)
{ {
char *name; char *name;
long nlen, ret; long ret;
/* fetch the name from userspace */ /* fetch the name from userspace */
name = NULL; name = NULL;
if (_name) { if (_name) {
ret = -EFAULT; name = strndup_user(_name, PAGE_SIZE);
nlen = strnlen_user(_name, PAGE_SIZE - 1); if (IS_ERR(name)) {
if (nlen <= 0) ret = PTR_ERR(name);
goto error;
ret = -EINVAL;
if (nlen > PAGE_SIZE - 1)
goto error; goto error;
}
ret = -ENOMEM;
name = kmalloc(nlen + 1, GFP_KERNEL);
if (!name)
goto error;
name[nlen] = '\0';
ret = -EFAULT;
if (copy_from_user(name, _name, nlen) != 0)
goto error2;
} }
/* join the session */ /* join the session */
ret = join_session_keyring(name); ret = join_session_keyring(name);
error2:
kfree(name);
error: error:
return ret; return ret;
...@@ -566,32 +525,18 @@ long keyctl_keyring_search(key_serial_t ringid, ...@@ -566,32 +525,18 @@ long keyctl_keyring_search(key_serial_t ringid,
struct key_type *ktype; struct key_type *ktype;
key_ref_t keyring_ref, key_ref, dest_ref; key_ref_t keyring_ref, key_ref, dest_ref;
char type[32], *description; char type[32], *description;
long dlen, ret; long ret;
/* pull the type and description into kernel space */ /* pull the type and description into kernel space */
ret = strncpy_from_user(type, _type, sizeof(type) - 1); ret = key_get_type_from_user(type, _type, sizeof(type));
if (ret < 0) if (ret < 0)
goto error; goto error;
type[31] = '\0';
ret = -EFAULT;
dlen = strnlen_user(_description, PAGE_SIZE - 1);
if (dlen <= 0)
goto error;
ret = -EINVAL;
if (dlen > PAGE_SIZE - 1)
goto error;
ret = -ENOMEM; description = strndup_user(_description, PAGE_SIZE);
description = kmalloc(dlen + 1, GFP_KERNEL); if (IS_ERR(description)) {
if (!description) ret = PTR_ERR(description);
goto error; goto error;
description[dlen] = '\0'; }
ret = -EFAULT;
if (copy_from_user(description, _description, dlen) != 0)
goto error2;
/* get the keyring at which to begin the search */ /* get the keyring at which to begin the search */
keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment