~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to security/keys/proc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
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
        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
 
 
91
static 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
 
 
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(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
 
 
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(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(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
        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
                                                      true, 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
 
 
272
static 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
 
 
283
static struct rb_node *key_user_next(struct rb_node *n)
 
284
{
 
285
        return __key_user_next(rb_next(n));
 
286
}
 
287
 
 
288
static 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
 */
 
298
static int proc_key_users_open(struct inode *inode, struct file *file)
 
299
{
 
300
        return seq_open(file, &proc_key_users_ops);
 
301
}
 
302
 
 
303
static 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
 
 
320
static 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
 
 
326
static 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
 
 
332
static 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
}