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