linux/security/keys/proc.c
<<
>>
Prefs
   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
  16static void *proc_keys_start(struct seq_file *p, loff_t *_pos);
  17static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos);
  18static void proc_keys_stop(struct seq_file *p, void *v);
  19static int proc_keys_show(struct seq_file *m, void *v);
  20
  21static 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
  28static void *proc_key_users_start(struct seq_file *p, loff_t *_pos);
  29static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos);
  30static void proc_key_users_stop(struct seq_file *p, void *v);
  31static int proc_key_users_show(struct seq_file *m, void *v);
  32
  33static 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 */
  43static 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 */
  64static 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
  78static 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
 112static 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
 129static 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
 135static 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
 147static void proc_keys_stop(struct seq_file *p, void *v)
 148        __releases(key_serial_lock)
 149{
 150        spin_unlock(&key_serial_lock);
 151}
 152
 153static 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 == 0) {
 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
 252static 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
 263static 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
 268static 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
 274static 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
 291static 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
 297static 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
 303static 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