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