KEYS: Fix UID check in keyctl_get_persistent()
[deliverable/linux.git] / security / keys / big_key.c
CommitLineData
ab3c3587
DH
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
21MODULE_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 */
34struct key_type key_type_big_key = {
35 .name = "big_key",
36 .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
37 .instantiate = big_key_instantiate,
38 .match = user_match,
39 .revoke = big_key_revoke,
40 .destroy = big_key_destroy,
41 .describe = big_key_describe,
42 .read = big_key_read,
43};
44
45/*
46 * Instantiate a big key
47 */
48int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
49{
50 struct path *path = (struct path *)&key->payload.data2;
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 ret = key_payload_reserve(key, 16);
62 if (ret < 0)
63 goto error;
64
65 key->type_data.x[1] = 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_file_setup("", datalen, 0);
d2b86970
WY
74 if (IS_ERR(file)) {
75 ret = PTR_ERR(file);
ab3c3587 76 goto err_quota;
d2b86970 77 }
ab3c3587
DH
78
79 written = kernel_write(file, prep->data, prep->datalen, 0);
80 if (written != datalen) {
81 if (written >= 0)
82 ret = -ENOMEM;
83 goto err_fput;
84 }
85
86 /* Pin the mount and dentry to the key so that we can open it again
87 * later
88 */
89 *path = file->f_path;
90 path_get(path);
91 fput(file);
92 } else {
93 /* Just store the data in a buffer */
94 void *data = kmalloc(datalen, GFP_KERNEL);
95 if (!data) {
96 ret = -ENOMEM;
97 goto err_quota;
98 }
99
100 key->payload.data = memcpy(data, prep->data, prep->datalen);
101 }
102 return 0;
103
104err_fput:
105 fput(file);
106err_quota:
107 key_payload_reserve(key, 0);
108error:
109 return ret;
110}
111
112/*
113 * dispose of the links from a revoked keyring
114 * - called with the key sem write-locked
115 */
116void big_key_revoke(struct key *key)
117{
118 struct path *path = (struct path *)&key->payload.data2;
119
120 /* clear the quota */
121 key_payload_reserve(key, 0);
122 if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD)
123 vfs_truncate(path, 0);
124}
125
126/*
127 * dispose of the data dangling from the corpse of a big_key key
128 */
129void big_key_destroy(struct key *key)
130{
131 if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) {
132 struct path *path = (struct path *)&key->payload.data2;
133 path_put(path);
134 path->mnt = NULL;
135 path->dentry = NULL;
136 } else {
137 kfree(key->payload.data);
138 key->payload.data = NULL;
139 }
140}
141
142/*
143 * describe the big_key key
144 */
145void big_key_describe(const struct key *key, struct seq_file *m)
146{
147 unsigned long datalen = key->type_data.x[1];
148
149 seq_puts(m, key->description);
150
151 if (key_is_instantiated(key))
152 seq_printf(m, ": %lu [%s]",
153 datalen,
154 datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
155}
156
157/*
158 * read the key data
159 * - the key's semaphore is read-locked
160 */
161long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
162{
163 unsigned long datalen = key->type_data.x[1];
164 long ret;
165
166 if (!buffer || buflen < datalen)
167 return datalen;
168
169 if (datalen > BIG_KEY_FILE_THRESHOLD) {
170 struct path *path = (struct path *)&key->payload.data2;
171 struct file *file;
172 loff_t pos;
173
174 file = dentry_open(path, O_RDONLY, current_cred());
175 if (IS_ERR(file))
176 return PTR_ERR(file);
177
178 pos = 0;
179 ret = vfs_read(file, buffer, datalen, &pos);
180 fput(file);
181 if (ret >= 0 && ret != datalen)
182 ret = -EIO;
183 } else {
184 ret = datalen;
185 if (copy_to_user(buffer, key->payload.data, datalen) != 0)
186 ret = -EFAULT;
187 }
188
189 return ret;
190}
191
192/*
193 * Module stuff
194 */
195static int __init big_key_init(void)
196{
197 return register_key_type(&key_type_big_key);
198}
199
200static void __exit big_key_cleanup(void)
201{
202 unregister_key_type(&key_type_big_key);
203}
204
205module_init(big_key_init);
206module_exit(big_key_cleanup);
This page took 0.033298 seconds and 5 git commands to generate.