Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* Request key authorisation token key definition. 3 : : * 4 : : * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. 5 : : * Written by David Howells (dhowells@redhat.com) 6 : : * 7 : : * See Documentation/security/keys/request-key.rst 8 : : */ 9 : : 10 : : #include <linux/sched.h> 11 : : #include <linux/err.h> 12 : : #include <linux/seq_file.h> 13 : : #include <linux/slab.h> 14 : : #include <linux/uaccess.h> 15 : : #include "internal.h" 16 : : #include <keys/request_key_auth-type.h> 17 : : 18 : : static int request_key_auth_preparse(struct key_preparsed_payload *); 19 : : static void request_key_auth_free_preparse(struct key_preparsed_payload *); 20 : : static int request_key_auth_instantiate(struct key *, 21 : : struct key_preparsed_payload *); 22 : : static void request_key_auth_describe(const struct key *, struct seq_file *); 23 : : static void request_key_auth_revoke(struct key *); 24 : : static void request_key_auth_destroy(struct key *); 25 : : static long request_key_auth_read(const struct key *, char *, size_t); 26 : : 27 : : /* 28 : : * The request-key authorisation key type definition. 29 : : */ 30 : : struct key_type key_type_request_key_auth = { 31 : : .name = ".request_key_auth", 32 : : .def_datalen = sizeof(struct request_key_auth), 33 : : .preparse = request_key_auth_preparse, 34 : : .free_preparse = request_key_auth_free_preparse, 35 : : .instantiate = request_key_auth_instantiate, 36 : : .describe = request_key_auth_describe, 37 : : .revoke = request_key_auth_revoke, 38 : : .destroy = request_key_auth_destroy, 39 : : .read = request_key_auth_read, 40 : : }; 41 : : 42 : 0 : static int request_key_auth_preparse(struct key_preparsed_payload *prep) 43 : : { 44 : 0 : return 0; 45 : : } 46 : : 47 : 0 : static void request_key_auth_free_preparse(struct key_preparsed_payload *prep) 48 : : { 49 : 0 : } 50 : : 51 : : /* 52 : : * Instantiate a request-key authorisation key. 53 : : */ 54 : 0 : static int request_key_auth_instantiate(struct key *key, 55 : : struct key_preparsed_payload *prep) 56 : : { 57 : 0 : rcu_assign_keypointer(key, (struct request_key_auth *)prep->data); 58 : 0 : return 0; 59 : : } 60 : : 61 : : /* 62 : : * Describe an authorisation token. 63 : : */ 64 : 0 : static void request_key_auth_describe(const struct key *key, 65 : : struct seq_file *m) 66 : : { 67 : 0 : struct request_key_auth *rka = dereference_key_rcu(key); 68 : : 69 : 0 : if (!rka) 70 : 0 : return; 71 : : 72 : 0 : seq_puts(m, "key:"); 73 : 0 : seq_puts(m, key->description); 74 : 0 : if (key_is_positive(key)) 75 : 0 : seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); 76 : : } 77 : : 78 : : /* 79 : : * Read the callout_info data (retrieves the callout information). 80 : : * - the key's semaphore is read-locked 81 : : */ 82 : 0 : static long request_key_auth_read(const struct key *key, 83 : : char *buffer, size_t buflen) 84 : : { 85 : 0 : struct request_key_auth *rka = dereference_key_locked(key); 86 : : size_t datalen; 87 : : long ret; 88 : : 89 : 0 : if (!rka) 90 : : return -EKEYREVOKED; 91 : : 92 : 0 : datalen = rka->callout_len; 93 : 0 : ret = datalen; 94 : : 95 : : /* we can return the data as is */ 96 : 0 : if (buffer && buflen > 0) { 97 : 0 : if (buflen > datalen) 98 : : buflen = datalen; 99 : : 100 : 0 : memcpy(buffer, rka->callout_info, buflen); 101 : : } 102 : : 103 : 0 : return ret; 104 : : } 105 : : 106 : 0 : static void free_request_key_auth(struct request_key_auth *rka) 107 : : { 108 : 0 : if (!rka) 109 : 0 : return; 110 : 0 : key_put(rka->target_key); 111 : 0 : key_put(rka->dest_keyring); 112 : 0 : if (rka->cred) 113 : 0 : put_cred(rka->cred); 114 : 0 : kfree(rka->callout_info); 115 : 0 : kfree(rka); 116 : : } 117 : : 118 : : /* 119 : : * Dispose of the request_key_auth record under RCU conditions 120 : : */ 121 : 0 : static void request_key_auth_rcu_disposal(struct rcu_head *rcu) 122 : : { 123 : : struct request_key_auth *rka = 124 : : container_of(rcu, struct request_key_auth, rcu); 125 : : 126 : 0 : free_request_key_auth(rka); 127 : 0 : } 128 : : 129 : : /* 130 : : * Handle revocation of an authorisation token key. 131 : : * 132 : : * Called with the key sem write-locked. 133 : : */ 134 : 0 : static void request_key_auth_revoke(struct key *key) 135 : : { 136 : 0 : struct request_key_auth *rka = dereference_key_locked(key); 137 : : 138 : : kenter("{%d}", key->serial); 139 : : rcu_assign_keypointer(key, NULL); 140 : 0 : call_rcu(&rka->rcu, request_key_auth_rcu_disposal); 141 : 0 : } 142 : : 143 : : /* 144 : : * Destroy an instantiation authorisation token key. 145 : : */ 146 : 0 : static void request_key_auth_destroy(struct key *key) 147 : : { 148 : : struct request_key_auth *rka = rcu_access_pointer(key->payload.rcu_data0); 149 : : 150 : : kenter("{%d}", key->serial); 151 : 0 : if (rka) { 152 : : rcu_assign_keypointer(key, NULL); 153 : 0 : call_rcu(&rka->rcu, request_key_auth_rcu_disposal); 154 : : } 155 : 0 : } 156 : : 157 : : /* 158 : : * Create an authorisation token for /sbin/request-key or whoever to gain 159 : : * access to the caller's security data. 160 : : */ 161 : 0 : struct key *request_key_auth_new(struct key *target, const char *op, 162 : : const void *callout_info, size_t callout_len, 163 : : struct key *dest_keyring) 164 : : { 165 : : struct request_key_auth *rka, *irka; 166 : 0 : const struct cred *cred = current_cred(); 167 : : struct key *authkey = NULL; 168 : : char desc[20]; 169 : : int ret = -ENOMEM; 170 : : 171 : : kenter("%d,", target->serial); 172 : : 173 : : /* allocate a auth record */ 174 : 0 : rka = kzalloc(sizeof(*rka), GFP_KERNEL); 175 : 0 : if (!rka) 176 : : goto error; 177 : 0 : rka->callout_info = kmemdup(callout_info, callout_len, GFP_KERNEL); 178 : 0 : if (!rka->callout_info) 179 : : goto error_free_rka; 180 : 0 : rka->callout_len = callout_len; 181 : 0 : strlcpy(rka->op, op, sizeof(rka->op)); 182 : : 183 : : /* see if the calling process is already servicing the key request of 184 : : * another process */ 185 : 0 : if (cred->request_key_auth) { 186 : : /* it is - use that instantiation context here too */ 187 : 0 : down_read(&cred->request_key_auth->sem); 188 : : 189 : : /* if the auth key has been revoked, then the key we're 190 : : * servicing is already instantiated */ 191 : 0 : if (test_bit(KEY_FLAG_REVOKED, 192 : 0 : &cred->request_key_auth->flags)) { 193 : 0 : up_read(&cred->request_key_auth->sem); 194 : : ret = -EKEYREVOKED; 195 : 0 : goto error_free_rka; 196 : : } 197 : : 198 : 0 : irka = cred->request_key_auth->payload.data[0]; 199 : 0 : rka->cred = get_cred(irka->cred); 200 : 0 : rka->pid = irka->pid; 201 : : 202 : 0 : up_read(&cred->request_key_auth->sem); 203 : : } 204 : : else { 205 : : /* it isn't - use this process as the context */ 206 : 0 : rka->cred = get_cred(cred); 207 : 0 : rka->pid = current->pid; 208 : : } 209 : : 210 : 0 : rka->target_key = key_get(target); 211 : 0 : rka->dest_keyring = key_get(dest_keyring); 212 : : 213 : : /* allocate the auth key */ 214 : 0 : sprintf(desc, "%x", target->serial); 215 : : 216 : 0 : authkey = key_alloc(&key_type_request_key_auth, desc, 217 : : cred->fsuid, cred->fsgid, cred, 218 : : KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | KEY_POS_LINK | 219 : : KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA, NULL); 220 : 0 : if (IS_ERR(authkey)) { 221 : : ret = PTR_ERR(authkey); 222 : 0 : goto error_free_rka; 223 : : } 224 : : 225 : : /* construct the auth key */ 226 : 0 : ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); 227 : 0 : if (ret < 0) 228 : : goto error_put_authkey; 229 : : 230 : : kleave(" = {%d,%d}", authkey->serial, refcount_read(&authkey->usage)); 231 : : return authkey; 232 : : 233 : : error_put_authkey: 234 : 0 : key_put(authkey); 235 : : error_free_rka: 236 : 0 : free_request_key_auth(rka); 237 : : error: 238 : : kleave("= %d", ret); 239 : 0 : return ERR_PTR(ret); 240 : : } 241 : : 242 : : /* 243 : : * Search the current process's keyrings for the authorisation key for 244 : : * instantiation of a key. 245 : : */ 246 : 0 : struct key *key_get_instantiation_authkey(key_serial_t target_id) 247 : : { 248 : : char description[16]; 249 : 0 : struct keyring_search_context ctx = { 250 : : .index_key.type = &key_type_request_key_auth, 251 : : .index_key.description = description, 252 : 0 : .cred = current_cred(), 253 : : .match_data.cmp = key_default_cmp, 254 : : .match_data.raw_data = description, 255 : : .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, 256 : : .flags = (KEYRING_SEARCH_DO_STATE_CHECK | 257 : : KEYRING_SEARCH_RECURSE), 258 : : }; 259 : : struct key *authkey; 260 : : key_ref_t authkey_ref; 261 : : 262 : 0 : ctx.index_key.desc_len = sprintf(description, "%x", target_id); 263 : : 264 : : rcu_read_lock(); 265 : 0 : authkey_ref = search_process_keyrings_rcu(&ctx); 266 : : rcu_read_unlock(); 267 : : 268 : 0 : if (IS_ERR(authkey_ref)) { 269 : : authkey = ERR_CAST(authkey_ref); 270 : 0 : if (authkey == ERR_PTR(-EAGAIN)) 271 : : authkey = ERR_PTR(-ENOKEY); 272 : : goto error; 273 : : } 274 : : 275 : : authkey = key_ref_to_ptr(authkey_ref); 276 : 0 : if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) { 277 : 0 : key_put(authkey); 278 : : authkey = ERR_PTR(-EKEYREVOKED); 279 : : } 280 : : 281 : : error: 282 : 0 : return authkey; 283 : : }