Root/security/keys/proc.c

Source at commit be977234bfb4a6dca8a39e7c52165e4cd536ad71 created 9 years 5 months ago.
By Lars-Peter Clausen, jz4740: Fix compile error
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
22static int proc_keys_open(struct inode *inode, struct file *file);
23static void *proc_keys_start(struct seq_file *p, loff_t *_pos);
24static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos);
25static void proc_keys_stop(struct seq_file *p, void *v);
26static int proc_keys_show(struct seq_file *m, void *v);
27
28static 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
35static 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
43static int proc_key_users_open(struct inode *inode, struct file *file);
44static void *proc_key_users_start(struct seq_file *p, loff_t *_pos);
45static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos);
46static void proc_key_users_stop(struct seq_file *p, void *v);
47static int proc_key_users_show(struct seq_file *m, void *v);
48
49static 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
56static 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 */
66static 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    if (!p)
78        panic("Cannot create /proc/key-users\n");
79
80    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
91static struct rb_node *key_serial_next(struct rb_node *n)
92{
93    struct user_namespace *user_ns = current_user_ns();
94
95    n = rb_next(n);
96    while (n) {
97        struct key *key = rb_entry(n, struct key, serial_node);
98        if (key->user->user_ns == user_ns)
99            break;
100        n = rb_next(n);
101    }
102    return n;
103}
104
105static int proc_keys_open(struct inode *inode, struct file *file)
106{
107    return seq_open(file, &proc_keys_ops);
108}
109
110static struct key *find_ge_key(key_serial_t id)
111{
112    struct user_namespace *user_ns = current_user_ns();
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 (minkey->user->user_ns == user_ns)
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
144static 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(pos);
155    if (!key)
156        return NULL;
157    *_pos = key->serial;
158    return &key->serial_node;
159}
160
161static 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
167static 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(v);
172    if (n)
173        *_pos = key_node_serial(n);
174    return n;
175}
176
177static void proc_keys_stop(struct seq_file *p, void *v)
178    __releases(key_serial_lock)
179{
180    spin_unlock(&key_serial_lock);
181}
182
183static int proc_keys_show(struct seq_file *m, void *v)
184{
185    const struct cred *cred = current_cred();
186    struct rb_node *_p = v;
187    struct key *key = rb_entry(_p, struct key, serial_node);
188    struct timespec now;
189    unsigned long timo;
190    key_ref_t key_ref, skey_ref;
191    char xbuf[12];
192    int rc;
193
194    key_ref = make_key_ref(key, 0);
195
196    /* determine if the key is possessed by this process (a test we can
197     * skip if the key does not indicate the possessor can view it
198     */
199    if (key->perm & KEY_POS_VIEW) {
200        skey_ref = search_my_process_keyrings(key->type, key,
201                              lookup_user_key_possessed,
202                              cred);
203        if (!IS_ERR(skey_ref)) {
204            key_ref_put(skey_ref);
205            key_ref = make_key_ref(key, 1);
206        }
207    }
208
209    /* check whether the current task is allowed to view the key (assuming
210     * non-possession)
211     * - the caller holds a spinlock, and thus the RCU read lock, making our
212     * access to __current_cred() safe
213     */
214    rc = key_task_permission(key_ref, cred, KEY_VIEW);
215    if (rc < 0)
216        return 0;
217
218    now = current_kernel_time();
219
220    rcu_read_lock();
221
222    /* come up with a suitable timeout value */
223    if (key->expiry == 0) {
224        memcpy(xbuf, "perm", 5);
225    } else if (now.tv_sec >= key->expiry) {
226        memcpy(xbuf, "expd", 5);
227    } else {
228        timo = key->expiry - now.tv_sec;
229
230        if (timo < 60)
231            sprintf(xbuf, "%lus", timo);
232        else if (timo < 60*60)
233            sprintf(xbuf, "%lum", timo / 60);
234        else if (timo < 60*60*24)
235            sprintf(xbuf, "%luh", timo / (60*60));
236        else if (timo < 60*60*24*7)
237            sprintf(xbuf, "%lud", timo / (60*60*24));
238        else
239            sprintf(xbuf, "%luw", timo / (60*60*24*7));
240    }
241
242#define showflag(KEY, LETTER, FLAG) \
243    (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
244
245    seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
246           key->serial,
247           showflag(key, 'I', KEY_FLAG_INSTANTIATED),
248           showflag(key, 'R', KEY_FLAG_REVOKED),
249           showflag(key, 'D', KEY_FLAG_DEAD),
250           showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
251           showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
252           showflag(key, 'N', KEY_FLAG_NEGATIVE),
253           atomic_read(&key->usage),
254           xbuf,
255           key->perm,
256           key->uid,
257           key->gid,
258           key->type->name);
259
260#undef showflag
261
262    if (key->type->describe)
263        key->type->describe(key, m);
264    seq_putc(m, '\n');
265
266    rcu_read_unlock();
267    return 0;
268}
269
270#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
271
272static struct rb_node *__key_user_next(struct rb_node *n)
273{
274    while (n) {
275        struct key_user *user = rb_entry(n, struct key_user, node);
276        if (user->user_ns == current_user_ns())
277            break;
278        n = rb_next(n);
279    }
280    return n;
281}
282
283static struct rb_node *key_user_next(struct rb_node *n)
284{
285    return __key_user_next(rb_next(n));
286}
287
288static struct rb_node *key_user_first(struct rb_root *r)
289{
290    struct rb_node *n = rb_first(r);
291    return __key_user_next(n);
292}
293
294/*
295 * Implement "/proc/key-users" to provides a list of the key users and their
296 * quotas.
297 */
298static int proc_key_users_open(struct inode *inode, struct file *file)
299{
300    return seq_open(file, &proc_key_users_ops);
301}
302
303static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
304    __acquires(key_user_lock)
305{
306    struct rb_node *_p;
307    loff_t pos = *_pos;
308
309    spin_lock(&key_user_lock);
310
311    _p = key_user_first(&key_user_tree);
312    while (pos > 0 && _p) {
313        pos--;
314        _p = key_user_next(_p);
315    }
316
317    return _p;
318}
319
320static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
321{
322    (*_pos)++;
323    return key_user_next((struct rb_node *)v);
324}
325
326static void proc_key_users_stop(struct seq_file *p, void *v)
327    __releases(key_user_lock)
328{
329    spin_unlock(&key_user_lock);
330}
331
332static int proc_key_users_show(struct seq_file *m, void *v)
333{
334    struct rb_node *_p = v;
335    struct key_user *user = rb_entry(_p, struct key_user, node);
336    unsigned maxkeys = (user->uid == 0) ?
337        key_quota_root_maxkeys : key_quota_maxkeys;
338    unsigned maxbytes = (user->uid == 0) ?
339        key_quota_root_maxbytes : key_quota_maxbytes;
340
341    seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
342           user->uid,
343           atomic_read(&user->usage),
344           atomic_read(&user->nkeys),
345           atomic_read(&user->nikeys),
346           user->qnkeys,
347           maxkeys,
348           user->qnbytes,
349           maxbytes);
350
351    return 0;
352}
353

Archive Download this file



interactive