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(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(dir: d_backing_inode(upper: root), dentry: root, mode: 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(dir: d_backing_inode(upper: root), dentry: root, mode: 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: *_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(upper: 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(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 | |