1 /* Large capacity key type 2 * 3 * Copyright (C) 2013 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 Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/init.h> 14 #include <linux/seq_file.h> 15 #include <linux/file.h> 16 #include <linux/shmem_fs.h> 17 #include <linux/err.h> 18 #include <keys/user-type.h> 19 #include <keys/big_key-type.h> 20 21 MODULE_LICENSE("GPL"); 22 23 /* 24 * If the data is under this limit, there's no point creating a shm file to 25 * hold it as the permanently resident metadata for the shmem fs will be at 26 * least as large as the data. 27 */ 28 #define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry)) 29 30 /* 31 * big_key defined keys take an arbitrary string as the description and an 32 * arbitrary blob of data as the payload 33 */ 34 struct key_type key_type_big_key = { 35 .name = "big_key", 36 .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, 37 .preparse = big_key_preparse, 38 .free_preparse = big_key_free_preparse, 39 .instantiate = generic_key_instantiate, 40 .match = user_match, 41 .revoke = big_key_revoke, 42 .destroy = big_key_destroy, 43 .describe = big_key_describe, 44 .read = big_key_read, 45 }; 46 47 /* 48 * Preparse a big key 49 */ 50 int big_key_preparse(struct key_preparsed_payload *prep) 51 { 52 struct path *path = (struct path *)&prep->payload; 53 struct file *file; 54 ssize_t written; 55 size_t datalen = prep->datalen; 56 int ret; 57 58 ret = -EINVAL; 59 if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data) 60 goto error; 61 62 /* Set an arbitrary quota */ 63 prep->quotalen = 16; 64 65 prep->type_data[1] = (void *)(unsigned long)datalen; 66 67 if (datalen > BIG_KEY_FILE_THRESHOLD) { 68 /* Create a shmem file to store the data in. This will permit the data 69 * to be swapped out if needed. 70 * 71 * TODO: Encrypt the stored data with a temporary key. 72 */ 73 file = shmem_kernel_file_setup("", datalen, 0); 74 if (IS_ERR(file)) { 75 ret = PTR_ERR(file); 76 goto error; 77 } 78 79 written = kernel_write(file, prep->data, prep->datalen, 0); 80 if (written != datalen) { 81 ret = written; 82 if (written >= 0) 83 ret = -ENOMEM; 84 goto err_fput; 85 } 86 87 /* Pin the mount and dentry to the key so that we can open it again 88 * later 89 */ 90 *path = file->f_path; 91 path_get(path); 92 fput(file); 93 } else { 94 /* Just store the data in a buffer */ 95 void *data = kmalloc(datalen, GFP_KERNEL); 96 if (!data) 97 return -ENOMEM; 98 99 prep->payload[0] = memcpy(data, prep->data, prep->datalen); 100 } 101 return 0; 102 103 err_fput: 104 fput(file); 105 error: 106 return ret; 107 } 108 109 /* 110 * Clear preparsement. 111 */ 112 void big_key_free_preparse(struct key_preparsed_payload *prep) 113 { 114 if (prep->datalen > BIG_KEY_FILE_THRESHOLD) { 115 struct path *path = (struct path *)&prep->payload; 116 path_put(path); 117 } else { 118 kfree(prep->payload[0]); 119 } 120 } 121 122 /* 123 * dispose of the links from a revoked keyring 124 * - called with the key sem write-locked 125 */ 126 void big_key_revoke(struct key *key) 127 { 128 struct path *path = (struct path *)&key->payload.data2; 129 130 /* clear the quota */ 131 key_payload_reserve(key, 0); 132 if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) 133 vfs_truncate(path, 0); 134 } 135 136 /* 137 * dispose of the data dangling from the corpse of a big_key key 138 */ 139 void big_key_destroy(struct key *key) 140 { 141 if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) { 142 struct path *path = (struct path *)&key->payload.data2; 143 path_put(path); 144 path->mnt = NULL; 145 path->dentry = NULL; 146 } else { 147 kfree(key->payload.data); 148 key->payload.data = NULL; 149 } 150 } 151 152 /* 153 * describe the big_key key 154 */ 155 void big_key_describe(const struct key *key, struct seq_file *m) 156 { 157 unsigned long datalen = key->type_data.x[1]; 158 159 seq_puts(m, key->description); 160 161 if (key_is_instantiated(key)) 162 seq_printf(m, ": %lu [%s]", 163 datalen, 164 datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); 165 } 166 167 /* 168 * read the key data 169 * - the key's semaphore is read-locked 170 */ 171 long big_key_read(const struct key *key, char __user *buffer, size_t buflen) 172 { 173 unsigned long datalen = key->type_data.x[1]; 174 long ret; 175 176 if (!buffer || buflen < datalen) 177 return datalen; 178 179 if (datalen > BIG_KEY_FILE_THRESHOLD) { 180 struct path *path = (struct path *)&key->payload.data2; 181 struct file *file; 182 loff_t pos; 183 184 file = dentry_open(path, O_RDONLY, current_cred()); 185 if (IS_ERR(file)) 186 return PTR_ERR(file); 187 188 pos = 0; 189 ret = vfs_read(file, buffer, datalen, &pos); 190 fput(file); 191 if (ret >= 0 && ret != datalen) 192 ret = -EIO; 193 } else { 194 ret = datalen; 195 if (copy_to_user(buffer, key->payload.data, datalen) != 0) 196 ret = -EFAULT; 197 } 198 199 return ret; 200 } 201 202 /* 203 * Module stuff 204 */ 205 static int __init big_key_init(void) 206 { 207 return register_key_type(&key_type_big_key); 208 } 209 210 static void __exit big_key_cleanup(void) 211 { 212 unregister_key_type(&key_type_big_key); 213 } 214 215 module_init(big_key_init); 216 module_exit(big_key_cleanup); 217