xref: /openbmc/linux/fs/cachefiles/security.c (revision dc1b4df0)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* CacheFiles security management
3  *
4  * Copyright (C) 2007, 2021 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #include <linux/fs.h>
9 #include <linux/cred.h>
10 #include "internal.h"
11 
12 /*
13  * determine the security context within which we access the cache from within
14  * the kernel
15  */
16 int cachefiles_get_security_ID(struct cachefiles_cache *cache)
17 {
18 	struct cred *new;
19 	int ret;
20 
21 	_enter("{%s}", cache->secctx);
22 
23 	new = prepare_kernel_cred(current);
24 	if (!new) {
25 		ret = -ENOMEM;
26 		goto error;
27 	}
28 
29 	if (cache->secctx) {
30 		ret = set_security_override_from_ctx(new, cache->secctx);
31 		if (ret < 0) {
32 			put_cred(new);
33 			pr_err("Security denies permission to nominate security context: error %d\n",
34 			       ret);
35 			goto error;
36 		}
37 	}
38 
39 	cache->cache_cred = new;
40 	ret = 0;
41 error:
42 	_leave(" = %d", ret);
43 	return ret;
44 }
45 
46 /*
47  * see if mkdir and create can be performed in the root directory
48  */
49 static int cachefiles_check_cache_dir(struct cachefiles_cache *cache,
50 				      struct dentry *root)
51 {
52 	int ret;
53 
54 	ret = security_inode_mkdir(d_backing_inode(root), root, 0);
55 	if (ret < 0) {
56 		pr_err("Security denies permission to make dirs: error %d",
57 		       ret);
58 		return ret;
59 	}
60 
61 	ret = security_inode_create(d_backing_inode(root), root, 0);
62 	if (ret < 0)
63 		pr_err("Security denies permission to create files: error %d",
64 		       ret);
65 
66 	return ret;
67 }
68 
69 /*
70  * check the security details of the on-disk cache
71  * - must be called with security override in force
72  * - must return with a security override in force - even in the case of an
73  *   error
74  */
75 int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
76 					struct dentry *root,
77 					const struct cred **_saved_cred)
78 {
79 	struct cred *new;
80 	int ret;
81 
82 	_enter("");
83 
84 	/* duplicate the cache creds for COW (the override is currently in
85 	 * force, so we can use prepare_creds() to do this) */
86 	new = prepare_creds();
87 	if (!new)
88 		return -ENOMEM;
89 
90 	cachefiles_end_secure(cache, *_saved_cred);
91 
92 	/* use the cache root dir's security context as the basis with
93 	 * which create files */
94 	ret = set_create_files_as(new, d_backing_inode(root));
95 	if (ret < 0) {
96 		abort_creds(new);
97 		cachefiles_begin_secure(cache, _saved_cred);
98 		_leave(" = %d [cfa]", ret);
99 		return ret;
100 	}
101 
102 	put_cred(cache->cache_cred);
103 	cache->cache_cred = new;
104 
105 	cachefiles_begin_secure(cache, _saved_cred);
106 	ret = cachefiles_check_cache_dir(cache, root);
107 
108 	if (ret == -EOPNOTSUPP)
109 		ret = 0;
110 	_leave(" = %d", ret);
111 	return ret;
112 }
113