xref: /linux/security/ipe/fs.c (revision f44554b5067b36c14cc91ed811fa1bd58baed34a)
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 *np __ro_after_init;
16 static struct dentry *root __ro_after_init;
17 struct dentry *policy_root __ro_after_init;
18 static struct dentry *audit_node __ro_after_init;
19 
20 /**
21  * setaudit() - Write handler for the securityfs node, "ipe/success_audit"
22  * @f: Supplies a file structure representing the securityfs node.
23  * @data: Supplies a buffer passed to the write syscall.
24  * @len: Supplies the length of @data.
25  * @offset: unused.
26  *
27  * Return:
28  * * Length of buffer written	- Success
29  * * %-EPERM			- Insufficient permission
30  */
31 static ssize_t setaudit(struct file *f, const char __user *data,
32 			size_t len, loff_t *offset)
33 {
34 	int rc = 0;
35 	bool value;
36 
37 	if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
38 		return -EPERM;
39 
40 	rc = kstrtobool_from_user(data, len, &value);
41 	if (rc)
42 		return rc;
43 
44 	WRITE_ONCE(success_audit, value);
45 
46 	return len;
47 }
48 
49 /**
50  * getaudit() - Read handler for the securityfs node, "ipe/success_audit"
51  * @f: Supplies a file structure representing the securityfs node.
52  * @data: Supplies a buffer passed to the read syscall.
53  * @len: Supplies the length of @data.
54  * @offset: unused.
55  *
56  * Return: Length of buffer written
57  */
58 static ssize_t getaudit(struct file *f, char __user *data,
59 			size_t len, loff_t *offset)
60 {
61 	const char *result;
62 
63 	result = ((READ_ONCE(success_audit)) ? "1" : "0");
64 
65 	return simple_read_from_buffer(data, len, offset, result, 1);
66 }
67 
68 /**
69  * new_policy() - Write handler for the securityfs node, "ipe/new_policy".
70  * @f: Supplies a file structure representing the securityfs node.
71  * @data: Supplies a buffer passed to the write syscall.
72  * @len: Supplies the length of @data.
73  * @offset: unused.
74  *
75  * Return:
76  * * Length of buffer written	- Success
77  * * %-EPERM			- Insufficient permission
78  * * %-ENOMEM			- Out of memory (OOM)
79  * * %-EBADMSG			- Policy is invalid
80  * * %-ERANGE			- Policy version number overflow
81  * * %-EINVAL			- Policy version parsing error
82  * * %-EEXIST			- Same name policy already deployed
83  */
84 static ssize_t new_policy(struct file *f, const char __user *data,
85 			  size_t len, loff_t *offset)
86 {
87 	struct ipe_policy *p = NULL;
88 	char *copy = NULL;
89 	int rc = 0;
90 
91 	if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
92 		return -EPERM;
93 
94 	copy = memdup_user_nul(data, len);
95 	if (IS_ERR(copy))
96 		return PTR_ERR(copy);
97 
98 	p = ipe_new_policy(NULL, 0, copy, len);
99 	if (IS_ERR(p)) {
100 		rc = PTR_ERR(p);
101 		goto out;
102 	}
103 
104 	rc = ipe_new_policyfs_node(p);
105 	if (rc)
106 		goto out;
107 
108 	ipe_audit_policy_load(p);
109 
110 out:
111 	if (rc < 0)
112 		ipe_free_policy(p);
113 	kfree(copy);
114 	return (rc < 0) ? rc : len;
115 }
116 
117 static const struct file_operations np_fops = {
118 	.write = new_policy,
119 };
120 
121 static const struct file_operations audit_fops = {
122 	.write = setaudit,
123 	.read = getaudit,
124 };
125 
126 /**
127  * ipe_init_securityfs() - Initialize IPE's securityfs tree at fsinit.
128  *
129  * Return: %0 on success. If an error occurs, the function will return
130  * the -errno.
131  */
132 static int __init ipe_init_securityfs(void)
133 {
134 	int rc = 0;
135 
136 	if (!ipe_enabled)
137 		return -EOPNOTSUPP;
138 
139 	root = securityfs_create_dir("ipe", NULL);
140 	if (IS_ERR(root)) {
141 		rc = PTR_ERR(root);
142 		goto err;
143 	}
144 
145 	audit_node = securityfs_create_file("success_audit", 0600, root,
146 					    NULL, &audit_fops);
147 	if (IS_ERR(audit_node)) {
148 		rc = PTR_ERR(audit_node);
149 		goto err;
150 	}
151 
152 	policy_root = securityfs_create_dir("policies", root);
153 	if (IS_ERR(policy_root)) {
154 		rc = PTR_ERR(policy_root);
155 		goto err;
156 	}
157 
158 	np = securityfs_create_file("new_policy", 0200, root, NULL, &np_fops);
159 	if (IS_ERR(np)) {
160 		rc = PTR_ERR(np);
161 		goto err;
162 	}
163 
164 	return 0;
165 err:
166 	securityfs_remove(np);
167 	securityfs_remove(policy_root);
168 	securityfs_remove(audit_node);
169 	securityfs_remove(root);
170 	return rc;
171 }
172 
173 fs_initcall(ipe_init_securityfs);
174