xref: /linux/security/keys/permission.c (revision e9a83bd2322035ed9d7dcf35753d3f984d76c6a5)
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 }
396