xref: /linux/security/ipe/policy_fs.c (revision a430d95c5efa2b545d26a094eb5f624e36732af0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4  */
5 #include <linux/fs.h>
6 #include <linux/namei.h>
7 #include <linux/types.h>
8 #include <linux/dcache.h>
9 #include <linux/security.h>
10 
11 #include "ipe.h"
12 #include "policy.h"
13 #include "eval.h"
14 #include "fs.h"
15 
16 #define MAX_VERSION_SIZE ARRAY_SIZE("65535.65535.65535")
17 
18 /**
19  * ipefs_file - defines a file in securityfs.
20  */
21 struct ipefs_file {
22 	const char *name;
23 	umode_t access;
24 	const struct file_operations *fops;
25 };
26 
27 /**
28  * read_pkcs7() - Read handler for "ipe/policies/$name/pkcs7".
29  * @f: Supplies a file structure representing the securityfs node.
30  * @data: Supplies a buffer passed to the write syscall.
31  * @len: Supplies the length of @data.
32  * @offset: unused.
33  *
34  * @data will be populated with the pkcs7 blob representing the policy
35  * on success. If the policy is unsigned (like the boot policy), this
36  * will return -ENOENT.
37  *
38  * Return:
39  * * Length of buffer written	- Success
40  * * %-ENOENT			- Policy initializing/deleted or is unsigned
41  */
read_pkcs7(struct file * f,char __user * data,size_t len,loff_t * offset)42 static ssize_t read_pkcs7(struct file *f, char __user *data,
43 			  size_t len, loff_t *offset)
44 {
45 	const struct ipe_policy *p = NULL;
46 	struct inode *root = NULL;
47 	int rc = 0;
48 
49 	root = d_inode(f->f_path.dentry->d_parent);
50 
51 	inode_lock_shared(root);
52 	p = (struct ipe_policy *)root->i_private;
53 	if (!p) {
54 		rc = -ENOENT;
55 		goto out;
56 	}
57 
58 	if (!p->pkcs7) {
59 		rc = -ENOENT;
60 		goto out;
61 	}
62 
63 	rc = simple_read_from_buffer(data, len, offset, p->pkcs7, p->pkcs7len);
64 
65 out:
66 	inode_unlock_shared(root);
67 
68 	return rc;
69 }
70 
71 /**
72  * read_policy() - Read handler for "ipe/policies/$name/policy".
73  * @f: Supplies a file structure representing the securityfs node.
74  * @data: Supplies a buffer passed to the write syscall.
75  * @len: Supplies the length of @data.
76  * @offset: unused.
77  *
78  * @data will be populated with the plain-text version of the policy
79  * on success.
80  *
81  * Return:
82  * * Length of buffer written	- Success
83  * * %-ENOENT			- Policy initializing/deleted
84  */
read_policy(struct file * f,char __user * data,size_t len,loff_t * offset)85 static ssize_t read_policy(struct file *f, char __user *data,
86 			   size_t len, loff_t *offset)
87 {
88 	const struct ipe_policy *p = NULL;
89 	struct inode *root = NULL;
90 	int rc = 0;
91 
92 	root = d_inode(f->f_path.dentry->d_parent);
93 
94 	inode_lock_shared(root);
95 	p = (struct ipe_policy *)root->i_private;
96 	if (!p) {
97 		rc = -ENOENT;
98 		goto out;
99 	}
100 
101 	rc = simple_read_from_buffer(data, len, offset, p->text, p->textlen);
102 
103 out:
104 	inode_unlock_shared(root);
105 
106 	return rc;
107 }
108 
109 /**
110  * read_name() - Read handler for "ipe/policies/$name/name".
111  * @f: Supplies a file structure representing the securityfs node.
112  * @data: Supplies a buffer passed to the write syscall.
113  * @len: Supplies the length of @data.
114  * @offset: unused.
115  *
116  * @data will be populated with the policy_name attribute on success.
117  *
118  * Return:
119  * * Length of buffer written	- Success
120  * * %-ENOENT			- Policy initializing/deleted
121  */
read_name(struct file * f,char __user * data,size_t len,loff_t * offset)122 static ssize_t read_name(struct file *f, char __user *data,
123 			 size_t len, loff_t *offset)
124 {
125 	const struct ipe_policy *p = NULL;
126 	struct inode *root = NULL;
127 	int rc = 0;
128 
129 	root = d_inode(f->f_path.dentry->d_parent);
130 
131 	inode_lock_shared(root);
132 	p = (struct ipe_policy *)root->i_private;
133 	if (!p) {
134 		rc = -ENOENT;
135 		goto out;
136 	}
137 
138 	rc = simple_read_from_buffer(data, len, offset, p->parsed->name,
139 				     strlen(p->parsed->name));
140 
141 out:
142 	inode_unlock_shared(root);
143 
144 	return rc;
145 }
146 
147 /**
148  * read_version() - Read handler for "ipe/policies/$name/version".
149  * @f: Supplies a file structure representing the securityfs node.
150  * @data: Supplies a buffer passed to the write syscall.
151  * @len: Supplies the length of @data.
152  * @offset: unused.
153  *
154  * @data will be populated with the version string on success.
155  *
156  * Return:
157  * * Length of buffer written	- Success
158  * * %-ENOENT			- Policy initializing/deleted
159  */
read_version(struct file * f,char __user * data,size_t len,loff_t * offset)160 static ssize_t read_version(struct file *f, char __user *data,
161 			    size_t len, loff_t *offset)
162 {
163 	char buffer[MAX_VERSION_SIZE] = { 0 };
164 	const struct ipe_policy *p = NULL;
165 	struct inode *root = NULL;
166 	size_t strsize = 0;
167 	ssize_t rc = 0;
168 
169 	root = d_inode(f->f_path.dentry->d_parent);
170 
171 	inode_lock_shared(root);
172 	p = (struct ipe_policy *)root->i_private;
173 	if (!p) {
174 		rc = -ENOENT;
175 		goto out;
176 	}
177 
178 	strsize = scnprintf(buffer, ARRAY_SIZE(buffer), "%hu.%hu.%hu",
179 			    p->parsed->version.major, p->parsed->version.minor,
180 			    p->parsed->version.rev);
181 
182 	rc = simple_read_from_buffer(data, len, offset, buffer, strsize);
183 
184 out:
185 	inode_unlock_shared(root);
186 
187 	return rc;
188 }
189 
190 /**
191  * setactive() - Write handler for "ipe/policies/$name/active".
192  * @f: Supplies a file structure representing the securityfs node.
193  * @data: Supplies a buffer passed to the write syscall.
194  * @len: Supplies the length of @data.
195  * @offset: unused.
196  *
197  * Return:
198  * * Length of buffer written	- Success
199  * * %-EPERM			- Insufficient permission
200  * * %-EINVAL			- Invalid input
201  * * %-ENOENT			- Policy initializing/deleted
202  */
setactive(struct file * f,const char __user * data,size_t len,loff_t * offset)203 static ssize_t setactive(struct file *f, const char __user *data,
204 			 size_t len, loff_t *offset)
205 {
206 	const struct ipe_policy *p = NULL;
207 	struct inode *root = NULL;
208 	bool value = false;
209 	int rc = 0;
210 
211 	if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
212 		return -EPERM;
213 
214 	rc = kstrtobool_from_user(data, len, &value);
215 	if (rc)
216 		return rc;
217 
218 	if (!value)
219 		return -EINVAL;
220 
221 	root = d_inode(f->f_path.dentry->d_parent);
222 	inode_lock(root);
223 
224 	p = (struct ipe_policy *)root->i_private;
225 	if (!p) {
226 		rc = -ENOENT;
227 		goto out;
228 	}
229 
230 	rc = ipe_set_active_pol(p);
231 
232 out:
233 	inode_unlock(root);
234 	return (rc < 0) ? rc : len;
235 }
236 
237 /**
238  * getactive() - Read handler for "ipe/policies/$name/active".
239  * @f: Supplies a file structure representing the securityfs node.
240  * @data: Supplies a buffer passed to the write syscall.
241  * @len: Supplies the length of @data.
242  * @offset: unused.
243  *
244  * @data will be populated with the 1 or 0 depending on if the
245  * corresponding policy is active.
246  *
247  * Return:
248  * * Length of buffer written	- Success
249  * * %-ENOENT			- Policy initializing/deleted
250  */
getactive(struct file * f,char __user * data,size_t len,loff_t * offset)251 static ssize_t getactive(struct file *f, char __user *data,
252 			 size_t len, loff_t *offset)
253 {
254 	const struct ipe_policy *p = NULL;
255 	struct inode *root = NULL;
256 	const char *str;
257 	int rc = 0;
258 
259 	root = d_inode(f->f_path.dentry->d_parent);
260 
261 	inode_lock_shared(root);
262 	p = (struct ipe_policy *)root->i_private;
263 	if (!p) {
264 		inode_unlock_shared(root);
265 		return -ENOENT;
266 	}
267 	inode_unlock_shared(root);
268 
269 	str = (p == rcu_access_pointer(ipe_active_policy)) ? "1" : "0";
270 	rc = simple_read_from_buffer(data, len, offset, str, 1);
271 
272 	return rc;
273 }
274 
275 /**
276  * update_policy() - Write handler for "ipe/policies/$name/update".
277  * @f: Supplies a file structure representing the securityfs node.
278  * @data: Supplies a buffer passed to the write syscall.
279  * @len: Supplies the length of @data.
280  * @offset: unused.
281  *
282  * On success this updates the policy represented by $name,
283  * in-place.
284  *
285  * Return: Length of buffer written on success. If an error occurs,
286  * the function will return the -errno.
287  */
update_policy(struct file * f,const char __user * data,size_t len,loff_t * offset)288 static ssize_t update_policy(struct file *f, const char __user *data,
289 			     size_t len, loff_t *offset)
290 {
291 	struct inode *root = NULL;
292 	char *copy = NULL;
293 	int rc = 0;
294 
295 	if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
296 		return -EPERM;
297 
298 	copy = memdup_user(data, len);
299 	if (IS_ERR(copy))
300 		return PTR_ERR(copy);
301 
302 	root = d_inode(f->f_path.dentry->d_parent);
303 	inode_lock(root);
304 	rc = ipe_update_policy(root, NULL, 0, copy, len);
305 	inode_unlock(root);
306 
307 	kfree(copy);
308 	if (rc)
309 		return rc;
310 
311 	return len;
312 }
313 
314 /**
315  * delete_policy() - write handler for  "ipe/policies/$name/delete".
316  * @f: Supplies a file structure representing the securityfs node.
317  * @data: Supplies a buffer passed to the write syscall.
318  * @len: Supplies the length of @data.
319  * @offset: unused.
320  *
321  * On success this deletes the policy represented by $name.
322  *
323  * Return:
324  * * Length of buffer written	- Success
325  * * %-EPERM			- Insufficient permission/deleting active policy
326  * * %-EINVAL			- Invalid input
327  * * %-ENOENT			- Policy initializing/deleted
328  */
delete_policy(struct file * f,const char __user * data,size_t len,loff_t * offset)329 static ssize_t delete_policy(struct file *f, const char __user *data,
330 			     size_t len, loff_t *offset)
331 {
332 	struct ipe_policy *ap = NULL;
333 	struct ipe_policy *p = NULL;
334 	struct inode *root = NULL;
335 	bool value = false;
336 	int rc = 0;
337 
338 	if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
339 		return -EPERM;
340 
341 	rc = kstrtobool_from_user(data, len, &value);
342 	if (rc)
343 		return rc;
344 
345 	if (!value)
346 		return -EINVAL;
347 
348 	root = d_inode(f->f_path.dentry->d_parent);
349 	inode_lock(root);
350 	p = (struct ipe_policy *)root->i_private;
351 	if (!p) {
352 		inode_unlock(root);
353 		return -ENOENT;
354 	}
355 
356 	mutex_lock(&ipe_policy_lock);
357 	ap = rcu_dereference_protected(ipe_active_policy,
358 				       lockdep_is_held(&ipe_policy_lock));
359 	if (p == ap) {
360 		mutex_unlock(&ipe_policy_lock);
361 		inode_unlock(root);
362 		return -EPERM;
363 	}
364 	mutex_unlock(&ipe_policy_lock);
365 
366 	root->i_private = NULL;
367 	inode_unlock(root);
368 
369 	synchronize_rcu();
370 	ipe_free_policy(p);
371 
372 	return len;
373 }
374 
375 static const struct file_operations content_fops = {
376 	.read = read_policy,
377 };
378 
379 static const struct file_operations pkcs7_fops = {
380 	.read = read_pkcs7,
381 };
382 
383 static const struct file_operations name_fops = {
384 	.read = read_name,
385 };
386 
387 static const struct file_operations ver_fops = {
388 	.read = read_version,
389 };
390 
391 static const struct file_operations active_fops = {
392 	.write = setactive,
393 	.read = getactive,
394 };
395 
396 static const struct file_operations update_fops = {
397 	.write = update_policy,
398 };
399 
400 static const struct file_operations delete_fops = {
401 	.write = delete_policy,
402 };
403 
404 /**
405  * policy_subdir - files under a policy subdirectory
406  */
407 static const struct ipefs_file policy_subdir[] = {
408 	{ "pkcs7", 0444, &pkcs7_fops },
409 	{ "policy", 0444, &content_fops },
410 	{ "name", 0444, &name_fops },
411 	{ "version", 0444, &ver_fops },
412 	{ "active", 0600, &active_fops },
413 	{ "update", 0200, &update_fops },
414 	{ "delete", 0200, &delete_fops },
415 };
416 
417 /**
418  * ipe_del_policyfs_node() - Delete a securityfs entry for @p.
419  * @p: Supplies a pointer to the policy to delete a securityfs entry for.
420  */
ipe_del_policyfs_node(struct ipe_policy * p)421 void ipe_del_policyfs_node(struct ipe_policy *p)
422 {
423 	securityfs_recursive_remove(p->policyfs);
424 	p->policyfs = NULL;
425 }
426 
427 /**
428  * ipe_new_policyfs_node() - Create a securityfs entry for @p.
429  * @p: Supplies a pointer to the policy to create a securityfs entry for.
430  *
431  * Return: %0 on success. If an error occurs, the function will return
432  * the -errno.
433  */
ipe_new_policyfs_node(struct ipe_policy * p)434 int ipe_new_policyfs_node(struct ipe_policy *p)
435 {
436 	const struct ipefs_file *f = NULL;
437 	struct dentry *policyfs = NULL;
438 	struct inode *root = NULL;
439 	struct dentry *d = NULL;
440 	size_t i = 0;
441 	int rc = 0;
442 
443 	if (p->policyfs)
444 		return 0;
445 
446 	policyfs = securityfs_create_dir(p->parsed->name, policy_root);
447 	if (IS_ERR(policyfs))
448 		return PTR_ERR(policyfs);
449 
450 	root = d_inode(policyfs);
451 
452 	for (i = 0; i < ARRAY_SIZE(policy_subdir); ++i) {
453 		f = &policy_subdir[i];
454 
455 		d = securityfs_create_file(f->name, f->access, policyfs,
456 					   NULL, f->fops);
457 		if (IS_ERR(d)) {
458 			rc = PTR_ERR(d);
459 			goto err;
460 		}
461 	}
462 
463 	inode_lock(root);
464 	p->policyfs = policyfs;
465 	root->i_private = p;
466 	inode_unlock(root);
467 
468 	return 0;
469 err:
470 	securityfs_recursive_remove(policyfs);
471 	return rc;
472 }
473