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 17 static 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 */ 23 struct 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 35 EXPORT_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 */ 43 struct 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 }; 54 EXPORT_SYMBOL_GPL(key_type_logon); 55 56 /* 57 * Preparse a user defined key payload 58 */ 59 int 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 } 78 EXPORT_SYMBOL_GPL(user_preparse); 79 80 /* 81 * Free a preparse of a user defined key payload 82 */ 83 void user_free_preparse(struct key_preparsed_payload *prep) 84 { 85 kfree_sensitive(prep->payload.data[0]); 86 } 87 EXPORT_SYMBOL_GPL(user_free_preparse); 88 89 static 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 */ 101 int 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 } 122 EXPORT_SYMBOL_GPL(user_update); 123 124 /* 125 * dispose of the links from a revoked keyring 126 * - called with the key sem write-locked 127 */ 128 void 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 141 EXPORT_SYMBOL(user_revoke); 142 143 /* 144 * dispose of the data dangling from the corpse of a user key 145 */ 146 void user_destroy(struct key *key) 147 { 148 struct user_key_payload *upayload = key->payload.data[0]; 149 150 kfree_sensitive(upayload); 151 } 152 153 EXPORT_SYMBOL_GPL(user_destroy); 154 155 /* 156 * describe the user key 157 */ 158 void 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 165 EXPORT_SYMBOL_GPL(user_describe); 166 167 /* 168 * read the key data 169 * - the key's semaphore is read-locked 170 */ 171 long 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 190 EXPORT_SYMBOL_GPL(user_read); 191 192 /* Vet the description for a "logon" key */ 193 static 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 } 208
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.