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 */ 29 int 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 62 use_other_perms: 63 64 /* otherwise use the least-significant 8-bits */ 65 kperm = key->perm; 66 67 use_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 85 EXPORT_SYMBOL(key_task_permission); 86 87 /*****************************************************************************/ 88 /* 89 * validate a key 90 */ 91 int 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 117 EXPORT_SYMBOL(key_validate); 118