linux/security/keys/permission.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Key permission checking
   3 *
   4 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/export.h>
   9#include <linux/security.h>
  10#include "internal.h"
  11
  12/**
  13 * key_task_permission - Check a key can be used
  14 * @key_ref: The key to check.
  15 * @cred: The credentials to use.
  16 * @perm: The permissions to check for.
  17 *
  18 * Check to see whether permission is granted to use a key in the desired way,
  19 * but permit the security modules to override.
  20 *
  21 * The caller must hold either a ref on cred or must hold the RCU readlock.
  22 *
  23 * Returns 0 if successful, -EACCES if access is denied based on the
  24 * permissions bits or the LSM check.
  25 */
  26int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
  27                        unsigned perm)
  28{
  29        struct key *key;
  30        key_perm_t kperm;
  31        int ret;
  32
  33        key = key_ref_to_ptr(key_ref);
  34
  35        /* use the second 8-bits of permissions for keys the caller owns */
  36        if (uid_eq(key->uid, cred->fsuid)) {
  37                kperm = key->perm >> 16;
  38                goto use_these_perms;
  39        }
  40
  41        /* use the third 8-bits of permissions for keys the caller has a group
  42         * membership in common with */
  43        if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) {
  44                if (gid_eq(key->gid, cred->fsgid)) {
  45                        kperm = key->perm >> 8;
  46                        goto use_these_perms;
  47                }
  48
  49                ret = groups_search(cred->group_info, key->gid);
  50                if (ret) {
  51                        kperm = key->perm >> 8;
  52                        goto use_these_perms;
  53                }
  54        }
  55
  56        /* otherwise use the least-significant 8-bits */
  57        kperm = key->perm;
  58
  59use_these_perms:
  60
  61        /* use the top 8-bits of permissions for keys the caller possesses
  62         * - possessor permissions are additive with other permissions
  63         */
  64        if (is_key_possessed(key_ref))
  65                kperm |= key->perm >> 24;
  66
  67        kperm = kperm & perm & KEY_NEED_ALL;
  68
  69        if (kperm != perm)
  70                return -EACCES;
  71
  72        /* let LSM be the final arbiter */
  73        return security_key_permission(key_ref, cred, perm);
  74}
  75EXPORT_SYMBOL(key_task_permission);
  76
  77/**
  78 * key_validate - Validate a key.
  79 * @key: The key to be validated.
  80 *
  81 * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the
  82 * key is invalidated, -EKEYREVOKED if the key's type has been removed or if
  83 * the key has been revoked or -EKEYEXPIRED if the key has expired.
  84 */
  85int key_validate(const struct key *key)
  86{
  87        unsigned long flags = READ_ONCE(key->flags);
  88        time64_t expiry = READ_ONCE(key->expiry);
  89
  90        if (flags & (1 << KEY_FLAG_INVALIDATED))
  91                return -ENOKEY;
  92
  93        /* check it's still accessible */
  94        if (flags & ((1 << KEY_FLAG_REVOKED) |
  95                     (1 << KEY_FLAG_DEAD)))
  96                return -EKEYREVOKED;
  97
  98        /* check it hasn't expired */
  99        if (expiry) {
 100                if (ktime_get_real_seconds() >= expiry)
 101                        return -EKEYEXPIRED;
 102        }
 103
 104        return 0;
 105}
 106EXPORT_SYMBOL(key_validate);
 107