user_defined.c (4734B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* user_defined.c: user defined key type 3 * 4 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8#include <linux/export.h> 9#include <linux/init.h> 10#include <linux/slab.h> 11#include <linux/seq_file.h> 12#include <linux/err.h> 13#include <keys/user-type.h> 14#include <linux/uaccess.h> 15#include "internal.h" 16 17static int logon_vet_description(const char *desc); 18 19/* 20 * user defined keys take an arbitrary string as the description and an 21 * arbitrary blob of data as the payload 22 */ 23struct key_type key_type_user = { 24 .name = "user", 25 .preparse = user_preparse, 26 .free_preparse = user_free_preparse, 27 .instantiate = generic_key_instantiate, 28 .update = user_update, 29 .revoke = user_revoke, 30 .destroy = user_destroy, 31 .describe = user_describe, 32 .read = user_read, 33}; 34 35EXPORT_SYMBOL_GPL(key_type_user); 36 37/* 38 * This key type is essentially the same as key_type_user, but it does 39 * not define a .read op. This is suitable for storing username and 40 * password pairs in the keyring that you do not want to be readable 41 * from userspace. 42 */ 43struct key_type key_type_logon = { 44 .name = "logon", 45 .preparse = user_preparse, 46 .free_preparse = user_free_preparse, 47 .instantiate = generic_key_instantiate, 48 .update = user_update, 49 .revoke = user_revoke, 50 .destroy = user_destroy, 51 .describe = user_describe, 52 .vet_description = logon_vet_description, 53}; 54EXPORT_SYMBOL_GPL(key_type_logon); 55 56/* 57 * Preparse a user defined key payload 58 */ 59int user_preparse(struct key_preparsed_payload *prep) 60{ 61 struct user_key_payload *upayload; 62 size_t datalen = prep->datalen; 63 64 if (datalen <= 0 || datalen > 32767 || !prep->data) 65 return -EINVAL; 66 67 upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL); 68 if (!upayload) 69 return -ENOMEM; 70 71 /* attach the data */ 72 prep->quotalen = datalen; 73 prep->payload.data[0] = upayload; 74 upayload->datalen = datalen; 75 memcpy(upayload->data, prep->data, datalen); 76 return 0; 77} 78EXPORT_SYMBOL_GPL(user_preparse); 79 80/* 81 * Free a preparse of a user defined key payload 82 */ 83void user_free_preparse(struct key_preparsed_payload *prep) 84{ 85 kfree_sensitive(prep->payload.data[0]); 86} 87EXPORT_SYMBOL_GPL(user_free_preparse); 88 89static void user_free_payload_rcu(struct rcu_head *head) 90{ 91 struct user_key_payload *payload; 92 93 payload = container_of(head, struct user_key_payload, rcu); 94 kfree_sensitive(payload); 95} 96 97/* 98 * update a user defined key 99 * - the key's semaphore is write-locked 100 */ 101int user_update(struct key *key, struct key_preparsed_payload *prep) 102{ 103 struct user_key_payload *zap = NULL; 104 int ret; 105 106 /* check the quota and attach the new data */ 107 ret = key_payload_reserve(key, prep->datalen); 108 if (ret < 0) 109 return ret; 110 111 /* attach the new data, displacing the old */ 112 key->expiry = prep->expiry; 113 if (key_is_positive(key)) 114 zap = dereference_key_locked(key); 115 rcu_assign_keypointer(key, prep->payload.data[0]); 116 prep->payload.data[0] = NULL; 117 118 if (zap) 119 call_rcu(&zap->rcu, user_free_payload_rcu); 120 return ret; 121} 122EXPORT_SYMBOL_GPL(user_update); 123 124/* 125 * dispose of the links from a revoked keyring 126 * - called with the key sem write-locked 127 */ 128void user_revoke(struct key *key) 129{ 130 struct user_key_payload *upayload = user_key_payload_locked(key); 131 132 /* clear the quota */ 133 key_payload_reserve(key, 0); 134 135 if (upayload) { 136 rcu_assign_keypointer(key, NULL); 137 call_rcu(&upayload->rcu, user_free_payload_rcu); 138 } 139} 140 141EXPORT_SYMBOL(user_revoke); 142 143/* 144 * dispose of the data dangling from the corpse of a user key 145 */ 146void user_destroy(struct key *key) 147{ 148 struct user_key_payload *upayload = key->payload.data[0]; 149 150 kfree_sensitive(upayload); 151} 152 153EXPORT_SYMBOL_GPL(user_destroy); 154 155/* 156 * describe the user key 157 */ 158void user_describe(const struct key *key, struct seq_file *m) 159{ 160 seq_puts(m, key->description); 161 if (key_is_positive(key)) 162 seq_printf(m, ": %u", key->datalen); 163} 164 165EXPORT_SYMBOL_GPL(user_describe); 166 167/* 168 * read the key data 169 * - the key's semaphore is read-locked 170 */ 171long user_read(const struct key *key, char *buffer, size_t buflen) 172{ 173 const struct user_key_payload *upayload; 174 long ret; 175 176 upayload = user_key_payload_locked(key); 177 ret = upayload->datalen; 178 179 /* we can return the data as is */ 180 if (buffer && buflen > 0) { 181 if (buflen > upayload->datalen) 182 buflen = upayload->datalen; 183 184 memcpy(buffer, upayload->data, buflen); 185 } 186 187 return ret; 188} 189 190EXPORT_SYMBOL_GPL(user_read); 191 192/* Vet the description for a "logon" key */ 193static int logon_vet_description(const char *desc) 194{ 195 char *p; 196 197 /* require a "qualified" description string */ 198 p = strchr(desc, ':'); 199 if (!p) 200 return -EINVAL; 201 202 /* also reject description with ':' as first char */ 203 if (p == desc) 204 return -EINVAL; 205 206 return 0; 207}