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        return n;
 143}
 144
 145static void proc_keys_stop(struct seq_file *p, void *v)
 146        __releases(key_serial_lock)
 147{
 148        spin_unlock(&key_serial_lock);
 149}
 150
 151static 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
 250static 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
 261static 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
 266static 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
 272static 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
 289static 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
 295static 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
 301static 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