Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/ipe/fs.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4
*/
5
6
#include <linux/dcache.h>
7
#include <linux/security.h>
8
9
#include "ipe.h"
10
#include "fs.h"
11
#include "eval.h"
12
#include "policy.h"
13
#include "audit.h"
14
15
static struct dentry *root __ro_after_init;
16
struct dentry *policy_root __ro_after_init;
17
18
/**
19
* setaudit() - Write handler for the securityfs node, "ipe/success_audit"
20
* @f: Supplies a file structure representing the securityfs node.
21
* @data: Supplies a buffer passed to the write syscall.
22
* @len: Supplies the length of @data.
23
* @offset: unused.
24
*
25
* Return:
26
* * Length of buffer written - Success
27
* * %-EPERM - Insufficient permission
28
*/
29
static ssize_t setaudit(struct file *f, const char __user *data,
30
size_t len, loff_t *offset)
31
{
32
int rc = 0;
33
bool value;
34
35
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
36
return -EPERM;
37
38
rc = kstrtobool_from_user(data, len, &value);
39
if (rc)
40
return rc;
41
42
WRITE_ONCE(success_audit, value);
43
44
return len;
45
}
46
47
/**
48
* getaudit() - Read handler for the securityfs node, "ipe/success_audit"
49
* @f: Supplies a file structure representing the securityfs node.
50
* @data: Supplies a buffer passed to the read syscall.
51
* @len: Supplies the length of @data.
52
* @offset: unused.
53
*
54
* Return: Length of buffer written
55
*/
56
static ssize_t getaudit(struct file *f, char __user *data,
57
size_t len, loff_t *offset)
58
{
59
const char *result;
60
61
result = ((READ_ONCE(success_audit)) ? "1" : "0");
62
63
return simple_read_from_buffer(data, len, offset, result, 1);
64
}
65
66
/**
67
* setenforce() - Write handler for the securityfs node, "ipe/enforce"
68
* @f: Supplies a file structure representing the securityfs node.
69
* @data: Supplies a buffer passed to the write syscall.
70
* @len: Supplies the length of @data.
71
* @offset: unused.
72
*
73
* Return:
74
* * Length of buffer written - Success
75
* * %-EPERM - Insufficient permission
76
*/
77
static ssize_t setenforce(struct file *f, const char __user *data,
78
size_t len, loff_t *offset)
79
{
80
int rc = 0;
81
bool new_value, old_value;
82
83
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
84
return -EPERM;
85
86
old_value = READ_ONCE(enforce);
87
rc = kstrtobool_from_user(data, len, &new_value);
88
if (rc)
89
return rc;
90
91
if (new_value != old_value) {
92
ipe_audit_enforce(new_value, old_value);
93
WRITE_ONCE(enforce, new_value);
94
}
95
96
return len;
97
}
98
99
/**
100
* getenforce() - Read handler for the securityfs node, "ipe/enforce"
101
* @f: Supplies a file structure representing the securityfs node.
102
* @data: Supplies a buffer passed to the read syscall.
103
* @len: Supplies the length of @data.
104
* @offset: unused.
105
*
106
* Return: Length of buffer written
107
*/
108
static ssize_t getenforce(struct file *f, char __user *data,
109
size_t len, loff_t *offset)
110
{
111
const char *result;
112
113
result = ((READ_ONCE(enforce)) ? "1" : "0");
114
115
return simple_read_from_buffer(data, len, offset, result, 1);
116
}
117
118
/**
119
* new_policy() - Write handler for the securityfs node, "ipe/new_policy".
120
* @f: Supplies a file structure representing the securityfs node.
121
* @data: Supplies a buffer passed to the write syscall.
122
* @len: Supplies the length of @data.
123
* @offset: unused.
124
*
125
* Return:
126
* * Length of buffer written - Success
127
* * %-EPERM - Insufficient permission
128
* * %-ENOMEM - Out of memory (OOM)
129
* * %-EBADMSG - Policy is invalid
130
* * %-ERANGE - Policy version number overflow
131
* * %-EINVAL - Policy version parsing error
132
* * %-EEXIST - Same name policy already deployed
133
* * %-ENOKEY - Policy signing key not found
134
* * %-EKEYREJECTED - Policy signature verification failed
135
*/
136
static ssize_t new_policy(struct file *f, const char __user *data,
137
size_t len, loff_t *offset)
138
{
139
struct ipe_policy *p = NULL;
140
char *copy = NULL;
141
int rc = 0;
142
143
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) {
144
rc = -EPERM;
145
goto out;
146
}
147
148
copy = memdup_user_nul(data, len);
149
if (IS_ERR(copy)) {
150
rc = PTR_ERR(copy);
151
copy = NULL;
152
goto out;
153
}
154
155
p = ipe_new_policy(NULL, 0, copy, len);
156
if (IS_ERR(p)) {
157
rc = PTR_ERR(p);
158
goto out;
159
}
160
161
rc = ipe_new_policyfs_node(p);
162
if (rc)
163
goto out;
164
165
out:
166
kfree(copy);
167
if (rc < 0) {
168
ipe_free_policy(p);
169
ipe_audit_policy_load(ERR_PTR(rc));
170
} else {
171
ipe_audit_policy_load(p);
172
}
173
return (rc < 0) ? rc : len;
174
}
175
176
static const struct file_operations np_fops = {
177
.write = new_policy,
178
};
179
180
static const struct file_operations audit_fops = {
181
.write = setaudit,
182
.read = getaudit,
183
};
184
185
static const struct file_operations enforce_fops = {
186
.write = setenforce,
187
.read = getenforce,
188
};
189
190
/**
191
* ipe_init_securityfs() - Initialize IPE's securityfs tree at fsinit.
192
*
193
* Return: %0 on success. If an error occurs, the function will return
194
* the -errno.
195
*/
196
static int __init ipe_init_securityfs(void)
197
{
198
int rc = 0;
199
struct ipe_policy *ap;
200
struct dentry *dentry;
201
202
if (!ipe_enabled)
203
return -EOPNOTSUPP;
204
205
root = securityfs_create_dir("ipe", NULL);
206
if (IS_ERR(root))
207
return PTR_ERR(root);
208
209
dentry = securityfs_create_file("success_audit", 0600, root,
210
NULL, &audit_fops);
211
if (IS_ERR(dentry)) {
212
rc = PTR_ERR(dentry);
213
goto err;
214
}
215
216
dentry = securityfs_create_file("enforce", 0600, root, NULL,
217
&enforce_fops);
218
if (IS_ERR(dentry)) {
219
rc = PTR_ERR(dentry);
220
goto err;
221
}
222
223
policy_root = securityfs_create_dir("policies", root);
224
if (IS_ERR(policy_root)) {
225
rc = PTR_ERR(policy_root);
226
goto err;
227
}
228
229
ap = rcu_access_pointer(ipe_active_policy);
230
if (ap) {
231
rc = ipe_new_policyfs_node(ap);
232
if (rc)
233
goto err;
234
}
235
236
dentry = securityfs_create_file("new_policy", 0200, root, NULL, &np_fops);
237
if (IS_ERR(dentry)) {
238
rc = PTR_ERR(dentry);
239
goto err;
240
}
241
242
return 0;
243
err:
244
securityfs_remove(root);
245
return rc;
246
}
247
248
fs_initcall(ipe_init_securityfs);
249
250