1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * Copyright (C) 2020-2024 Microsoft Corporati 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.655 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/polici 29 * @f: Supplies a file structure representing 30 * @data: Supplies a buffer passed to the writ 31 * @len: Supplies the length of @data. 32 * @offset: unused. 33 * 34 * @data will be populated with the pkcs7 blob 35 * on success. If the policy is unsigned (like 36 * will return -ENOENT. 37 * 38 * Return: 39 * * Length of buffer written - Success 40 * * %-ENOENT - Policy initi 41 */ 42 static ssize_t read_pkcs7(struct file *f, char 43 size_t len, loff_t * 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_par 50 51 inode_lock_shared(root); 52 p = (struct ipe_policy *)root->i_priva 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 64 65 out: 66 inode_unlock_shared(root); 67 68 return rc; 69 } 70 71 /** 72 * read_policy() - Read handler for "ipe/polic 73 * @f: Supplies a file structure representing 74 * @data: Supplies a buffer passed to the writ 75 * @len: Supplies the length of @data. 76 * @offset: unused. 77 * 78 * @data will be populated with the plain-text 79 * on success. 80 * 81 * Return: 82 * * Length of buffer written - Success 83 * * %-ENOENT - Policy initi 84 */ 85 static ssize_t read_policy(struct file *f, cha 86 size_t len, loff_t 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_par 93 94 inode_lock_shared(root); 95 p = (struct ipe_policy *)root->i_priva 96 if (!p) { 97 rc = -ENOENT; 98 goto out; 99 } 100 101 rc = simple_read_from_buffer(data, len 102 103 out: 104 inode_unlock_shared(root); 105 106 return rc; 107 } 108 109 /** 110 * read_name() - Read handler for "ipe/policie 111 * @f: Supplies a file structure representing 112 * @data: Supplies a buffer passed to the writ 113 * @len: Supplies the length of @data. 114 * @offset: unused. 115 * 116 * @data will be populated with the policy_nam 117 * 118 * Return: 119 * * Length of buffer written - Success 120 * * %-ENOENT - Policy initi 121 */ 122 static ssize_t read_name(struct file *f, char 123 size_t len, loff_t *o 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_par 130 131 inode_lock_shared(root); 132 p = (struct ipe_policy *)root->i_priva 133 if (!p) { 134 rc = -ENOENT; 135 goto out; 136 } 137 138 rc = simple_read_from_buffer(data, len 139 strlen(p- 140 141 out: 142 inode_unlock_shared(root); 143 144 return rc; 145 } 146 147 /** 148 * read_version() - Read handler for "ipe/poli 149 * @f: Supplies a file structure representing 150 * @data: Supplies a buffer passed to the writ 151 * @len: Supplies the length of @data. 152 * @offset: unused. 153 * 154 * @data will be populated with the version st 155 * 156 * Return: 157 * * Length of buffer written - Success 158 * * %-ENOENT - Policy initi 159 */ 160 static ssize_t read_version(struct file *f, ch 161 size_t len, loff_t 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_par 170 171 inode_lock_shared(root); 172 p = (struct ipe_policy *)root->i_priva 173 if (!p) { 174 rc = -ENOENT; 175 goto out; 176 } 177 178 strsize = scnprintf(buffer, ARRAY_SIZE 179 p->parsed->version 180 p->parsed->version 181 182 rc = simple_read_from_buffer(data, len 183 184 out: 185 inode_unlock_shared(root); 186 187 return rc; 188 } 189 190 /** 191 * setactive() - Write handler for "ipe/polici 192 * @f: Supplies a file structure representing 193 * @data: Supplies a buffer passed to the writ 194 * @len: Supplies the length of @data. 195 * @offset: unused. 196 * 197 * Return: 198 * * Length of buffer written - Success 199 * * %-EPERM - Insufficient 200 * * %-EINVAL - Invalid inpu 201 * * %-ENOENT - Policy initi 202 */ 203 static ssize_t setactive(struct file *f, const 204 size_t len, loff_t *o 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, 212 return -EPERM; 213 214 rc = kstrtobool_from_user(data, len, & 215 if (rc) 216 return rc; 217 218 if (!value) 219 return -EINVAL; 220 221 root = d_inode(f->f_path.dentry->d_par 222 inode_lock(root); 223 224 p = (struct ipe_policy *)root->i_priva 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/policie 239 * @f: Supplies a file structure representing 240 * @data: Supplies a buffer passed to the writ 241 * @len: Supplies the length of @data. 242 * @offset: unused. 243 * 244 * @data will be populated with the 1 or 0 dep 245 * corresponding policy is active. 246 * 247 * Return: 248 * * Length of buffer written - Success 249 * * %-ENOENT - Policy initi 250 */ 251 static ssize_t getactive(struct file *f, char 252 size_t len, loff_t *o 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_par 260 261 inode_lock_shared(root); 262 p = (struct ipe_policy *)root->i_priva 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_act 270 rc = simple_read_from_buffer(data, len 271 272 return rc; 273 } 274 275 /** 276 * update_policy() - Write handler for "ipe/po 277 * @f: Supplies a file structure representing 278 * @data: Supplies a buffer passed to the writ 279 * @len: Supplies the length of @data. 280 * @offset: unused. 281 * 282 * On success this updates the policy represen 283 * in-place. 284 * 285 * Return: Length of buffer written on success 286 * the function will return the -errno. 287 */ 288 static ssize_t update_policy(struct file *f, c 289 size_t len, loff_ 290 { 291 struct inode *root = NULL; 292 char *copy = NULL; 293 int rc = 0; 294 295 if (!file_ns_capable(f, &init_user_ns, 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_par 303 inode_lock(root); 304 rc = ipe_update_policy(root, NULL, 0, 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/p 316 * @f: Supplies a file structure representing 317 * @data: Supplies a buffer passed to the writ 318 * @len: Supplies the length of @data. 319 * @offset: unused. 320 * 321 * On success this deletes the policy represen 322 * 323 * Return: 324 * * Length of buffer written - Success 325 * * %-EPERM - Insufficient 326 * * %-EINVAL - Invalid inpu 327 * * %-ENOENT - Policy initi 328 */ 329 static ssize_t delete_policy(struct file *f, c 330 size_t len, loff_ 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, 339 return -EPERM; 340 341 rc = kstrtobool_from_user(data, len, & 342 if (rc) 343 return rc; 344 345 if (!value) 346 return -EINVAL; 347 348 root = d_inode(f->f_path.dentry->d_par 349 inode_lock(root); 350 p = (struct ipe_policy *)root->i_priva 351 if (!p) { 352 inode_unlock(root); 353 return -ENOENT; 354 } 355 356 mutex_lock(&ipe_policy_lock); 357 ap = rcu_dereference_protected(ipe_act 358 lockdep 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_fo 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_fop 392 .write = setactive, 393 .read = getactive, 394 }; 395 396 static const struct file_operations update_fop 397 .write = update_policy, 398 }; 399 400 static const struct file_operations delete_fop 401 .write = delete_policy, 402 }; 403 404 /** 405 * policy_subdir - files under a policy subdir 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 security 419 * @p: Supplies a pointer to the policy to del 420 */ 421 void ipe_del_policyfs_node(struct ipe_policy * 422 { 423 securityfs_recursive_remove(p->policyf 424 p->policyfs = NULL; 425 } 426 427 /** 428 * ipe_new_policyfs_node() - Create a security 429 * @p: Supplies a pointer to the policy to cre 430 * 431 * Return: %0 on success. If an error occurs, 432 * the -errno. 433 */ 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->pa 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_subd 453 f = &policy_subdir[i]; 454 455 d = securityfs_create_file(f-> 456 NUL 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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.