cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

permission.c (3235B)


      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 * @need_perm: The permission required.
     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			enum key_need_perm need_perm)
     28{
     29	struct key *key;
     30	key_perm_t kperm, mask;
     31	int ret;
     32
     33	switch (need_perm) {
     34	default:
     35		WARN_ON(1);
     36		return -EACCES;
     37	case KEY_NEED_UNLINK:
     38	case KEY_SYSADMIN_OVERRIDE:
     39	case KEY_AUTHTOKEN_OVERRIDE:
     40	case KEY_DEFER_PERM_CHECK:
     41		goto lsm;
     42
     43	case KEY_NEED_VIEW:	mask = KEY_OTH_VIEW;	break;
     44	case KEY_NEED_READ:	mask = KEY_OTH_READ;	break;
     45	case KEY_NEED_WRITE:	mask = KEY_OTH_WRITE;	break;
     46	case KEY_NEED_SEARCH:	mask = KEY_OTH_SEARCH;	break;
     47	case KEY_NEED_LINK:	mask = KEY_OTH_LINK;	break;
     48	case KEY_NEED_SETATTR:	mask = KEY_OTH_SETATTR;	break;
     49	}
     50
     51	key = key_ref_to_ptr(key_ref);
     52
     53	/* use the second 8-bits of permissions for keys the caller owns */
     54	if (uid_eq(key->uid, cred->fsuid)) {
     55		kperm = key->perm >> 16;
     56		goto use_these_perms;
     57	}
     58
     59	/* use the third 8-bits of permissions for keys the caller has a group
     60	 * membership in common with */
     61	if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) {
     62		if (gid_eq(key->gid, cred->fsgid)) {
     63			kperm = key->perm >> 8;
     64			goto use_these_perms;
     65		}
     66
     67		ret = groups_search(cred->group_info, key->gid);
     68		if (ret) {
     69			kperm = key->perm >> 8;
     70			goto use_these_perms;
     71		}
     72	}
     73
     74	/* otherwise use the least-significant 8-bits */
     75	kperm = key->perm;
     76
     77use_these_perms:
     78
     79	/* use the top 8-bits of permissions for keys the caller possesses
     80	 * - possessor permissions are additive with other permissions
     81	 */
     82	if (is_key_possessed(key_ref))
     83		kperm |= key->perm >> 24;
     84
     85	if ((kperm & mask) != mask)
     86		return -EACCES;
     87
     88	/* let LSM be the final arbiter */
     89lsm:
     90	return security_key_permission(key_ref, cred, need_perm);
     91}
     92EXPORT_SYMBOL(key_task_permission);
     93
     94/**
     95 * key_validate - Validate a key.
     96 * @key: The key to be validated.
     97 *
     98 * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the
     99 * key is invalidated, -EKEYREVOKED if the key's type has been removed or if
    100 * the key has been revoked or -EKEYEXPIRED if the key has expired.
    101 */
    102int key_validate(const struct key *key)
    103{
    104	unsigned long flags = READ_ONCE(key->flags);
    105	time64_t expiry = READ_ONCE(key->expiry);
    106
    107	if (flags & (1 << KEY_FLAG_INVALIDATED))
    108		return -ENOKEY;
    109
    110	/* check it's still accessible */
    111	if (flags & ((1 << KEY_FLAG_REVOKED) |
    112		     (1 << KEY_FLAG_DEAD)))
    113		return -EKEYREVOKED;
    114
    115	/* check it hasn't expired */
    116	if (expiry) {
    117		if (ktime_get_real_seconds() >= expiry)
    118			return -EKEYEXPIRED;
    119	}
    120
    121	return 0;
    122}
    123EXPORT_SYMBOL(key_validate);