linux/security/keys/permission.c
<<
>>
Prefs
   1/* permission.c: key permission determination
   2 *
   3 * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/security.h>
  14#include "internal.h"
  15
  16/*****************************************************************************/
  17/**
  18 * key_task_permission - Check a key can be used
  19 * @key_ref: The key to check
  20 * @cred: The credentials to use
  21 * @perm: The permissions to check for
  22 *
  23 * Check to see whether permission is granted to use a key in the desired way,
  24 * but permit the security modules to override.
  25 *
  26 * The caller must hold either a ref on cred or must hold the RCU readlock or a
  27 * spinlock.
  28 */
  29int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
  30                        key_perm_t perm)
  31{
  32        struct key *key;
  33        key_perm_t kperm;
  34        int ret;
  35
  36        key = key_ref_to_ptr(key_ref);
  37
  38        if (key->user->user_ns != cred->user->user_ns)
  39                goto use_other_perms;
  40
  41        /* use the second 8-bits of permissions for keys the caller owns */
  42        if (key->uid == cred->fsuid) {
  43                kperm = key->perm >> 16;
  44                goto use_these_perms;
  45        }
  46
  47        /* use the third 8-bits of permissions for keys the caller has a group
  48         * membership in common with */
  49        if (key->gid != -1 && key->perm & KEY_GRP_ALL) {
  50                if (key->gid == cred->fsgid) {
  51                        kperm = key->perm >> 8;
  52                        goto use_these_perms;
  53                }
  54
  55                ret = groups_search(cred->group_info, key->gid);
  56                if (ret) {
  57                        kperm = key->perm >> 8;
  58                        goto use_these_perms;
  59                }
  60        }
  61
  62use_other_perms:
  63
  64        /* otherwise use the least-significant 8-bits */
  65        kperm = key->perm;
  66
  67use_these_perms:
  68
  69        /* use the top 8-bits of permissions for keys the caller possesses
  70         * - possessor permissions are additive with other permissions
  71         */
  72        if (is_key_possessed(key_ref))
  73                kperm |= key->perm >> 24;
  74
  75        kperm = kperm & perm & KEY_ALL;
  76
  77        if (kperm != perm)
  78                return -EACCES;
  79
  80        /* let LSM be the final arbiter */
  81        return security_key_permission(key_ref, cred, perm);
  82
  83} /* end key_task_permission() */
  84
  85EXPORT_SYMBOL(key_task_permission);
  86
  87/*****************************************************************************/
  88/*
  89 * validate a key
  90 */
  91int key_validate(struct key *key)
  92{
  93        struct timespec now;
  94        int ret = 0;
  95
  96        if (key) {
  97                /* check it's still accessible */
  98                ret = -EKEYREVOKED;
  99                if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
 100                    test_bit(KEY_FLAG_DEAD, &key->flags))
 101                        goto error;
 102
 103                /* check it hasn't expired */
 104                ret = 0;
 105                if (key->expiry) {
 106                        now = current_kernel_time();
 107                        if (now.tv_sec >= key->expiry)
 108                                ret = -EKEYEXPIRED;
 109                }
 110        }
 111
 112 error:
 113        return ret;
 114
 115} /* end key_validate() */
 116
 117EXPORT_SYMBOL(key_validate);
 118