diff options
Diffstat (limited to 'security')
-rw-r--r-- | 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 d9ca15c109cc..8ec84326a983 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/capability.h> | 19 | #include <linux/capability.h> |
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/vmalloc.h> | ||
22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
@@ -62,9 +63,10 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
62 | char type[32], *description; | 63 | char type[32], *description; |
63 | void *payload; | 64 | void *payload; |
64 | long ret; | 65 | long ret; |
66 | bool vm; | ||
65 | 67 | ||
66 | ret = -EINVAL; | 68 | ret = -EINVAL; |
67 | if (plen > 32767) | 69 | if (plen > 1024 * 1024 - 1) |
68 | goto error; | 70 | goto error; |
69 | 71 | ||
70 | /* draw all the data into kernel space */ | 72 | /* draw all the data into kernel space */ |
@@ -81,11 +83,18 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
81 | /* pull the payload in if one was supplied */ | 83 | /* pull the payload in if one was supplied */ |
82 | payload = NULL; | 84 | payload = NULL; |
83 | 85 | ||
86 | vm = false; | ||
84 | if (_payload) { | 87 | if (_payload) { |
85 | ret = -ENOMEM; | 88 | ret = -ENOMEM; |
86 | payload = kmalloc(plen, GFP_KERNEL); | 89 | payload = kmalloc(plen, GFP_KERNEL); |
87 | if (!payload) | 90 | if (!payload) { |
88 | goto error2; | 91 | if (plen <= PAGE_SIZE) |
92 | goto error2; | ||
93 | vm = true; | ||
94 | payload = vmalloc(plen); | ||
95 | if (!payload) | ||
96 | goto error2; | ||
97 | } | ||
89 | 98 | ||
90 | ret = -EFAULT; | 99 | ret = -EFAULT; |
91 | if (copy_from_user(payload, _payload, plen) != 0) | 100 | if (copy_from_user(payload, _payload, plen) != 0) |
@@ -113,7 +122,10 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
113 | 122 | ||
114 | key_ref_put(keyring_ref); | 123 | key_ref_put(keyring_ref); |
115 | error3: | 124 | error3: |
116 | kfree(payload); | 125 | if (!vm) |
126 | kfree(payload); | ||
127 | else | ||
128 | vfree(payload); | ||
117 | error2: | 129 | error2: |
118 | kfree(description); | 130 | kfree(description); |
119 | error: | 131 | error: |
@@ -821,9 +833,10 @@ long keyctl_instantiate_key(key_serial_t id, | |||
821 | key_ref_t keyring_ref; | 833 | key_ref_t keyring_ref; |
822 | void *payload; | 834 | void *payload; |
823 | long ret; | 835 | long ret; |
836 | bool vm = false; | ||
824 | 837 | ||
825 | ret = -EINVAL; | 838 | ret = -EINVAL; |
826 | if (plen > 32767) | 839 | if (plen > 1024 * 1024 - 1) |
827 | goto error; | 840 | goto error; |
828 | 841 | ||
829 | /* the appropriate instantiation authorisation key must have been | 842 | /* the appropriate instantiation authorisation key must have been |
@@ -843,8 +856,14 @@ long keyctl_instantiate_key(key_serial_t id, | |||
843 | if (_payload) { | 856 | if (_payload) { |
844 | ret = -ENOMEM; | 857 | ret = -ENOMEM; |
845 | payload = kmalloc(plen, GFP_KERNEL); | 858 | payload = kmalloc(plen, GFP_KERNEL); |
846 | if (!payload) | 859 | if (!payload) { |
847 | goto error; | 860 | if (plen <= PAGE_SIZE) |
861 | goto error; | ||
862 | vm = true; | ||
863 | payload = vmalloc(plen); | ||
864 | if (!payload) | ||
865 | goto error; | ||
866 | } | ||
848 | 867 | ||
849 | ret = -EFAULT; | 868 | ret = -EFAULT; |
850 | if (copy_from_user(payload, _payload, plen) != 0) | 869 | if (copy_from_user(payload, _payload, plen) != 0) |
@@ -877,7 +896,10 @@ long keyctl_instantiate_key(key_serial_t id, | |||
877 | } | 896 | } |
878 | 897 | ||
879 | error2: | 898 | error2: |
880 | kfree(payload); | 899 | if (!vm) |
900 | kfree(payload); | ||
901 | else | ||
902 | vfree(payload); | ||
881 | error: | 903 | error: |
882 | return ret; | 904 | return ret; |
883 | 905 | ||