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