Branch data Line data Source code
1 : : /* procfs files for key database enumeration
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/sched.h>
15 : : #include <linux/fs.h>
16 : : #include <linux/proc_fs.h>
17 : : #include <linux/seq_file.h>
18 : : #include <asm/errno.h>
19 : : #include "internal.h"
20 : :
21 : : #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
22 : : static int proc_keys_open(struct inode *inode, struct file *file);
23 : : static void *proc_keys_start(struct seq_file *p, loff_t *_pos);
24 : : static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos);
25 : : static void proc_keys_stop(struct seq_file *p, void *v);
26 : : static int proc_keys_show(struct seq_file *m, void *v);
27 : :
28 : : static const struct seq_operations proc_keys_ops = {
29 : : .start = proc_keys_start,
30 : : .next = proc_keys_next,
31 : : .stop = proc_keys_stop,
32 : : .show = proc_keys_show,
33 : : };
34 : :
35 : : static const struct file_operations proc_keys_fops = {
36 : : .open = proc_keys_open,
37 : : .read = seq_read,
38 : : .llseek = seq_lseek,
39 : : .release = seq_release,
40 : : };
41 : : #endif
42 : :
43 : : static int proc_key_users_open(struct inode *inode, struct file *file);
44 : : static void *proc_key_users_start(struct seq_file *p, loff_t *_pos);
45 : : static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos);
46 : : static void proc_key_users_stop(struct seq_file *p, void *v);
47 : : static int proc_key_users_show(struct seq_file *m, void *v);
48 : :
49 : : static const struct seq_operations proc_key_users_ops = {
50 : : .start = proc_key_users_start,
51 : : .next = proc_key_users_next,
52 : : .stop = proc_key_users_stop,
53 : : .show = proc_key_users_show,
54 : : };
55 : :
56 : : static const struct file_operations proc_key_users_fops = {
57 : : .open = proc_key_users_open,
58 : : .read = seq_read,
59 : : .llseek = seq_lseek,
60 : : .release = seq_release,
61 : : };
62 : :
63 : : /*
64 : : * Declare the /proc files.
65 : : */
66 : 0 : static int __init key_proc_init(void)
67 : : {
68 : : struct proc_dir_entry *p;
69 : :
70 : : #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
71 : : p = proc_create("keys", 0, NULL, &proc_keys_fops);
72 : : if (!p)
73 : : panic("Cannot create /proc/keys\n");
74 : : #endif
75 : :
76 : : p = proc_create("key-users", 0, NULL, &proc_key_users_fops);
77 [ # # ]: 0 : if (!p)
78 : 0 : panic("Cannot create /proc/key-users\n");
79 : :
80 : 0 : return 0;
81 : : }
82 : :
83 : : __initcall(key_proc_init);
84 : :
85 : : /*
86 : : * Implement "/proc/keys" to provide a list of the keys on the system that
87 : : * grant View permission to the caller.
88 : : */
89 : : #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
90 : :
91 : : static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n)
92 : : {
93 : : struct user_namespace *user_ns = seq_user_ns(p);
94 : :
95 : : n = rb_next(n);
96 : : while (n) {
97 : : struct key *key = rb_entry(n, struct key, serial_node);
98 : : if (kuid_has_mapping(user_ns, key->user->uid))
99 : : break;
100 : : n = rb_next(n);
101 : : }
102 : : return n;
103 : : }
104 : :
105 : : static int proc_keys_open(struct inode *inode, struct file *file)
106 : : {
107 : : return seq_open(file, &proc_keys_ops);
108 : : }
109 : :
110 : : static struct key *find_ge_key(struct seq_file *p, key_serial_t id)
111 : : {
112 : : struct user_namespace *user_ns = seq_user_ns(p);
113 : : struct rb_node *n = key_serial_tree.rb_node;
114 : : struct key *minkey = NULL;
115 : :
116 : : while (n) {
117 : : struct key *key = rb_entry(n, struct key, serial_node);
118 : : if (id < key->serial) {
119 : : if (!minkey || minkey->serial > key->serial)
120 : : minkey = key;
121 : : n = n->rb_left;
122 : : } else if (id > key->serial) {
123 : : n = n->rb_right;
124 : : } else {
125 : : minkey = key;
126 : : break;
127 : : }
128 : : key = NULL;
129 : : }
130 : :
131 : : if (!minkey)
132 : : return NULL;
133 : :
134 : : for (;;) {
135 : : if (kuid_has_mapping(user_ns, minkey->user->uid))
136 : : return minkey;
137 : : n = rb_next(&minkey->serial_node);
138 : : if (!n)
139 : : return NULL;
140 : : minkey = rb_entry(n, struct key, serial_node);
141 : : }
142 : : }
143 : :
144 : : static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
145 : : __acquires(key_serial_lock)
146 : : {
147 : : key_serial_t pos = *_pos;
148 : : struct key *key;
149 : :
150 : : spin_lock(&key_serial_lock);
151 : :
152 : : if (*_pos > INT_MAX)
153 : : return NULL;
154 : : key = find_ge_key(p, pos);
155 : : if (!key)
156 : : return NULL;
157 : : *_pos = key->serial;
158 : : return &key->serial_node;
159 : : }
160 : :
161 : : static inline key_serial_t key_node_serial(struct rb_node *n)
162 : : {
163 : : struct key *key = rb_entry(n, struct key, serial_node);
164 : : return key->serial;
165 : : }
166 : :
167 : : static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
168 : : {
169 : : struct rb_node *n;
170 : :
171 : : n = key_serial_next(p, v);
172 : : if (n)
173 : : *_pos = key_node_serial(n);
174 : : return n;
175 : : }
176 : :
177 : : static void proc_keys_stop(struct seq_file *p, void *v)
178 : : __releases(key_serial_lock)
179 : : {
180 : : spin_unlock(&key_serial_lock);
181 : : }
182 : :
183 : : static int proc_keys_show(struct seq_file *m, void *v)
184 : : {
185 : : struct rb_node *_p = v;
186 : : struct key *key = rb_entry(_p, struct key, serial_node);
187 : : struct timespec now;
188 : : unsigned long timo;
189 : : key_ref_t key_ref, skey_ref;
190 : : char xbuf[12];
191 : : int rc;
192 : :
193 : : struct keyring_search_context ctx = {
194 : : .index_key.type = key->type,
195 : : .index_key.description = key->description,
196 : : .cred = current_cred(),
197 : : .match = lookup_user_key_possessed,
198 : : .match_data = key,
199 : : .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
200 : : KEYRING_SEARCH_LOOKUP_DIRECT),
201 : : };
202 : :
203 : : key_ref = make_key_ref(key, 0);
204 : :
205 : : /* determine if the key is possessed by this process (a test we can
206 : : * skip if the key does not indicate the possessor can view it
207 : : */
208 : : if (key->perm & KEY_POS_VIEW) {
209 : : skey_ref = search_my_process_keyrings(&ctx);
210 : : if (!IS_ERR(skey_ref)) {
211 : : key_ref_put(skey_ref);
212 : : key_ref = make_key_ref(key, 1);
213 : : }
214 : : }
215 : :
216 : : /* check whether the current task is allowed to view the key (assuming
217 : : * non-possession)
218 : : * - the caller holds a spinlock, and thus the RCU read lock, making our
219 : : * access to __current_cred() safe
220 : : */
221 : : rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW);
222 : : if (rc < 0)
223 : : return 0;
224 : :
225 : : now = current_kernel_time();
226 : :
227 : : rcu_read_lock();
228 : :
229 : : /* come up with a suitable timeout value */
230 : : if (key->expiry == 0) {
231 : : memcpy(xbuf, "perm", 5);
232 : : } else if (now.tv_sec >= key->expiry) {
233 : : memcpy(xbuf, "expd", 5);
234 : : } else {
235 : : timo = key->expiry - now.tv_sec;
236 : :
237 : : if (timo < 60)
238 : : sprintf(xbuf, "%lus", timo);
239 : : else if (timo < 60*60)
240 : : sprintf(xbuf, "%lum", timo / 60);
241 : : else if (timo < 60*60*24)
242 : : sprintf(xbuf, "%luh", timo / (60*60));
243 : : else if (timo < 60*60*24*7)
244 : : sprintf(xbuf, "%lud", timo / (60*60*24));
245 : : else
246 : : sprintf(xbuf, "%luw", timo / (60*60*24*7));
247 : : }
248 : :
249 : : #define showflag(KEY, LETTER, FLAG) \
250 : : (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
251 : :
252 : : seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
253 : : key->serial,
254 : : showflag(key, 'I', KEY_FLAG_INSTANTIATED),
255 : : showflag(key, 'R', KEY_FLAG_REVOKED),
256 : : showflag(key, 'D', KEY_FLAG_DEAD),
257 : : showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
258 : : showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
259 : : showflag(key, 'N', KEY_FLAG_NEGATIVE),
260 : : showflag(key, 'i', KEY_FLAG_INVALIDATED),
261 : : atomic_read(&key->usage),
262 : : xbuf,
263 : : key->perm,
264 : : from_kuid_munged(seq_user_ns(m), key->uid),
265 : : from_kgid_munged(seq_user_ns(m), key->gid),
266 : : key->type->name);
267 : :
268 : : #undef showflag
269 : :
270 : : if (key->type->describe)
271 : : key->type->describe(key, m);
272 : : seq_putc(m, '\n');
273 : :
274 : : rcu_read_unlock();
275 : : return 0;
276 : : }
277 : :
278 : : #endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
279 : :
280 : : static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n)
281 : : {
282 : : while (n) {
283 : : struct key_user *user = rb_entry(n, struct key_user, node);
284 : : if (kuid_has_mapping(user_ns, user->uid))
285 : : break;
286 : : n = rb_next(n);
287 : : }
288 : : return n;
289 : : }
290 : :
291 : : static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n)
292 : : {
293 : 2 : return __key_user_next(user_ns, rb_next(n));
294 : : }
295 : :
296 : : static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r)
297 : : {
298 : 2 : struct rb_node *n = rb_first(r);
299 : : return __key_user_next(user_ns, n);
300 : : }
301 : :
302 : : /*
303 : : * Implement "/proc/key-users" to provides a list of the key users and their
304 : : * quotas.
305 : : */
306 : 0 : static int proc_key_users_open(struct inode *inode, struct file *file)
307 : : {
308 : 1 : return seq_open(file, &proc_key_users_ops);
309 : : }
310 : :
311 : 0 : static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
312 : : __acquires(key_user_lock)
313 : : {
314 : : struct rb_node *_p;
315 : 2 : loff_t pos = *_pos;
316 : :
317 : : spin_lock(&key_user_lock);
318 : :
319 : : _p = key_user_first(seq_user_ns(p), &key_user_tree);
320 [ + + ]: 3 : while (pos > 0 && _p) {
321 : 1 : pos--;
322 : : _p = key_user_next(seq_user_ns(p), _p);
323 : : }
324 : :
325 : 2 : return _p;
326 : : }
327 : :
328 : 0 : static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
329 : : {
330 : 1 : (*_pos)++;
331 : 1 : return key_user_next(seq_user_ns(p), (struct rb_node *)v);
332 : : }
333 : :
334 : 0 : static void proc_key_users_stop(struct seq_file *p, void *v)
335 : : __releases(key_user_lock)
336 : : {
337 : : spin_unlock(&key_user_lock);
338 : 2 : }
339 : :
340 : 0 : static int proc_key_users_show(struct seq_file *m, void *v)
341 : : {
342 : : struct rb_node *_p = v;
343 : : struct key_user *user = rb_entry(_p, struct key_user, node);
344 : : unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
345 [ + - ]: 1 : key_quota_root_maxkeys : key_quota_maxkeys;
346 : : unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
347 [ + - ]: 1 : key_quota_root_maxbytes : key_quota_maxbytes;
348 : :
349 : 1 : seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
350 : : from_kuid_munged(seq_user_ns(m), user->uid),
351 : : atomic_read(&user->usage),
352 : : atomic_read(&user->nkeys),
353 : : atomic_read(&user->nikeys),
354 : : user->qnkeys,
355 : : maxkeys,
356 : : user->qnbytes,
357 : : maxbytes);
358 : :
359 : 1 : return 0;
360 : : }
|