1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* procfs files for key database enumeration
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/sched.h>
10*4882a593Smuzhiyun #include <linux/fs.h>
11*4882a593Smuzhiyun #include <linux/proc_fs.h>
12*4882a593Smuzhiyun #include <linux/seq_file.h>
13*4882a593Smuzhiyun #include <asm/errno.h>
14*4882a593Smuzhiyun #include "internal.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun static void *proc_keys_start(struct seq_file *p, loff_t *_pos);
17*4882a593Smuzhiyun static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos);
18*4882a593Smuzhiyun static void proc_keys_stop(struct seq_file *p, void *v);
19*4882a593Smuzhiyun static int proc_keys_show(struct seq_file *m, void *v);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static const struct seq_operations proc_keys_ops = {
22*4882a593Smuzhiyun .start = proc_keys_start,
23*4882a593Smuzhiyun .next = proc_keys_next,
24*4882a593Smuzhiyun .stop = proc_keys_stop,
25*4882a593Smuzhiyun .show = proc_keys_show,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static void *proc_key_users_start(struct seq_file *p, loff_t *_pos);
29*4882a593Smuzhiyun static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos);
30*4882a593Smuzhiyun static void proc_key_users_stop(struct seq_file *p, void *v);
31*4882a593Smuzhiyun static int proc_key_users_show(struct seq_file *m, void *v);
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun static const struct seq_operations proc_key_users_ops = {
34*4882a593Smuzhiyun .start = proc_key_users_start,
35*4882a593Smuzhiyun .next = proc_key_users_next,
36*4882a593Smuzhiyun .stop = proc_key_users_stop,
37*4882a593Smuzhiyun .show = proc_key_users_show,
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*
41*4882a593Smuzhiyun * Declare the /proc files.
42*4882a593Smuzhiyun */
key_proc_init(void)43*4882a593Smuzhiyun static int __init key_proc_init(void)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun struct proc_dir_entry *p;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun p = proc_create_seq("keys", 0, NULL, &proc_keys_ops);
48*4882a593Smuzhiyun if (!p)
49*4882a593Smuzhiyun panic("Cannot create /proc/keys\n");
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun p = proc_create_seq("key-users", 0, NULL, &proc_key_users_ops);
52*4882a593Smuzhiyun if (!p)
53*4882a593Smuzhiyun panic("Cannot create /proc/key-users\n");
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun return 0;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun __initcall(key_proc_init);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /*
61*4882a593Smuzhiyun * Implement "/proc/keys" to provide a list of the keys on the system that
62*4882a593Smuzhiyun * grant View permission to the caller.
63*4882a593Smuzhiyun */
key_serial_next(struct seq_file * p,struct rb_node * n)64*4882a593Smuzhiyun static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun struct user_namespace *user_ns = seq_user_ns(p);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun n = rb_next(n);
69*4882a593Smuzhiyun while (n) {
70*4882a593Smuzhiyun struct key *key = rb_entry(n, struct key, serial_node);
71*4882a593Smuzhiyun if (kuid_has_mapping(user_ns, key->user->uid))
72*4882a593Smuzhiyun break;
73*4882a593Smuzhiyun n = rb_next(n);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun return n;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
find_ge_key(struct seq_file * p,key_serial_t id)78*4882a593Smuzhiyun static struct key *find_ge_key(struct seq_file *p, key_serial_t id)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun struct user_namespace *user_ns = seq_user_ns(p);
81*4882a593Smuzhiyun struct rb_node *n = key_serial_tree.rb_node;
82*4882a593Smuzhiyun struct key *minkey = NULL;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun while (n) {
85*4882a593Smuzhiyun struct key *key = rb_entry(n, struct key, serial_node);
86*4882a593Smuzhiyun if (id < key->serial) {
87*4882a593Smuzhiyun if (!minkey || minkey->serial > key->serial)
88*4882a593Smuzhiyun minkey = key;
89*4882a593Smuzhiyun n = n->rb_left;
90*4882a593Smuzhiyun } else if (id > key->serial) {
91*4882a593Smuzhiyun n = n->rb_right;
92*4882a593Smuzhiyun } else {
93*4882a593Smuzhiyun minkey = key;
94*4882a593Smuzhiyun break;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun key = NULL;
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (!minkey)
100*4882a593Smuzhiyun return NULL;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun for (;;) {
103*4882a593Smuzhiyun if (kuid_has_mapping(user_ns, minkey->user->uid))
104*4882a593Smuzhiyun return minkey;
105*4882a593Smuzhiyun n = rb_next(&minkey->serial_node);
106*4882a593Smuzhiyun if (!n)
107*4882a593Smuzhiyun return NULL;
108*4882a593Smuzhiyun minkey = rb_entry(n, struct key, serial_node);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
proc_keys_start(struct seq_file * p,loff_t * _pos)112*4882a593Smuzhiyun static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
113*4882a593Smuzhiyun __acquires(key_serial_lock)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun key_serial_t pos = *_pos;
116*4882a593Smuzhiyun struct key *key;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun spin_lock(&key_serial_lock);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun if (*_pos > INT_MAX)
121*4882a593Smuzhiyun return NULL;
122*4882a593Smuzhiyun key = find_ge_key(p, pos);
123*4882a593Smuzhiyun if (!key)
124*4882a593Smuzhiyun return NULL;
125*4882a593Smuzhiyun *_pos = key->serial;
126*4882a593Smuzhiyun return &key->serial_node;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
key_node_serial(struct rb_node * n)129*4882a593Smuzhiyun static inline key_serial_t key_node_serial(struct rb_node *n)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct key *key = rb_entry(n, struct key, serial_node);
132*4882a593Smuzhiyun return key->serial;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
proc_keys_next(struct seq_file * p,void * v,loff_t * _pos)135*4882a593Smuzhiyun static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct rb_node *n;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun n = key_serial_next(p, v);
140*4882a593Smuzhiyun if (n)
141*4882a593Smuzhiyun *_pos = key_node_serial(n);
142*4882a593Smuzhiyun else
143*4882a593Smuzhiyun (*_pos)++;
144*4882a593Smuzhiyun return n;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
proc_keys_stop(struct seq_file * p,void * v)147*4882a593Smuzhiyun static void proc_keys_stop(struct seq_file *p, void *v)
148*4882a593Smuzhiyun __releases(key_serial_lock)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun spin_unlock(&key_serial_lock);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
proc_keys_show(struct seq_file * m,void * v)153*4882a593Smuzhiyun static int proc_keys_show(struct seq_file *m, void *v)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun struct rb_node *_p = v;
156*4882a593Smuzhiyun struct key *key = rb_entry(_p, struct key, serial_node);
157*4882a593Smuzhiyun unsigned long flags;
158*4882a593Smuzhiyun key_ref_t key_ref, skey_ref;
159*4882a593Smuzhiyun time64_t now, expiry;
160*4882a593Smuzhiyun char xbuf[16];
161*4882a593Smuzhiyun short state;
162*4882a593Smuzhiyun u64 timo;
163*4882a593Smuzhiyun int rc;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun struct keyring_search_context ctx = {
166*4882a593Smuzhiyun .index_key = key->index_key,
167*4882a593Smuzhiyun .cred = m->file->f_cred,
168*4882a593Smuzhiyun .match_data.cmp = lookup_user_key_possessed,
169*4882a593Smuzhiyun .match_data.raw_data = key,
170*4882a593Smuzhiyun .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT,
171*4882a593Smuzhiyun .flags = (KEYRING_SEARCH_NO_STATE_CHECK |
172*4882a593Smuzhiyun KEYRING_SEARCH_RECURSE),
173*4882a593Smuzhiyun };
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun key_ref = make_key_ref(key, 0);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* determine if the key is possessed by this process (a test we can
178*4882a593Smuzhiyun * skip if the key does not indicate the possessor can view it
179*4882a593Smuzhiyun */
180*4882a593Smuzhiyun if (key->perm & KEY_POS_VIEW) {
181*4882a593Smuzhiyun rcu_read_lock();
182*4882a593Smuzhiyun skey_ref = search_cred_keyrings_rcu(&ctx);
183*4882a593Smuzhiyun rcu_read_unlock();
184*4882a593Smuzhiyun if (!IS_ERR(skey_ref)) {
185*4882a593Smuzhiyun key_ref_put(skey_ref);
186*4882a593Smuzhiyun key_ref = make_key_ref(key, 1);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /* check whether the current task is allowed to view the key */
191*4882a593Smuzhiyun rc = key_task_permission(key_ref, ctx.cred, KEY_NEED_VIEW);
192*4882a593Smuzhiyun if (rc < 0)
193*4882a593Smuzhiyun return 0;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun now = ktime_get_real_seconds();
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun rcu_read_lock();
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /* come up with a suitable timeout value */
200*4882a593Smuzhiyun expiry = READ_ONCE(key->expiry);
201*4882a593Smuzhiyun if (expiry == 0) {
202*4882a593Smuzhiyun memcpy(xbuf, "perm", 5);
203*4882a593Smuzhiyun } else if (now >= expiry) {
204*4882a593Smuzhiyun memcpy(xbuf, "expd", 5);
205*4882a593Smuzhiyun } else {
206*4882a593Smuzhiyun timo = expiry - now;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (timo < 60)
209*4882a593Smuzhiyun sprintf(xbuf, "%llus", timo);
210*4882a593Smuzhiyun else if (timo < 60*60)
211*4882a593Smuzhiyun sprintf(xbuf, "%llum", div_u64(timo, 60));
212*4882a593Smuzhiyun else if (timo < 60*60*24)
213*4882a593Smuzhiyun sprintf(xbuf, "%lluh", div_u64(timo, 60 * 60));
214*4882a593Smuzhiyun else if (timo < 60*60*24*7)
215*4882a593Smuzhiyun sprintf(xbuf, "%llud", div_u64(timo, 60 * 60 * 24));
216*4882a593Smuzhiyun else
217*4882a593Smuzhiyun sprintf(xbuf, "%lluw", div_u64(timo, 60 * 60 * 24 * 7));
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun state = key_read_state(key);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun #define showflag(FLAGS, LETTER, FLAG) \
223*4882a593Smuzhiyun ((FLAGS & (1 << FLAG)) ? LETTER : '-')
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun flags = READ_ONCE(key->flags);
226*4882a593Smuzhiyun seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
227*4882a593Smuzhiyun key->serial,
228*4882a593Smuzhiyun state != KEY_IS_UNINSTANTIATED ? 'I' : '-',
229*4882a593Smuzhiyun showflag(flags, 'R', KEY_FLAG_REVOKED),
230*4882a593Smuzhiyun showflag(flags, 'D', KEY_FLAG_DEAD),
231*4882a593Smuzhiyun showflag(flags, 'Q', KEY_FLAG_IN_QUOTA),
232*4882a593Smuzhiyun showflag(flags, 'U', KEY_FLAG_USER_CONSTRUCT),
233*4882a593Smuzhiyun state < 0 ? 'N' : '-',
234*4882a593Smuzhiyun showflag(flags, 'i', KEY_FLAG_INVALIDATED),
235*4882a593Smuzhiyun refcount_read(&key->usage),
236*4882a593Smuzhiyun xbuf,
237*4882a593Smuzhiyun key->perm,
238*4882a593Smuzhiyun from_kuid_munged(seq_user_ns(m), key->uid),
239*4882a593Smuzhiyun from_kgid_munged(seq_user_ns(m), key->gid),
240*4882a593Smuzhiyun key->type->name);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun #undef showflag
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun if (key->type->describe)
245*4882a593Smuzhiyun key->type->describe(key, m);
246*4882a593Smuzhiyun seq_putc(m, '\n');
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun rcu_read_unlock();
249*4882a593Smuzhiyun return 0;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
__key_user_next(struct user_namespace * user_ns,struct rb_node * n)252*4882a593Smuzhiyun static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun while (n) {
255*4882a593Smuzhiyun struct key_user *user = rb_entry(n, struct key_user, node);
256*4882a593Smuzhiyun if (kuid_has_mapping(user_ns, user->uid))
257*4882a593Smuzhiyun break;
258*4882a593Smuzhiyun n = rb_next(n);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun return n;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
key_user_next(struct user_namespace * user_ns,struct rb_node * n)263*4882a593Smuzhiyun static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun return __key_user_next(user_ns, rb_next(n));
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
key_user_first(struct user_namespace * user_ns,struct rb_root * r)268*4882a593Smuzhiyun static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct rb_node *n = rb_first(r);
271*4882a593Smuzhiyun return __key_user_next(user_ns, n);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
proc_key_users_start(struct seq_file * p,loff_t * _pos)274*4882a593Smuzhiyun static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
275*4882a593Smuzhiyun __acquires(key_user_lock)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct rb_node *_p;
278*4882a593Smuzhiyun loff_t pos = *_pos;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun spin_lock(&key_user_lock);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun _p = key_user_first(seq_user_ns(p), &key_user_tree);
283*4882a593Smuzhiyun while (pos > 0 && _p) {
284*4882a593Smuzhiyun pos--;
285*4882a593Smuzhiyun _p = key_user_next(seq_user_ns(p), _p);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun return _p;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
proc_key_users_next(struct seq_file * p,void * v,loff_t * _pos)291*4882a593Smuzhiyun static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun (*_pos)++;
294*4882a593Smuzhiyun return key_user_next(seq_user_ns(p), (struct rb_node *)v);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
proc_key_users_stop(struct seq_file * p,void * v)297*4882a593Smuzhiyun static void proc_key_users_stop(struct seq_file *p, void *v)
298*4882a593Smuzhiyun __releases(key_user_lock)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun spin_unlock(&key_user_lock);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
proc_key_users_show(struct seq_file * m,void * v)303*4882a593Smuzhiyun static int proc_key_users_show(struct seq_file *m, void *v)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun struct rb_node *_p = v;
306*4882a593Smuzhiyun struct key_user *user = rb_entry(_p, struct key_user, node);
307*4882a593Smuzhiyun unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
308*4882a593Smuzhiyun key_quota_root_maxkeys : key_quota_maxkeys;
309*4882a593Smuzhiyun unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
310*4882a593Smuzhiyun key_quota_root_maxbytes : key_quota_maxbytes;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
313*4882a593Smuzhiyun from_kuid_munged(seq_user_ns(m), user->uid),
314*4882a593Smuzhiyun refcount_read(&user->usage),
315*4882a593Smuzhiyun atomic_read(&user->nkeys),
316*4882a593Smuzhiyun atomic_read(&user->nikeys),
317*4882a593Smuzhiyun user->qnkeys,
318*4882a593Smuzhiyun maxkeys,
319*4882a593Smuzhiyun user->qnbytes,
320*4882a593Smuzhiyun maxbytes);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun return 0;
323*4882a593Smuzhiyun }
324