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