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 return n; 143 } 144 145 static void proc_keys_stop(struct seq_file *p, void *v) 146 __releases(key_serial_lock) 147 { 148 spin_unlock(&key_serial_lock); 149 } 150 151 static int proc_keys_show(struct seq_file *m, void *v) 152 { 153 struct rb_node *_p = v; 154 struct key *key = rb_entry(_p, struct key, serial_node); 155 unsigned long flags; 156 key_ref_t key_ref, skey_ref; 157 time64_t now, expiry; 158 char xbuf[16]; 159 short state; 160 u64 timo; 161 int rc; 162 163 struct keyring_search_context ctx = { 164 .index_key = key->index_key, 165 .cred = m->file->f_cred, 166 .match_data.cmp = lookup_user_key_possessed, 167 .match_data.raw_data = key, 168 .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, 169 .flags = (KEYRING_SEARCH_NO_STATE_CHECK | 170 KEYRING_SEARCH_RECURSE), 171 }; 172 173 key_ref = make_key_ref(key, 0); 174 175 /* determine if the key is possessed by this process (a test we can 176 * skip if the key does not indicate the possessor can view it 177 */ 178 if (key->perm & KEY_POS_VIEW) { 179 rcu_read_lock(); 180 skey_ref = search_cred_keyrings_rcu(&ctx); 181 rcu_read_unlock(); 182 if (!IS_ERR(skey_ref)) { 183 key_ref_put(skey_ref); 184 key_ref = make_key_ref(key, 1); 185 } 186 } 187 188 /* check whether the current task is allowed to view the key */ 189 rc = key_task_permission(key_ref, ctx.cred, KEY_NEED_VIEW); 190 if (rc < 0) 191 return 0; 192 193 now = ktime_get_real_seconds(); 194 195 rcu_read_lock(); 196 197 /* come up with a suitable timeout value */ 198 expiry = READ_ONCE(key->expiry); 199 if (expiry == 0) { 200 memcpy(xbuf, "perm", 5); 201 } else if (now >= expiry) { 202 memcpy(xbuf, "expd", 5); 203 } else { 204 timo = expiry - now; 205 206 if (timo < 60) 207 sprintf(xbuf, "%llus", timo); 208 else if (timo < 60*60) 209 sprintf(xbuf, "%llum", div_u64(timo, 60)); 210 else if (timo < 60*60*24) 211 sprintf(xbuf, "%lluh", div_u64(timo, 60 * 60)); 212 else if (timo < 60*60*24*7) 213 sprintf(xbuf, "%llud", div_u64(timo, 60 * 60 * 24)); 214 else 215 sprintf(xbuf, "%lluw", div_u64(timo, 60 * 60 * 24 * 7)); 216 } 217 218 state = key_read_state(key); 219 220 #define showflag(FLAGS, LETTER, FLAG) \ 221 ((FLAGS & (1 << FLAG)) ? LETTER : '-') 222 223 flags = READ_ONCE(key->flags); 224 seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", 225 key->serial, 226 state != KEY_IS_UNINSTANTIATED ? 'I' : '-', 227 showflag(flags, 'R', KEY_FLAG_REVOKED), 228 showflag(flags, 'D', KEY_FLAG_DEAD), 229 showflag(flags, 'Q', KEY_FLAG_IN_QUOTA), 230 showflag(flags, 'U', KEY_FLAG_USER_CONSTRUCT), 231 state < 0 ? 'N' : '-', 232 showflag(flags, 'i', KEY_FLAG_INVALIDATED), 233 refcount_read(&key->usage), 234 xbuf, 235 key->perm, 236 from_kuid_munged(seq_user_ns(m), key->uid), 237 from_kgid_munged(seq_user_ns(m), key->gid), 238 key->type->name); 239 240 #undef showflag 241 242 if (key->type->describe) 243 key->type->describe(key, m); 244 seq_putc(m, '\n'); 245 246 rcu_read_unlock(); 247 return 0; 248 } 249 250 static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n) 251 { 252 while (n) { 253 struct key_user *user = rb_entry(n, struct key_user, node); 254 if (kuid_has_mapping(user_ns, user->uid)) 255 break; 256 n = rb_next(n); 257 } 258 return n; 259 } 260 261 static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n) 262 { 263 return __key_user_next(user_ns, rb_next(n)); 264 } 265 266 static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r) 267 { 268 struct rb_node *n = rb_first(r); 269 return __key_user_next(user_ns, n); 270 } 271 272 static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) 273 __acquires(key_user_lock) 274 { 275 struct rb_node *_p; 276 loff_t pos = *_pos; 277 278 spin_lock(&key_user_lock); 279 280 _p = key_user_first(seq_user_ns(p), &key_user_tree); 281 while (pos > 0 && _p) { 282 pos--; 283 _p = key_user_next(seq_user_ns(p), _p); 284 } 285 286 return _p; 287 } 288 289 static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) 290 { 291 (*_pos)++; 292 return key_user_next(seq_user_ns(p), (struct rb_node *)v); 293 } 294 295 static void proc_key_users_stop(struct seq_file *p, void *v) 296 __releases(key_user_lock) 297 { 298 spin_unlock(&key_user_lock); 299 } 300 301 static int proc_key_users_show(struct seq_file *m, void *v) 302 { 303 struct rb_node *_p = v; 304 struct key_user *user = rb_entry(_p, struct key_user, node); 305 unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ? 306 key_quota_root_maxkeys : key_quota_maxkeys; 307 unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ? 308 key_quota_root_maxbytes : key_quota_maxbytes; 309 310 seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", 311 from_kuid_munged(seq_user_ns(m), user->uid), 312 refcount_read(&user->usage), 313 atomic_read(&user->nkeys), 314 atomic_read(&user->nikeys), 315 user->qnkeys, 316 maxkeys, 317 user->qnbytes, 318 maxbytes); 319 320 return 0; 321 } 322