aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c126
1 files changed, 112 insertions, 14 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d9ca15c109cc..acc9c89e40a8 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -19,6 +19,8 @@
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>
23#include <linux/security.h>
22#include <asm/uaccess.h> 24#include <asm/uaccess.h>
23#include "internal.h" 25#include "internal.h"
24 26
@@ -62,9 +64,10 @@ asmlinkage long sys_add_key(const char __user *_type,
62 char type[32], *description; 64 char type[32], *description;
63 void *payload; 65 void *payload;
64 long ret; 66 long ret;
67 bool vm;
65 68
66 ret = -EINVAL; 69 ret = -EINVAL;
67 if (plen > 32767) 70 if (plen > 1024 * 1024 - 1)
68 goto error; 71 goto error;
69 72
70 /* draw all the data into kernel space */ 73 /* draw all the data into kernel space */
@@ -81,11 +84,18 @@ asmlinkage long sys_add_key(const char __user *_type,
81 /* pull the payload in if one was supplied */ 84 /* pull the payload in if one was supplied */
82 payload = NULL; 85 payload = NULL;
83 86
87 vm = false;
84 if (_payload) { 88 if (_payload) {
85 ret = -ENOMEM; 89 ret = -ENOMEM;
86 payload = kmalloc(plen, GFP_KERNEL); 90 payload = kmalloc(plen, GFP_KERNEL);
87 if (!payload) 91 if (!payload) {
88 goto error2; 92 if (plen <= PAGE_SIZE)
93 goto error2;
94 vm = true;
95 payload = vmalloc(plen);
96 if (!payload)
97 goto error2;
98 }
89 99
90 ret = -EFAULT; 100 ret = -EFAULT;
91 if (copy_from_user(payload, _payload, plen) != 0) 101 if (copy_from_user(payload, _payload, plen) != 0)
@@ -102,7 +112,8 @@ asmlinkage long sys_add_key(const char __user *_type,
102 /* create or update the requested key and add it to the target 112 /* create or update the requested key and add it to the target
103 * keyring */ 113 * keyring */
104 key_ref = key_create_or_update(keyring_ref, type, description, 114 key_ref = key_create_or_update(keyring_ref, type, description,
105 payload, plen, KEY_ALLOC_IN_QUOTA); 115 payload, plen, KEY_PERM_UNDEF,
116 KEY_ALLOC_IN_QUOTA);
106 if (!IS_ERR(key_ref)) { 117 if (!IS_ERR(key_ref)) {
107 ret = key_ref_to_ptr(key_ref)->serial; 118 ret = key_ref_to_ptr(key_ref)->serial;
108 key_ref_put(key_ref); 119 key_ref_put(key_ref);
@@ -113,7 +124,10 @@ asmlinkage long sys_add_key(const char __user *_type,
113 124
114 key_ref_put(keyring_ref); 125 key_ref_put(keyring_ref);
115 error3: 126 error3:
116 kfree(payload); 127 if (!vm)
128 kfree(payload);
129 else
130 vfree(payload);
117 error2: 131 error2:
118 kfree(description); 132 kfree(description);
119 error: 133 error:
@@ -140,6 +154,7 @@ asmlinkage long sys_request_key(const char __user *_type,
140 struct key_type *ktype; 154 struct key_type *ktype;
141 struct key *key; 155 struct key *key;
142 key_ref_t dest_ref; 156 key_ref_t dest_ref;
157 size_t callout_len;
143 char type[32], *description, *callout_info; 158 char type[32], *description, *callout_info;
144 long ret; 159 long ret;
145 160
@@ -157,12 +172,14 @@ asmlinkage long sys_request_key(const char __user *_type,
157 172
158 /* pull the callout info into kernel space */ 173 /* pull the callout info into kernel space */
159 callout_info = NULL; 174 callout_info = NULL;
175 callout_len = 0;
160 if (_callout_info) { 176 if (_callout_info) {
161 callout_info = strndup_user(_callout_info, PAGE_SIZE); 177 callout_info = strndup_user(_callout_info, PAGE_SIZE);
162 if (IS_ERR(callout_info)) { 178 if (IS_ERR(callout_info)) {
163 ret = PTR_ERR(callout_info); 179 ret = PTR_ERR(callout_info);
164 goto error2; 180 goto error2;
165 } 181 }
182 callout_len = strlen(callout_info);
166 } 183 }
167 184
168 /* get the destination keyring if specified */ 185 /* get the destination keyring if specified */
@@ -183,8 +200,8 @@ asmlinkage long sys_request_key(const char __user *_type,
183 } 200 }
184 201
185 /* do the search */ 202 /* do the search */
186 key = request_key_and_link(ktype, description, callout_info, NULL, 203 key = request_key_and_link(ktype, description, callout_info,
187 key_ref_to_ptr(dest_ref), 204 callout_len, NULL, key_ref_to_ptr(dest_ref),
188 KEY_ALLOC_IN_QUOTA); 205 KEY_ALLOC_IN_QUOTA);
189 if (IS_ERR(key)) { 206 if (IS_ERR(key)) {
190 ret = PTR_ERR(key); 207 ret = PTR_ERR(key);
@@ -714,10 +731,16 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
714 731
715 /* transfer the quota burden to the new user */ 732 /* transfer the quota burden to the new user */
716 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { 733 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
734 unsigned maxkeys = (uid == 0) ?
735 key_quota_root_maxkeys : key_quota_maxkeys;
736 unsigned maxbytes = (uid == 0) ?
737 key_quota_root_maxbytes : key_quota_maxbytes;
738
717 spin_lock(&newowner->lock); 739 spin_lock(&newowner->lock);
718 if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || 740 if (newowner->qnkeys + 1 >= maxkeys ||
719 newowner->qnbytes + key->quotalen >= 741 newowner->qnbytes + key->quotalen >= maxbytes ||
720 KEYQUOTA_MAX_BYTES) 742 newowner->qnbytes + key->quotalen <
743 newowner->qnbytes)
721 goto quota_overrun; 744 goto quota_overrun;
722 745
723 newowner->qnkeys++; 746 newowner->qnkeys++;
@@ -821,9 +844,10 @@ long keyctl_instantiate_key(key_serial_t id,
821 key_ref_t keyring_ref; 844 key_ref_t keyring_ref;
822 void *payload; 845 void *payload;
823 long ret; 846 long ret;
847 bool vm = false;
824 848
825 ret = -EINVAL; 849 ret = -EINVAL;
826 if (plen > 32767) 850 if (plen > 1024 * 1024 - 1)
827 goto error; 851 goto error;
828 852
829 /* the appropriate instantiation authorisation key must have been 853 /* the appropriate instantiation authorisation key must have been
@@ -843,8 +867,14 @@ long keyctl_instantiate_key(key_serial_t id,
843 if (_payload) { 867 if (_payload) {
844 ret = -ENOMEM; 868 ret = -ENOMEM;
845 payload = kmalloc(plen, GFP_KERNEL); 869 payload = kmalloc(plen, GFP_KERNEL);
846 if (!payload) 870 if (!payload) {
847 goto error; 871 if (plen <= PAGE_SIZE)
872 goto error;
873 vm = true;
874 payload = vmalloc(plen);
875 if (!payload)
876 goto error;
877 }
848 878
849 ret = -EFAULT; 879 ret = -EFAULT;
850 if (copy_from_user(payload, _payload, plen) != 0) 880 if (copy_from_user(payload, _payload, plen) != 0)
@@ -877,7 +907,10 @@ long keyctl_instantiate_key(key_serial_t id,
877 } 907 }
878 908
879error2: 909error2:
880 kfree(payload); 910 if (!vm)
911 kfree(payload);
912 else
913 vfree(payload);
881error: 914error:
882 return ret; 915 return ret;
883 916
@@ -1055,6 +1088,66 @@ error:
1055 1088
1056} /* end keyctl_assume_authority() */ 1089} /* end keyctl_assume_authority() */
1057 1090
1091/*
1092 * get the security label of a key
1093 * - the key must grant us view permission
1094 * - if there's a buffer, we place up to buflen bytes of data into it
1095 * - unless there's an error, we return the amount of information available,
1096 * irrespective of how much we may have copied (including the terminal NUL)
1097 * - implements keyctl(KEYCTL_GET_SECURITY)
1098 */
1099long keyctl_get_security(key_serial_t keyid,
1100 char __user *buffer,
1101 size_t buflen)
1102{
1103 struct key *key, *instkey;
1104 key_ref_t key_ref;
1105 char *context;
1106 long ret;
1107
1108 key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
1109 if (IS_ERR(key_ref)) {
1110 if (PTR_ERR(key_ref) != -EACCES)
1111 return PTR_ERR(key_ref);
1112
1113 /* viewing a key under construction is also permitted if we
1114 * have the authorisation token handy */
1115 instkey = key_get_instantiation_authkey(keyid);
1116 if (IS_ERR(instkey))
1117 return PTR_ERR(key_ref);
1118 key_put(instkey);
1119
1120 key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
1121 if (IS_ERR(key_ref))
1122 return PTR_ERR(key_ref);
1123 }
1124
1125 key = key_ref_to_ptr(key_ref);
1126 ret = security_key_getsecurity(key, &context);
1127 if (ret == 0) {
1128 /* if no information was returned, give userspace an empty
1129 * string */
1130 ret = 1;
1131 if (buffer && buflen > 0 &&
1132 copy_to_user(buffer, "", 1) != 0)
1133 ret = -EFAULT;
1134 } else if (ret > 0) {
1135 /* return as much data as there's room for */
1136 if (buffer && buflen > 0) {
1137 if (buflen > ret)
1138 buflen = ret;
1139
1140 if (copy_to_user(buffer, context, buflen) != 0)
1141 ret = -EFAULT;
1142 }
1143
1144 kfree(context);
1145 }
1146
1147 key_ref_put(key_ref);
1148 return ret;
1149}
1150
1058/*****************************************************************************/ 1151/*****************************************************************************/
1059/* 1152/*
1060 * the key control system call 1153 * the key control system call
@@ -1135,6 +1228,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
1135 case KEYCTL_ASSUME_AUTHORITY: 1228 case KEYCTL_ASSUME_AUTHORITY:
1136 return keyctl_assume_authority((key_serial_t) arg2); 1229 return keyctl_assume_authority((key_serial_t) arg2);
1137 1230
1231 case KEYCTL_GET_SECURITY:
1232 return keyctl_get_security((key_serial_t) arg2,
1233 (char *) arg3,
1234 (size_t) arg4);
1235
1138 default: 1236 default:
1139 return -EOPNOTSUPP; 1237 return -EOPNOTSUPP;
1140 } 1238 }