]> asedeno.scripts.mit.edu Git - linux.git/blob - security/keys/permission.c
Merge tag 'keys-acl-20190703' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowel...
[linux.git] / security / keys / permission.c
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 <linux/user_namespace.h>
11 #include <linux/uaccess.h>
12 #include "internal.h"
13
14 struct key_acl default_key_acl = {
15         .usage  = REFCOUNT_INIT(1),
16         .nr_ace = 2,
17         .possessor_viewable = true,
18         .aces = {
19                 KEY_POSSESSOR_ACE(KEY_ACE__PERMS & ~KEY_ACE_JOIN),
20                 KEY_OWNER_ACE(KEY_ACE_VIEW),
21         }
22 };
23 EXPORT_SYMBOL(default_key_acl);
24
25 struct key_acl joinable_keyring_acl = {
26         .usage  = REFCOUNT_INIT(1),
27         .nr_ace = 2,
28         .possessor_viewable = true,
29         .aces   = {
30                 KEY_POSSESSOR_ACE(KEY_ACE__PERMS & ~KEY_ACE_JOIN),
31                 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_LINK | KEY_ACE_JOIN),
32         }
33 };
34 EXPORT_SYMBOL(joinable_keyring_acl);
35
36 struct key_acl internal_key_acl = {
37         .usage  = REFCOUNT_INIT(1),
38         .nr_ace = 2,
39         .aces = {
40                 KEY_POSSESSOR_ACE(KEY_ACE_SEARCH),
41                 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_SEARCH),
42         }
43 };
44 EXPORT_SYMBOL(internal_key_acl);
45
46 struct key_acl internal_keyring_acl = {
47         .usage  = REFCOUNT_INIT(1),
48         .nr_ace = 2,
49         .aces = {
50                 KEY_POSSESSOR_ACE(KEY_ACE_SEARCH),
51                 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_SEARCH),
52         }
53 };
54 EXPORT_SYMBOL(internal_keyring_acl);
55
56 struct key_acl internal_writable_keyring_acl = {
57         .usage  = REFCOUNT_INIT(1),
58         .nr_ace = 2,
59         .aces = {
60                 KEY_POSSESSOR_ACE(KEY_ACE_SEARCH | KEY_ACE_WRITE),
61                 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_WRITE | KEY_ACE_SEARCH),
62         }
63 };
64 EXPORT_SYMBOL(internal_writable_keyring_acl);
65
66 /**
67  * key_task_permission - Check a key can be used
68  * @key_ref: The key to check.
69  * @cred: The credentials to use.
70  * @desired_perm: The permission to check for.
71  *
72  * Check to see whether permission is granted to use a key in the desired way,
73  * but permit the security modules to override.
74  *
75  * The caller must hold either a ref on cred or must hold the RCU readlock.
76  *
77  * Returns 0 if successful, -EACCES if access is denied based on the
78  * permissions bits or the LSM check.
79  */
80 int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
81                         unsigned int desired_perm)
82 {
83         const struct key_acl *acl;
84         const struct key *key;
85         unsigned int allow = 0;
86         int i;
87
88         BUILD_BUG_ON(KEY_NEED_VIEW      != KEY_ACE_VIEW         ||
89                      KEY_NEED_READ      != KEY_ACE_READ         ||
90                      KEY_NEED_WRITE     != KEY_ACE_WRITE        ||
91                      KEY_NEED_SEARCH    != KEY_ACE_SEARCH       ||
92                      KEY_NEED_LINK      != KEY_ACE_LINK         ||
93                      KEY_NEED_SETSEC    != KEY_ACE_SET_SECURITY ||
94                      KEY_NEED_INVAL     != KEY_ACE_INVAL        ||
95                      KEY_NEED_REVOKE    != KEY_ACE_REVOKE       ||
96                      KEY_NEED_JOIN      != KEY_ACE_JOIN         ||
97                      KEY_NEED_CLEAR     != KEY_ACE_CLEAR);
98
99         key = key_ref_to_ptr(key_ref);
100
101         rcu_read_lock();
102
103         acl = rcu_dereference(key->acl);
104         if (!acl || acl->nr_ace == 0)
105                 goto no_access_rcu;
106
107         for (i = 0; i < acl->nr_ace; i++) {
108                 const struct key_ace *ace = &acl->aces[i];
109
110                 switch (ace->type) {
111                 case KEY_ACE_SUBJ_STANDARD:
112                         switch (ace->subject_id) {
113                         case KEY_ACE_POSSESSOR:
114                                 if (is_key_possessed(key_ref))
115                                         allow |= ace->perm;
116                                 break;
117                         case KEY_ACE_OWNER:
118                                 if (uid_eq(key->uid, cred->fsuid))
119                                         allow |= ace->perm;
120                                 break;
121                         case KEY_ACE_GROUP:
122                                 if (gid_valid(key->gid)) {
123                                         if (gid_eq(key->gid, cred->fsgid))
124                                                 allow |= ace->perm;
125                                         else if (groups_search(cred->group_info, key->gid))
126                                                 allow |= ace->perm;
127                                 }
128                                 break;
129                         case KEY_ACE_EVERYONE:
130                                 allow |= ace->perm;
131                                 break;
132                         }
133                         break;
134                 }
135         }
136
137         rcu_read_unlock();
138
139         if (!(allow & desired_perm))
140                 goto no_access;
141
142         return security_key_permission(key_ref, cred, desired_perm);
143
144 no_access_rcu:
145         rcu_read_unlock();
146 no_access:
147         return -EACCES;
148 }
149 EXPORT_SYMBOL(key_task_permission);
150
151 /**
152  * key_validate - Validate a key.
153  * @key: The key to be validated.
154  *
155  * Check that a key is valid, returning 0 if the key is okay, -ENOKEY if the
156  * key is invalidated, -EKEYREVOKED if the key's type has been removed or if
157  * the key has been revoked or -EKEYEXPIRED if the key has expired.
158  */
159 int key_validate(const struct key *key)
160 {
161         unsigned long flags = READ_ONCE(key->flags);
162         time64_t expiry = READ_ONCE(key->expiry);
163
164         if (flags & (1 << KEY_FLAG_INVALIDATED))
165                 return -ENOKEY;
166
167         /* check it's still accessible */
168         if (flags & ((1 << KEY_FLAG_REVOKED) |
169                      (1 << KEY_FLAG_DEAD)))
170                 return -EKEYREVOKED;
171
172         /* check it hasn't expired */
173         if (expiry) {
174                 if (ktime_get_real_seconds() >= expiry)
175                         return -EKEYEXPIRED;
176         }
177
178         return 0;
179 }
180 EXPORT_SYMBOL(key_validate);
181
182 /*
183  * Roughly render an ACL to an old-style permissions mask.  We cannot
184  * accurately render what the ACL, particularly if it has ACEs that represent
185  * subjects outside of { poss, user, group, other }.
186  */
187 unsigned int key_acl_to_perm(const struct key_acl *acl)
188 {
189         unsigned int perm = 0, tperm;
190         int i;
191
192         BUILD_BUG_ON(KEY_OTH_VIEW       != KEY_ACE_VIEW         ||
193                      KEY_OTH_READ       != KEY_ACE_READ         ||
194                      KEY_OTH_WRITE      != KEY_ACE_WRITE        ||
195                      KEY_OTH_SEARCH     != KEY_ACE_SEARCH       ||
196                      KEY_OTH_LINK       != KEY_ACE_LINK         ||
197                      KEY_OTH_SETATTR    != KEY_ACE_SET_SECURITY);
198
199         if (!acl || acl->nr_ace == 0)
200                 return 0;
201
202         for (i = 0; i < acl->nr_ace; i++) {
203                 const struct key_ace *ace = &acl->aces[i];
204
205                 switch (ace->type) {
206                 case KEY_ACE_SUBJ_STANDARD:
207                         tperm = ace->perm & KEY_OTH_ALL;
208
209                         /* Invalidation and joining were allowed by SEARCH */
210                         if (ace->perm & (KEY_ACE_INVAL | KEY_ACE_JOIN))
211                                 tperm |= KEY_OTH_SEARCH;
212
213                         /* Revocation was allowed by either SETATTR or WRITE */
214                         if ((ace->perm & KEY_ACE_REVOKE) && !(tperm & KEY_OTH_SETATTR))
215                                 tperm |= KEY_OTH_WRITE;
216
217                         /* Clearing was allowed by WRITE */
218                         if (ace->perm & KEY_ACE_CLEAR)
219                                 tperm |= KEY_OTH_WRITE;
220
221                         switch (ace->subject_id) {
222                         case KEY_ACE_POSSESSOR:
223                                 perm |= tperm << 24;
224                                 break;
225                         case KEY_ACE_OWNER:
226                                 perm |= tperm << 16;
227                                 break;
228                         case KEY_ACE_GROUP:
229                                 perm |= tperm << 8;
230                                 break;
231                         case KEY_ACE_EVERYONE:
232                                 perm |= tperm << 0;
233                                 break;
234                         }
235                 }
236         }
237
238         return perm;
239 }
240
241 /*
242  * Destroy a key's ACL.
243  */
244 void key_put_acl(struct key_acl *acl)
245 {
246         if (acl && refcount_dec_and_test(&acl->usage))
247                 kfree_rcu(acl, rcu);
248 }
249
250 /*
251  * Try to set the ACL.  This either attaches or discards the proposed ACL.
252  */
253 long key_set_acl(struct key *key, struct key_acl *acl)
254 {
255         int i;
256
257         /* If we're not the sysadmin, we can only change a key that we own. */
258         if (!capable(CAP_SYS_ADMIN) && !uid_eq(key->uid, current_fsuid())) {
259                 key_put_acl(acl);
260                 return -EACCES;
261         }
262
263         for (i = 0; i < acl->nr_ace; i++) {
264                 const struct key_ace *ace = &acl->aces[i];
265                 if (ace->type == KEY_ACE_SUBJ_STANDARD &&
266                     ace->subject_id == KEY_ACE_POSSESSOR) {
267                         if (ace->perm & KEY_ACE_VIEW)
268                                 acl->possessor_viewable = true;
269                         break;
270                 }
271         }
272
273         rcu_swap_protected(key->acl, acl, lockdep_is_held(&key->sem));
274         key_put_acl(acl);
275         return 0;
276 }
277
278 /*
279  * Allocate a new ACL with an extra ACE slot.
280  */
281 static struct key_acl *key_alloc_acl(const struct key_acl *old_acl, int nr, int skip)
282 {
283         struct key_acl *acl;
284         int nr_ace, i, j = 0;
285
286         nr_ace = old_acl->nr_ace + nr;
287         if (nr_ace > 16)
288                 return ERR_PTR(-EINVAL);
289
290         acl = kzalloc(struct_size(acl, aces, nr_ace), GFP_KERNEL);
291         if (!acl)
292                 return ERR_PTR(-ENOMEM);
293
294         refcount_set(&acl->usage, 1);
295         acl->nr_ace = nr_ace;
296         for (i = 0; i < old_acl->nr_ace; i++) {
297                 if (i == skip)
298                         continue;
299                 acl->aces[j] = old_acl->aces[i];
300                 j++;
301         }
302         return acl;
303 }
304
305 /*
306  * Generate the revised ACL.
307  */
308 static long key_change_acl(struct key *key, struct key_ace *new_ace)
309 {
310         struct key_acl *acl, *old;
311         int i;
312
313         old = rcu_dereference_protected(key->acl, lockdep_is_held(&key->sem));
314
315         for (i = 0; i < old->nr_ace; i++)
316                 if (old->aces[i].type == new_ace->type &&
317                     old->aces[i].subject_id == new_ace->subject_id)
318                         goto found_match;
319
320         if (new_ace->perm == 0)
321                 return 0; /* No permissions to remove.  Add deny record? */
322
323         acl = key_alloc_acl(old, 1, -1);
324         if (IS_ERR(acl))
325                 return PTR_ERR(acl);
326         acl->aces[i] = *new_ace;
327         goto change;
328
329 found_match:
330         if (new_ace->perm == 0)
331                 goto delete_ace;
332         if (new_ace->perm == old->aces[i].perm)
333                 return 0;
334         acl = key_alloc_acl(old, 0, -1);
335         if (IS_ERR(acl))
336                 return PTR_ERR(acl);
337         acl->aces[i].perm = new_ace->perm;
338         goto change;
339
340 delete_ace:
341         acl = key_alloc_acl(old, -1, i);
342         if (IS_ERR(acl))
343                 return PTR_ERR(acl);
344         goto change;
345
346 change:
347         return key_set_acl(key, acl);
348 }
349
350 /*
351  * Add, alter or remove (if perm == 0) an ACE in a key's ACL.
352  */
353 long keyctl_grant_permission(key_serial_t keyid,
354                              enum key_ace_subject_type type,
355                              unsigned int subject,
356                              unsigned int perm)
357 {
358         struct key_ace new_ace;
359         struct key *key;
360         key_ref_t key_ref;
361         long ret;
362
363         new_ace.type = type;
364         new_ace.perm = perm;
365
366         switch (type) {
367         case KEY_ACE_SUBJ_STANDARD:
368                 if (subject >= nr__key_ace_standard_subject)
369                         return -ENOENT;
370                 new_ace.subject_id = subject;
371                 break;
372
373         default:
374                 return -ENOENT;
375         }
376
377         key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_SETSEC);
378         if (IS_ERR(key_ref)) {
379                 ret = PTR_ERR(key_ref);
380                 goto error;
381         }
382
383         key = key_ref_to_ptr(key_ref);
384
385         down_write(&key->sem);
386
387         /* If we're not the sysadmin, we can only change a key that we own */
388         ret = -EACCES;
389         if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid()))
390                 ret = key_change_acl(key, &new_ace);
391         up_write(&key->sem);
392         key_put(key);
393 error:
394         return ret;
395 }