drm/panthor: Don't add write fences to the shared BOs
[drm/drm-misc.git] / security / ipe / policy_fs.c
blob3bcd8cbd09dff320883873087cfd0eb17d6720a2
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>
11 #include "ipe.h"
12 #include "policy.h"
13 #include "eval.h"
14 #include "fs.h"
16 #define MAX_VERSION_SIZE ARRAY_SIZE("65535.65535.65535")
18 /**
19 * ipefs_file - defines a file in securityfs.
21 struct ipefs_file {
22 const char *name;
23 umode_t access;
24 const struct file_operations *fops;
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.
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.
38 * Return:
39 * * Length of buffer written - Success
40 * * %-ENOENT - Policy initializing/deleted or is unsigned
42 static ssize_t read_pkcs7(struct file *f, char __user *data,
43 size_t len, loff_t *offset)
45 const struct ipe_policy *p = NULL;
46 struct inode *root = NULL;
47 int rc = 0;
49 root = d_inode(f->f_path.dentry->d_parent);
51 inode_lock_shared(root);
52 p = (struct ipe_policy *)root->i_private;
53 if (!p) {
54 rc = -ENOENT;
55 goto out;
58 if (!p->pkcs7) {
59 rc = -ENOENT;
60 goto out;
63 rc = simple_read_from_buffer(data, len, offset, p->pkcs7, p->pkcs7len);
65 out:
66 inode_unlock_shared(root);
68 return rc;
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.
78 * @data will be populated with the plain-text version of the policy
79 * on success.
81 * Return:
82 * * Length of buffer written - Success
83 * * %-ENOENT - Policy initializing/deleted
85 static ssize_t read_policy(struct file *f, char __user *data,
86 size_t len, loff_t *offset)
88 const struct ipe_policy *p = NULL;
89 struct inode *root = NULL;
90 int rc = 0;
92 root = d_inode(f->f_path.dentry->d_parent);
94 inode_lock_shared(root);
95 p = (struct ipe_policy *)root->i_private;
96 if (!p) {
97 rc = -ENOENT;
98 goto out;
101 rc = simple_read_from_buffer(data, len, offset, p->text, p->textlen);
103 out:
104 inode_unlock_shared(root);
106 return rc;
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.
116 * @data will be populated with the policy_name attribute on success.
118 * Return:
119 * * Length of buffer written - Success
120 * * %-ENOENT - Policy initializing/deleted
122 static ssize_t read_name(struct file *f, char __user *data,
123 size_t len, loff_t *offset)
125 const struct ipe_policy *p = NULL;
126 struct inode *root = NULL;
127 int rc = 0;
129 root = d_inode(f->f_path.dentry->d_parent);
131 inode_lock_shared(root);
132 p = (struct ipe_policy *)root->i_private;
133 if (!p) {
134 rc = -ENOENT;
135 goto out;
138 rc = simple_read_from_buffer(data, len, offset, p->parsed->name,
139 strlen(p->parsed->name));
141 out:
142 inode_unlock_shared(root);
144 return rc;
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.
154 * @data will be populated with the version string on success.
156 * Return:
157 * * Length of buffer written - Success
158 * * %-ENOENT - Policy initializing/deleted
160 static ssize_t read_version(struct file *f, char __user *data,
161 size_t len, loff_t *offset)
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;
169 root = d_inode(f->f_path.dentry->d_parent);
171 inode_lock_shared(root);
172 p = (struct ipe_policy *)root->i_private;
173 if (!p) {
174 rc = -ENOENT;
175 goto out;
178 strsize = scnprintf(buffer, ARRAY_SIZE(buffer), "%hu.%hu.%hu",
179 p->parsed->version.major, p->parsed->version.minor,
180 p->parsed->version.rev);
182 rc = simple_read_from_buffer(data, len, offset, buffer, strsize);
184 out:
185 inode_unlock_shared(root);
187 return rc;
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.
197 * Return:
198 * * Length of buffer written - Success
199 * * %-EPERM - Insufficient permission
200 * * %-EINVAL - Invalid input
201 * * %-ENOENT - Policy initializing/deleted
203 static ssize_t setactive(struct file *f, const char __user *data,
204 size_t len, loff_t *offset)
206 const struct ipe_policy *p = NULL;
207 struct inode *root = NULL;
208 bool value = false;
209 int rc = 0;
211 if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
212 return -EPERM;
214 rc = kstrtobool_from_user(data, len, &value);
215 if (rc)
216 return rc;
218 if (!value)
219 return -EINVAL;
221 root = d_inode(f->f_path.dentry->d_parent);
222 inode_lock(root);
224 p = (struct ipe_policy *)root->i_private;
225 if (!p) {
226 rc = -ENOENT;
227 goto out;
230 rc = ipe_set_active_pol(p);
232 out:
233 inode_unlock(root);
234 return (rc < 0) ? rc : len;
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.
244 * @data will be populated with the 1 or 0 depending on if the
245 * corresponding policy is active.
247 * Return:
248 * * Length of buffer written - Success
249 * * %-ENOENT - Policy initializing/deleted
251 static ssize_t getactive(struct file *f, char __user *data,
252 size_t len, loff_t *offset)
254 const struct ipe_policy *p = NULL;
255 struct inode *root = NULL;
256 const char *str;
257 int rc = 0;
259 root = d_inode(f->f_path.dentry->d_parent);
261 inode_lock_shared(root);
262 p = (struct ipe_policy *)root->i_private;
263 if (!p) {
264 inode_unlock_shared(root);
265 return -ENOENT;
267 inode_unlock_shared(root);
269 str = (p == rcu_access_pointer(ipe_active_policy)) ? "1" : "0";
270 rc = simple_read_from_buffer(data, len, offset, str, 1);
272 return rc;
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.
282 * On success this updates the policy represented by $name,
283 * in-place.
285 * Return: Length of buffer written on success. If an error occurs,
286 * the function will return the -errno.
288 static ssize_t update_policy(struct file *f, const char __user *data,
289 size_t len, loff_t *offset)
291 struct inode *root = NULL;
292 char *copy = NULL;
293 int rc = 0;
295 if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
296 return -EPERM;
298 copy = memdup_user(data, len);
299 if (IS_ERR(copy))
300 return PTR_ERR(copy);
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);
307 kfree(copy);
308 if (rc)
309 return rc;
311 return len;
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.
321 * On success this deletes the policy represented by $name.
323 * Return:
324 * * Length of buffer written - Success
325 * * %-EPERM - Insufficient permission/deleting active policy
326 * * %-EINVAL - Invalid input
327 * * %-ENOENT - Policy initializing/deleted
329 static ssize_t delete_policy(struct file *f, const char __user *data,
330 size_t len, loff_t *offset)
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;
338 if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
339 return -EPERM;
341 rc = kstrtobool_from_user(data, len, &value);
342 if (rc)
343 return rc;
345 if (!value)
346 return -EINVAL;
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;
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;
364 mutex_unlock(&ipe_policy_lock);
366 root->i_private = NULL;
367 inode_unlock(root);
369 synchronize_rcu();
370 ipe_free_policy(p);
372 return len;
375 static const struct file_operations content_fops = {
376 .read = read_policy,
379 static const struct file_operations pkcs7_fops = {
380 .read = read_pkcs7,
383 static const struct file_operations name_fops = {
384 .read = read_name,
387 static const struct file_operations ver_fops = {
388 .read = read_version,
391 static const struct file_operations active_fops = {
392 .write = setactive,
393 .read = getactive,
396 static const struct file_operations update_fops = {
397 .write = update_policy,
400 static const struct file_operations delete_fops = {
401 .write = delete_policy,
405 * policy_subdir - files under a policy subdirectory
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 },
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.
421 void ipe_del_policyfs_node(struct ipe_policy *p)
423 securityfs_recursive_remove(p->policyfs);
424 p->policyfs = NULL;
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.
431 * Return: %0 on success. If an error occurs, the function will return
432 * the -errno.
434 int ipe_new_policyfs_node(struct ipe_policy *p)
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;
443 if (p->policyfs)
444 return 0;
446 policyfs = securityfs_create_dir(p->parsed->name, policy_root);
447 if (IS_ERR(policyfs))
448 return PTR_ERR(policyfs);
450 root = d_inode(policyfs);
452 for (i = 0; i < ARRAY_SIZE(policy_subdir); ++i) {
453 f = &policy_subdir[i];
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;
463 inode_lock(root);
464 p->policyfs = policyfs;
465 root->i_private = p;
466 inode_unlock(root);
468 return 0;
469 err:
470 securityfs_recursive_remove(policyfs);
471 return rc;