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