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