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