|
@@ -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,
|
|
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;
|
|
|
|
- dlen = strnlen_user(_description, PAGE_SIZE - 1);
|
|
|
|
- if (dlen <= 0)
|
|
|
|
- goto error;
|
|
|
|
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- if (dlen > PAGE_SIZE - 1)
|
|
|
|
- goto error;
|
|
|
|
-
|
|
|
|
- ret = -ENOMEM;
|
|
|
|
- description = kmalloc(dlen + 1, GFP_KERNEL);
|
|
|
|
- if (!description)
|
|
|
|
|
|
+ description = strndup_user(_description, PAGE_SIZE);
|
|
|
|
+ if (IS_ERR(description)) {
|
|
|
|
+ ret = PTR_ERR(description);
|
|
goto error;
|
|
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,
|
|
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;
|
|
|
|
- dlen = strnlen_user(_description, PAGE_SIZE - 1);
|
|
|
|
- if (dlen <= 0)
|
|
|
|
- goto error;
|
|
|
|
-
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- if (dlen > PAGE_SIZE - 1)
|
|
|
|
- goto error;
|
|
|
|
-
|
|
|
|
- ret = -ENOMEM;
|
|
|
|
- description = kmalloc(dlen + 1, GFP_KERNEL);
|
|
|
|
- if (!description)
|
|
|
|
|
|
+ description = strndup_user(_description, PAGE_SIZE);
|
|
|
|
+ if (IS_ERR(description)) {
|
|
|
|
+ ret = PTR_ERR(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;
|
|
|
|
- dlen = strnlen_user(_callout_info, PAGE_SIZE - 1);
|
|
|
|
- if (dlen <= 0)
|
|
|
|
- goto error2;
|
|
|
|
-
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- if (dlen > PAGE_SIZE - 1)
|
|
|
|
- goto error2;
|
|
|
|
-
|
|
|
|
- ret = -ENOMEM;
|
|
|
|
- callout_info = kmalloc(dlen + 1, GFP_KERNEL);
|
|
|
|
- if (!callout_info)
|
|
|
|
|
|
+ callout_info = strndup_user(_callout_info, PAGE_SIZE);
|
|
|
|
+ if (IS_ERR(callout_info)) {
|
|
|
|
+ ret = PTR_ERR(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)
|
|
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;
|
|
|
|
- nlen = strnlen_user(_name, PAGE_SIZE - 1);
|
|
|
|
- if (nlen <= 0)
|
|
|
|
- goto error;
|
|
|
|
-
|
|
|
|
- ret = -EINVAL;
|
|
|
|
- if (nlen > PAGE_SIZE - 1)
|
|
|
|
|
|
+ name = strndup_user(_name, PAGE_SIZE);
|
|
|
|
+ if (IS_ERR(name)) {
|
|
|
|
+ ret = PTR_ERR(name);
|
|
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,
|
|
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)
|
|
|
|
|
|
+ description = strndup_user(_description, PAGE_SIZE);
|
|
|
|
+ if (IS_ERR(description)) {
|
|
|
|
+ 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;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
/* 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);
|