1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
6 #include <linux/namei.h>
7 #include <linux/types.h>
8 #include <linux/dcache.h>
9 #include <linux/security.h>
16 #define MAX_VERSION_SIZE ARRAY_SIZE("65535.65535.65535")
19 * ipefs_file - defines a file in securityfs.
24 const struct file_operations
*fops
;
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.
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.
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
;
49 root
= d_inode(f
->f_path
.dentry
->d_parent
);
51 inode_lock_shared(root
);
52 p
= (struct ipe_policy
*)root
->i_private
;
63 rc
= simple_read_from_buffer(data
, len
, offset
, p
->pkcs7
, p
->pkcs7len
);
66 inode_unlock_shared(root
);
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.
78 * @data will be populated with the plain-text version of the policy
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
;
92 root
= d_inode(f
->f_path
.dentry
->d_parent
);
94 inode_lock_shared(root
);
95 p
= (struct ipe_policy
*)root
->i_private
;
101 rc
= simple_read_from_buffer(data
, len
, offset
, p
->text
, p
->textlen
);
104 inode_unlock_shared(root
);
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.
116 * @data will be populated with the policy_name attribute on success.
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
;
129 root
= d_inode(f
->f_path
.dentry
->d_parent
);
131 inode_lock_shared(root
);
132 p
= (struct ipe_policy
*)root
->i_private
;
138 rc
= simple_read_from_buffer(data
, len
, offset
, p
->parsed
->name
,
139 strlen(p
->parsed
->name
));
142 inode_unlock_shared(root
);
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.
154 * @data will be populated with the version string on success.
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
;
169 root
= d_inode(f
->f_path
.dentry
->d_parent
);
171 inode_lock_shared(root
);
172 p
= (struct ipe_policy
*)root
->i_private
;
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
);
185 inode_unlock_shared(root
);
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.
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
;
211 if (!file_ns_capable(f
, &init_user_ns
, CAP_MAC_ADMIN
))
214 rc
= kstrtobool_from_user(data
, len
, &value
);
221 root
= d_inode(f
->f_path
.dentry
->d_parent
);
224 p
= (struct ipe_policy
*)root
->i_private
;
230 rc
= ipe_set_active_pol(p
);
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.
244 * @data will be populated with the 1 or 0 depending on if the
245 * corresponding policy is active.
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
;
259 root
= d_inode(f
->f_path
.dentry
->d_parent
);
261 inode_lock_shared(root
);
262 p
= (struct ipe_policy
*)root
->i_private
;
264 inode_unlock_shared(root
);
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);
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.
282 * On success this updates the policy represented by $name,
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
;
295 if (!file_ns_capable(f
, &init_user_ns
, CAP_MAC_ADMIN
))
298 copy
= memdup_user(data
, len
);
300 return PTR_ERR(copy
);
302 root
= d_inode(f
->f_path
.dentry
->d_parent
);
304 rc
= ipe_update_policy(root
, NULL
, 0, copy
, 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.
321 * On success this deletes the policy represented by $name.
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
;
338 if (!file_ns_capable(f
, &init_user_ns
, CAP_MAC_ADMIN
))
341 rc
= kstrtobool_from_user(data
, len
, &value
);
348 root
= d_inode(f
->f_path
.dentry
->d_parent
);
350 p
= (struct ipe_policy
*)root
->i_private
;
356 mutex_lock(&ipe_policy_lock
);
357 ap
= rcu_dereference_protected(ipe_active_policy
,
358 lockdep_is_held(&ipe_policy_lock
));
360 mutex_unlock(&ipe_policy_lock
);
364 mutex_unlock(&ipe_policy_lock
);
366 root
->i_private
= NULL
;
375 static const struct file_operations content_fops
= {
379 static const struct file_operations pkcs7_fops
= {
383 static const struct file_operations name_fops
= {
387 static const struct file_operations ver_fops
= {
388 .read
= read_version
,
391 static const struct file_operations active_fops
= {
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
);
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
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
;
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
,
464 p
->policyfs
= policyfs
;
470 securityfs_recursive_remove(policyfs
);