1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 23323eec9SMimi Zohar /* 33323eec9SMimi Zohar * Copyright (C) 2008 IBM Corporation 43323eec9SMimi Zohar * Author: Mimi Zohar <zohar@us.ibm.com> 53323eec9SMimi Zohar * 63323eec9SMimi Zohar * ima_policy.c 73323eec9SMimi Zohar * - initialize default measure policy rules 83323eec9SMimi Zohar */ 9876979c9SPaul Gortmaker #include <linux/init.h> 103323eec9SMimi Zohar #include <linux/list.h> 11cf222217SMimi Zohar #include <linux/fs.h> 123323eec9SMimi Zohar #include <linux/security.h> 133323eec9SMimi Zohar #include <linux/magic.h> 144af4662fSMimi Zohar #include <linux/parser.h> 155a0e3ad6STejun Heo #include <linux/slab.h> 1638d859f9SPetko Manolov #include <linux/rculist.h> 1785865c1fSDmitry Kasatkin #include <linux/genhd.h> 1880eae209SPetko Manolov #include <linux/seq_file.h> 1961917062SNayna Jain #include <linux/ima.h> 203323eec9SMimi Zohar 213323eec9SMimi Zohar #include "ima.h" 223323eec9SMimi Zohar 233323eec9SMimi Zohar /* flags definitions */ 243323eec9SMimi Zohar #define IMA_FUNC 0x0001 253323eec9SMimi Zohar #define IMA_MASK 0x0002 263323eec9SMimi Zohar #define IMA_FSMAGIC 0x0004 273323eec9SMimi Zohar #define IMA_UID 0x0008 2807f6a794SMimi Zohar #define IMA_FOWNER 0x0010 2985865c1fSDmitry Kasatkin #define IMA_FSUUID 0x0020 304351c294SMimi Zohar #define IMA_INMASK 0x0040 31139069efSMimi Zohar #define IMA_EUID 0x0080 320260643cSEric Richter #define IMA_PCR 0x0100 33f1b08bbcSMimi Zohar #define IMA_FSNAME 0x0200 343323eec9SMimi Zohar 352fe5d6deSMimi Zohar #define UNKNOWN 0 3645e2472eSDmitry Kasatkin #define MEASURE 0x0001 /* same as IMA_MEASURE */ 3745e2472eSDmitry Kasatkin #define DONT_MEASURE 0x0002 3845e2472eSDmitry Kasatkin #define APPRAISE 0x0004 /* same as IMA_APPRAISE */ 3945e2472eSDmitry Kasatkin #define DONT_APPRAISE 0x0008 40e7c568e0SPeter Moody #define AUDIT 0x0040 41da1b0029SMimi Zohar #define HASH 0x0100 42da1b0029SMimi Zohar #define DONT_HASH 0x0200 434af4662fSMimi Zohar 440260643cSEric Richter #define INVALID_PCR(a) (((a) < 0) || \ 450260643cSEric Richter (a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8)) 460260643cSEric Richter 47a756024eSRoberto Sassu int ima_policy_flag; 486ad6afa1SMimi Zohar static int temp_ima_appraise; 49ef96837bSMimi Zohar static int build_ima_appraise __ro_after_init; 50a756024eSRoberto Sassu 514af4662fSMimi Zohar #define MAX_LSM_RULES 6 524af4662fSMimi Zohar enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE, 534af4662fSMimi Zohar LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE 544af4662fSMimi Zohar }; 553323eec9SMimi Zohar 5624fd03c8SMimi Zohar enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB }; 5724fd03c8SMimi Zohar 58c52657d9SNayna Jain enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY }; 59c52657d9SNayna Jain 6007f6a794SMimi Zohar struct ima_rule_entry { 613323eec9SMimi Zohar struct list_head list; 622fe5d6deSMimi Zohar int action; 633323eec9SMimi Zohar unsigned int flags; 643323eec9SMimi Zohar enum ima_hooks func; 653323eec9SMimi Zohar int mask; 663323eec9SMimi Zohar unsigned long fsmagic; 67787d8c53SChristoph Hellwig uuid_t fsuuid; 688b94eea4SEric W. Biederman kuid_t uid; 6988265322SLinus Torvalds kuid_t fowner; 703dd0c8d0SMikhail Kurinnoi bool (*uid_op)(kuid_t, kuid_t); /* Handlers for operators */ 713dd0c8d0SMikhail Kurinnoi bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */ 720260643cSEric Richter int pcr; 734af4662fSMimi Zohar struct { 744af4662fSMimi Zohar void *rule; /* LSM file metadata specific */ 757163a993SMimi Zohar void *args_p; /* audit value */ 764af4662fSMimi Zohar int type; /* audit type */ 774af4662fSMimi Zohar } lsm[MAX_LSM_RULES]; 78f1b08bbcSMimi Zohar char *fsname; 7919453ce0SMatthew Garrett struct ima_template_desc *template; 803323eec9SMimi Zohar }; 813323eec9SMimi Zohar 825789ba3bSEric Paris /* 835789ba3bSEric Paris * Without LSM specific knowledge, the default policy can only be 8407f6a794SMimi Zohar * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner 854af4662fSMimi Zohar */ 865789ba3bSEric Paris 875789ba3bSEric Paris /* 885789ba3bSEric Paris * The minimum rule set to allow for full TCB coverage. Measures all files 895789ba3bSEric Paris * opened or mmap for exec and everything read by root. Dangerous because 905789ba3bSEric Paris * normal users can easily run the machine out of memory simply building 915789ba3bSEric Paris * and running executables. 925789ba3bSEric Paris */ 93bad4417bSJames Morris static struct ima_rule_entry dont_measure_rules[] __ro_after_init = { 9475834fc3SEric Paris {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 953323eec9SMimi Zohar {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, 963323eec9SMimi Zohar {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, 973323eec9SMimi Zohar {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC}, 988445d64dSDmitry Kasatkin {.action = DONT_MEASURE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 998445d64dSDmitry Kasatkin {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, 10075834fc3SEric Paris {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, 10175834fc3SEric Paris {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, 1021c070b18SMartin Townsend {.action = DONT_MEASURE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC}, 1036438de9fSRoberto Sassu {.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC, 1046438de9fSRoberto Sassu .flags = IMA_FSMAGIC}, 10582e3bb4dSLaura Abbott {.action = DONT_MEASURE, .fsmagic = CGROUP2_SUPER_MAGIC, 10682e3bb4dSLaura Abbott .flags = IMA_FSMAGIC}, 107060190fbSMimi Zohar {.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, 108060190fbSMimi Zohar {.action = DONT_MEASURE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC} 10924fd03c8SMimi Zohar }; 11024fd03c8SMimi Zohar 111bad4417bSJames Morris static struct ima_rule_entry original_measurement_rules[] __ro_after_init = { 11216cac49fSMimi Zohar {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, 1133323eec9SMimi Zohar .flags = IMA_FUNC | IMA_MASK}, 1143323eec9SMimi Zohar {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, 1153323eec9SMimi Zohar .flags = IMA_FUNC | IMA_MASK}, 11624fd03c8SMimi Zohar {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, 1173dd0c8d0SMikhail Kurinnoi .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, 1183dd0c8d0SMikhail Kurinnoi .flags = IMA_FUNC | IMA_MASK | IMA_UID}, 11924fd03c8SMimi Zohar {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, 12024fd03c8SMimi Zohar {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, 12124fd03c8SMimi Zohar }; 12224fd03c8SMimi Zohar 123bad4417bSJames Morris static struct ima_rule_entry default_measurement_rules[] __ro_after_init = { 12424fd03c8SMimi Zohar {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC, 12524fd03c8SMimi Zohar .flags = IMA_FUNC | IMA_MASK}, 12624fd03c8SMimi Zohar {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC, 12724fd03c8SMimi Zohar .flags = IMA_FUNC | IMA_MASK}, 12824fd03c8SMimi Zohar {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, 1293dd0c8d0SMikhail Kurinnoi .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, 1303dd0c8d0SMikhail Kurinnoi .flags = IMA_FUNC | IMA_INMASK | IMA_EUID}, 13124fd03c8SMimi Zohar {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, 1323dd0c8d0SMikhail Kurinnoi .uid = GLOBAL_ROOT_UID, .uid_op = &uid_eq, 1333dd0c8d0SMikhail Kurinnoi .flags = IMA_FUNC | IMA_INMASK | IMA_UID}, 134fdf90729SMimi Zohar {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, 1355a9196d7SMimi Zohar {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, 13619f8a847SMimi Zohar {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC}, 1373323eec9SMimi Zohar }; 1383323eec9SMimi Zohar 139bad4417bSJames Morris static struct ima_rule_entry default_appraise_rules[] __ro_after_init = { 14007f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 14107f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC}, 14207f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC}, 14307f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC}, 14407f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC}, 14507f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 14607f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC}, 14707f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC}, 14807f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, 1491c070b18SMartin Townsend {.action = DONT_APPRAISE, .fsmagic = SMACK_MAGIC, .flags = IMA_FSMAGIC}, 150cd025f7fSMimi Zohar {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, 151060190fbSMimi Zohar {.action = DONT_APPRAISE, .fsmagic = EFIVARFS_MAGIC, .flags = IMA_FSMAGIC}, 15207f6a794SMimi Zohar {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 15382e3bb4dSLaura Abbott {.action = DONT_APPRAISE, .fsmagic = CGROUP2_SUPER_MAGIC, .flags = IMA_FSMAGIC}, 15495ee08faSMimi Zohar #ifdef CONFIG_IMA_WRITE_POLICY 15595ee08faSMimi Zohar {.action = APPRAISE, .func = POLICY_CHECK, 15695ee08faSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 15795ee08faSMimi Zohar #endif 158c57782c1SDmitry Kasatkin #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT 1593dd0c8d0SMikhail Kurinnoi {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, 1603dd0c8d0SMikhail Kurinnoi .flags = IMA_FOWNER}, 161c57782c1SDmitry Kasatkin #else 162c57782c1SDmitry Kasatkin /* force signature */ 1633dd0c8d0SMikhail Kurinnoi {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .fowner_op = &uid_eq, 164c57782c1SDmitry Kasatkin .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED}, 165c57782c1SDmitry Kasatkin #endif 16607f6a794SMimi Zohar }; 1673323eec9SMimi Zohar 168ef96837bSMimi Zohar static struct ima_rule_entry build_appraise_rules[] __ro_after_init = { 169ef96837bSMimi Zohar #ifdef CONFIG_IMA_APPRAISE_REQUIRE_MODULE_SIGS 170ef96837bSMimi Zohar {.action = APPRAISE, .func = MODULE_CHECK, 171ef96837bSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 172ef96837bSMimi Zohar #endif 173ef96837bSMimi Zohar #ifdef CONFIG_IMA_APPRAISE_REQUIRE_FIRMWARE_SIGS 174ef96837bSMimi Zohar {.action = APPRAISE, .func = FIRMWARE_CHECK, 175ef96837bSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 176ef96837bSMimi Zohar #endif 177ef96837bSMimi Zohar #ifdef CONFIG_IMA_APPRAISE_REQUIRE_KEXEC_SIGS 178ef96837bSMimi Zohar {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK, 179ef96837bSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 180ef96837bSMimi Zohar #endif 181ef96837bSMimi Zohar #ifdef CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS 182ef96837bSMimi Zohar {.action = APPRAISE, .func = POLICY_CHECK, 183ef96837bSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 184ef96837bSMimi Zohar #endif 185ef96837bSMimi Zohar }; 186ef96837bSMimi Zohar 187503ceaefSMimi Zohar static struct ima_rule_entry secure_boot_rules[] __ro_after_init = { 188503ceaefSMimi Zohar {.action = APPRAISE, .func = MODULE_CHECK, 189503ceaefSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 190503ceaefSMimi Zohar {.action = APPRAISE, .func = FIRMWARE_CHECK, 191503ceaefSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 192503ceaefSMimi Zohar {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK, 193503ceaefSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 194503ceaefSMimi Zohar {.action = APPRAISE, .func = POLICY_CHECK, 195503ceaefSMimi Zohar .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 196503ceaefSMimi Zohar }; 197503ceaefSMimi Zohar 19861917062SNayna Jain /* An array of architecture specific rules */ 19968f25290SYueHaibing static struct ima_rule_entry *arch_policy_entry __ro_after_init; 20061917062SNayna Jain 20107f6a794SMimi Zohar static LIST_HEAD(ima_default_rules); 20207f6a794SMimi Zohar static LIST_HEAD(ima_policy_rules); 20338d859f9SPetko Manolov static LIST_HEAD(ima_temp_rules); 20407f6a794SMimi Zohar static struct list_head *ima_rules; 20507f6a794SMimi Zohar 20624fd03c8SMimi Zohar static int ima_policy __initdata; 20738d859f9SPetko Manolov 20807f6a794SMimi Zohar static int __init default_measure_policy_setup(char *str) 2095789ba3bSEric Paris { 21024fd03c8SMimi Zohar if (ima_policy) 21124fd03c8SMimi Zohar return 1; 21224fd03c8SMimi Zohar 21324fd03c8SMimi Zohar ima_policy = ORIGINAL_TCB; 2145789ba3bSEric Paris return 1; 2155789ba3bSEric Paris } 21607f6a794SMimi Zohar __setup("ima_tcb", default_measure_policy_setup); 21707f6a794SMimi Zohar 21833ce9549SMimi Zohar static bool ima_use_appraise_tcb __initdata; 219503ceaefSMimi Zohar static bool ima_use_secure_boot __initdata; 2209e67028eSMimi Zohar static bool ima_fail_unverifiable_sigs __ro_after_init; 22124fd03c8SMimi Zohar static int __init policy_setup(char *str) 22224fd03c8SMimi Zohar { 22333ce9549SMimi Zohar char *p; 22424fd03c8SMimi Zohar 22533ce9549SMimi Zohar while ((p = strsep(&str, " |\n")) != NULL) { 22633ce9549SMimi Zohar if (*p == ' ') 22733ce9549SMimi Zohar continue; 22833ce9549SMimi Zohar if ((strcmp(p, "tcb") == 0) && !ima_policy) 22924fd03c8SMimi Zohar ima_policy = DEFAULT_TCB; 23033ce9549SMimi Zohar else if (strcmp(p, "appraise_tcb") == 0) 23139adb925SThomas Meyer ima_use_appraise_tcb = true; 232503ceaefSMimi Zohar else if (strcmp(p, "secure_boot") == 0) 23339adb925SThomas Meyer ima_use_secure_boot = true; 2349e67028eSMimi Zohar else if (strcmp(p, "fail_securely") == 0) 2359e67028eSMimi Zohar ima_fail_unverifiable_sigs = true; 23633ce9549SMimi Zohar } 23724fd03c8SMimi Zohar 23824fd03c8SMimi Zohar return 1; 23924fd03c8SMimi Zohar } 24024fd03c8SMimi Zohar __setup("ima_policy=", policy_setup); 24124fd03c8SMimi Zohar 24207f6a794SMimi Zohar static int __init default_appraise_policy_setup(char *str) 24307f6a794SMimi Zohar { 24439adb925SThomas Meyer ima_use_appraise_tcb = true; 24507f6a794SMimi Zohar return 1; 24607f6a794SMimi Zohar } 24707f6a794SMimi Zohar __setup("ima_appraise_tcb", default_appraise_policy_setup); 2485789ba3bSEric Paris 249b1694245SJanne Karhunen static void ima_lsm_free_rule(struct ima_rule_entry *entry) 2507163a993SMimi Zohar { 2517163a993SMimi Zohar int i; 2527163a993SMimi Zohar 253b1694245SJanne Karhunen for (i = 0; i < MAX_LSM_RULES; i++) { 254b1694245SJanne Karhunen kfree(entry->lsm[i].rule); 255b1694245SJanne Karhunen kfree(entry->lsm[i].args_p); 256b1694245SJanne Karhunen } 257b1694245SJanne Karhunen kfree(entry); 258b1694245SJanne Karhunen } 259b1694245SJanne Karhunen 260b1694245SJanne Karhunen static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) 261b1694245SJanne Karhunen { 262b1694245SJanne Karhunen struct ima_rule_entry *nentry; 263b1694245SJanne Karhunen int i, result; 264b1694245SJanne Karhunen 265b1694245SJanne Karhunen nentry = kmalloc(sizeof(*nentry), GFP_KERNEL); 266b1694245SJanne Karhunen if (!nentry) 267b1694245SJanne Karhunen return NULL; 268b1694245SJanne Karhunen 269b1694245SJanne Karhunen /* 270b1694245SJanne Karhunen * Immutable elements are copied over as pointers and data; only 271b1694245SJanne Karhunen * lsm rules can change 272b1694245SJanne Karhunen */ 273b1694245SJanne Karhunen memcpy(nentry, entry, sizeof(*nentry)); 274b1694245SJanne Karhunen memset(nentry->lsm, 0, FIELD_SIZEOF(struct ima_rule_entry, lsm)); 275b1694245SJanne Karhunen 2767163a993SMimi Zohar for (i = 0; i < MAX_LSM_RULES; i++) { 2777163a993SMimi Zohar if (!entry->lsm[i].rule) 2787163a993SMimi Zohar continue; 279b1694245SJanne Karhunen 280b1694245SJanne Karhunen nentry->lsm[i].type = entry->lsm[i].type; 281b1694245SJanne Karhunen nentry->lsm[i].args_p = kstrdup(entry->lsm[i].args_p, 282b1694245SJanne Karhunen GFP_KERNEL); 283b1694245SJanne Karhunen if (!nentry->lsm[i].args_p) 284b1694245SJanne Karhunen goto out_err; 285b1694245SJanne Karhunen 286b1694245SJanne Karhunen result = security_filter_rule_init(nentry->lsm[i].type, 2877163a993SMimi Zohar Audit_equal, 288b1694245SJanne Karhunen nentry->lsm[i].args_p, 289b1694245SJanne Karhunen &nentry->lsm[i].rule); 290b1694245SJanne Karhunen if (result == -EINVAL) 291b1694245SJanne Karhunen pr_warn("ima: rule for LSM \'%d\' is undefined\n", 292b1694245SJanne Karhunen entry->lsm[i].type); 293b1694245SJanne Karhunen } 294b1694245SJanne Karhunen return nentry; 295b1694245SJanne Karhunen 296b1694245SJanne Karhunen out_err: 297b1694245SJanne Karhunen ima_lsm_free_rule(nentry); 298b1694245SJanne Karhunen return NULL; 299b1694245SJanne Karhunen } 300b1694245SJanne Karhunen 301b1694245SJanne Karhunen static int ima_lsm_update_rule(struct ima_rule_entry *entry) 302b1694245SJanne Karhunen { 303b1694245SJanne Karhunen struct ima_rule_entry *nentry; 304b1694245SJanne Karhunen 305b1694245SJanne Karhunen nentry = ima_lsm_copy_rule(entry); 306b1694245SJanne Karhunen if (!nentry) 307b1694245SJanne Karhunen return -ENOMEM; 308b1694245SJanne Karhunen 309b1694245SJanne Karhunen list_replace_rcu(&entry->list, &nentry->list); 310b1694245SJanne Karhunen synchronize_rcu(); 311b1694245SJanne Karhunen ima_lsm_free_rule(entry); 312b1694245SJanne Karhunen 313b1694245SJanne Karhunen return 0; 314b1694245SJanne Karhunen } 315b1694245SJanne Karhunen 316b1694245SJanne Karhunen /* 317b1694245SJanne Karhunen * The LSM policy can be reloaded, leaving the IMA LSM based rules referring 318b1694245SJanne Karhunen * to the old, stale LSM policy. Update the IMA LSM based rules to reflect 319b1694245SJanne Karhunen * the reloaded LSM policy. 320b1694245SJanne Karhunen */ 321b1694245SJanne Karhunen static void ima_lsm_update_rules(void) 322b1694245SJanne Karhunen { 323b1694245SJanne Karhunen struct ima_rule_entry *entry, *e; 324b1694245SJanne Karhunen int i, result, needs_update; 325b1694245SJanne Karhunen 326b1694245SJanne Karhunen list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { 327b1694245SJanne Karhunen needs_update = 0; 328b1694245SJanne Karhunen for (i = 0; i < MAX_LSM_RULES; i++) { 329b1694245SJanne Karhunen if (entry->lsm[i].rule) { 330b1694245SJanne Karhunen needs_update = 1; 331b1694245SJanne Karhunen break; 3327163a993SMimi Zohar } 3337163a993SMimi Zohar } 334b1694245SJanne Karhunen if (!needs_update) 335b1694245SJanne Karhunen continue; 336b1694245SJanne Karhunen 337b1694245SJanne Karhunen result = ima_lsm_update_rule(entry); 338b1694245SJanne Karhunen if (result) { 339b1694245SJanne Karhunen pr_err("ima: lsm rule update error %d\n", 340b1694245SJanne Karhunen result); 341b1694245SJanne Karhunen return; 342b1694245SJanne Karhunen } 343b1694245SJanne Karhunen } 344b1694245SJanne Karhunen } 345b1694245SJanne Karhunen 346b1694245SJanne Karhunen int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, 347b1694245SJanne Karhunen void *lsm_data) 348b1694245SJanne Karhunen { 349b1694245SJanne Karhunen if (event != LSM_POLICY_CHANGE) 350b1694245SJanne Karhunen return NOTIFY_DONE; 351b1694245SJanne Karhunen 352b1694245SJanne Karhunen ima_lsm_update_rules(); 353b1694245SJanne Karhunen return NOTIFY_OK; 3547163a993SMimi Zohar } 3557163a993SMimi Zohar 3563323eec9SMimi Zohar /** 3573323eec9SMimi Zohar * ima_match_rules - determine whether an inode matches the measure rule. 3583323eec9SMimi Zohar * @rule: a pointer to a rule 3593323eec9SMimi Zohar * @inode: a pointer to an inode 360d906c10dSMatthew Garrett * @cred: a pointer to a credentials structure for user validation 361d906c10dSMatthew Garrett * @secid: the secid of the task to be validated 3623323eec9SMimi Zohar * @func: LIM hook identifier 3633323eec9SMimi Zohar * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) 3643323eec9SMimi Zohar * 3653323eec9SMimi Zohar * Returns true on rule match, false on failure. 3663323eec9SMimi Zohar */ 3674ad87a3dSMimi Zohar static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, 368d906c10dSMatthew Garrett const struct cred *cred, u32 secid, 3694ad87a3dSMimi Zohar enum ima_hooks func, int mask) 3703323eec9SMimi Zohar { 3714af4662fSMimi Zohar int i; 3723323eec9SMimi Zohar 373b0935123SPrakhar Srivastava if (func == KEXEC_CMDLINE) { 374b0935123SPrakhar Srivastava if ((rule->flags & IMA_FUNC) && (rule->func == func)) 375b0935123SPrakhar Srivastava return true; 376b0935123SPrakhar Srivastava return false; 377b0935123SPrakhar Srivastava } 37809b1148eSDmitry Kasatkin if ((rule->flags & IMA_FUNC) && 37909b1148eSDmitry Kasatkin (rule->func != func && func != POST_SETATTR)) 3803323eec9SMimi Zohar return false; 38109b1148eSDmitry Kasatkin if ((rule->flags & IMA_MASK) && 38209b1148eSDmitry Kasatkin (rule->mask != mask && func != POST_SETATTR)) 3833323eec9SMimi Zohar return false; 3844351c294SMimi Zohar if ((rule->flags & IMA_INMASK) && 3854351c294SMimi Zohar (!(rule->mask & mask) && func != POST_SETATTR)) 3864351c294SMimi Zohar return false; 3873323eec9SMimi Zohar if ((rule->flags & IMA_FSMAGIC) 3883323eec9SMimi Zohar && rule->fsmagic != inode->i_sb->s_magic) 3893323eec9SMimi Zohar return false; 390f1b08bbcSMimi Zohar if ((rule->flags & IMA_FSNAME) 391f1b08bbcSMimi Zohar && strcmp(rule->fsname, inode->i_sb->s_type->name)) 392f1b08bbcSMimi Zohar return false; 39385865c1fSDmitry Kasatkin if ((rule->flags & IMA_FSUUID) && 39485787090SChristoph Hellwig !uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid)) 39585865c1fSDmitry Kasatkin return false; 3963dd0c8d0SMikhail Kurinnoi if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid)) 3973323eec9SMimi Zohar return false; 398139069efSMimi Zohar if (rule->flags & IMA_EUID) { 399139069efSMimi Zohar if (has_capability_noaudit(current, CAP_SETUID)) { 4003dd0c8d0SMikhail Kurinnoi if (!rule->uid_op(cred->euid, rule->uid) 4013dd0c8d0SMikhail Kurinnoi && !rule->uid_op(cred->suid, rule->uid) 4023dd0c8d0SMikhail Kurinnoi && !rule->uid_op(cred->uid, rule->uid)) 403139069efSMimi Zohar return false; 4043dd0c8d0SMikhail Kurinnoi } else if (!rule->uid_op(cred->euid, rule->uid)) 405139069efSMimi Zohar return false; 406139069efSMimi Zohar } 407139069efSMimi Zohar 4083dd0c8d0SMikhail Kurinnoi if ((rule->flags & IMA_FOWNER) && 4093dd0c8d0SMikhail Kurinnoi !rule->fowner_op(inode->i_uid, rule->fowner)) 41007f6a794SMimi Zohar return false; 4114af4662fSMimi Zohar for (i = 0; i < MAX_LSM_RULES; i++) { 41253fc0e22SMimi Zohar int rc = 0; 413d906c10dSMatthew Garrett u32 osid; 4144af4662fSMimi Zohar 4154af4662fSMimi Zohar if (!rule->lsm[i].rule) 4164af4662fSMimi Zohar continue; 417b1694245SJanne Karhunen 4184af4662fSMimi Zohar switch (i) { 4194af4662fSMimi Zohar case LSM_OBJ_USER: 4204af4662fSMimi Zohar case LSM_OBJ_ROLE: 4214af4662fSMimi Zohar case LSM_OBJ_TYPE: 4224af4662fSMimi Zohar security_inode_getsecid(inode, &osid); 4234af4662fSMimi Zohar rc = security_filter_rule_match(osid, 4244af4662fSMimi Zohar rule->lsm[i].type, 42553fc0e22SMimi Zohar Audit_equal, 42690462a5bSRichard Guy Briggs rule->lsm[i].rule); 4274af4662fSMimi Zohar break; 4284af4662fSMimi Zohar case LSM_SUBJ_USER: 4294af4662fSMimi Zohar case LSM_SUBJ_ROLE: 4304af4662fSMimi Zohar case LSM_SUBJ_TYPE: 431d906c10dSMatthew Garrett rc = security_filter_rule_match(secid, 4324af4662fSMimi Zohar rule->lsm[i].type, 43353fc0e22SMimi Zohar Audit_equal, 43490462a5bSRichard Guy Briggs rule->lsm[i].rule); 4354af4662fSMimi Zohar default: 4364af4662fSMimi Zohar break; 4374af4662fSMimi Zohar } 4384af4662fSMimi Zohar if (!rc) 4394af4662fSMimi Zohar return false; 4404af4662fSMimi Zohar } 4413323eec9SMimi Zohar return true; 4423323eec9SMimi Zohar } 4433323eec9SMimi Zohar 444d79d72e0SMimi Zohar /* 445d79d72e0SMimi Zohar * In addition to knowing that we need to appraise the file in general, 4465a73fcfaSMimi Zohar * we need to differentiate between calling hooks, for hook specific rules. 447d79d72e0SMimi Zohar */ 4484ad87a3dSMimi Zohar static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) 449d79d72e0SMimi Zohar { 4505a73fcfaSMimi Zohar if (!(rule->flags & IMA_FUNC)) 4515a73fcfaSMimi Zohar return IMA_FILE_APPRAISE; 4525a73fcfaSMimi Zohar 453d79d72e0SMimi Zohar switch (func) { 454d79d72e0SMimi Zohar case MMAP_CHECK: 455d79d72e0SMimi Zohar return IMA_MMAP_APPRAISE; 456d79d72e0SMimi Zohar case BPRM_CHECK: 457d79d72e0SMimi Zohar return IMA_BPRM_APPRAISE; 458d906c10dSMatthew Garrett case CREDS_CHECK: 459d906c10dSMatthew Garrett return IMA_CREDS_APPRAISE; 460d79d72e0SMimi Zohar case FILE_CHECK: 461c6af8efeSMimi Zohar case POST_SETATTR: 462d79d72e0SMimi Zohar return IMA_FILE_APPRAISE; 463c6af8efeSMimi Zohar case MODULE_CHECK ... MAX_CHECK - 1: 464c6af8efeSMimi Zohar default: 465c6af8efeSMimi Zohar return IMA_READ_APPRAISE; 466d79d72e0SMimi Zohar } 467d79d72e0SMimi Zohar } 468d79d72e0SMimi Zohar 4693323eec9SMimi Zohar /** 4703323eec9SMimi Zohar * ima_match_policy - decision based on LSM and other conditions 4713323eec9SMimi Zohar * @inode: pointer to an inode for which the policy decision is being made 472d906c10dSMatthew Garrett * @cred: pointer to a credentials structure for which the policy decision is 473d906c10dSMatthew Garrett * being made 474d906c10dSMatthew Garrett * @secid: LSM secid of the task to be validated 4753323eec9SMimi Zohar * @func: IMA hook identifier 4763323eec9SMimi Zohar * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) 477725de7faSEric Richter * @pcr: set the pcr to extend 47819453ce0SMatthew Garrett * @template_desc: the template that should be used for this rule 4793323eec9SMimi Zohar * 4803323eec9SMimi Zohar * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) 4813323eec9SMimi Zohar * conditions. 4823323eec9SMimi Zohar * 48338d859f9SPetko Manolov * Since the IMA policy may be updated multiple times we need to lock the 48438d859f9SPetko Manolov * list when walking it. Reads are many orders of magnitude more numerous 48538d859f9SPetko Manolov * than writes so ima_match_policy() is classical RCU candidate. 4863323eec9SMimi Zohar */ 487d906c10dSMatthew Garrett int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, 48819453ce0SMatthew Garrett enum ima_hooks func, int mask, int flags, int *pcr, 48919453ce0SMatthew Garrett struct ima_template_desc **template_desc) 4903323eec9SMimi Zohar { 49107f6a794SMimi Zohar struct ima_rule_entry *entry; 4922fe5d6deSMimi Zohar int action = 0, actmask = flags | (flags << 1); 4933323eec9SMimi Zohar 494*b36f281fSMimi Zohar if (template_desc) 495*b36f281fSMimi Zohar *template_desc = ima_template_desc_current(); 496*b36f281fSMimi Zohar 49738d859f9SPetko Manolov rcu_read_lock(); 49838d859f9SPetko Manolov list_for_each_entry_rcu(entry, ima_rules, list) { 4993323eec9SMimi Zohar 5002fe5d6deSMimi Zohar if (!(entry->action & actmask)) 5012fe5d6deSMimi Zohar continue; 5022fe5d6deSMimi Zohar 503d906c10dSMatthew Garrett if (!ima_match_rules(entry, inode, cred, secid, func, mask)) 5042fe5d6deSMimi Zohar continue; 5052fe5d6deSMimi Zohar 5060e5a247cSDmitry Kasatkin action |= entry->flags & IMA_ACTION_FLAGS; 5070e5a247cSDmitry Kasatkin 50845e2472eSDmitry Kasatkin action |= entry->action & IMA_DO_MASK; 509da1b0029SMimi Zohar if (entry->action & IMA_APPRAISE) { 5105a73fcfaSMimi Zohar action |= get_subaction(entry, func); 511a9a4935dSMimi Zohar action &= ~IMA_HASH; 5129e67028eSMimi Zohar if (ima_fail_unverifiable_sigs) 5139e67028eSMimi Zohar action |= IMA_FAIL_UNVERIFIABLE_SIGS; 514da1b0029SMimi Zohar } 515d79d72e0SMimi Zohar 516*b36f281fSMimi Zohar 51745e2472eSDmitry Kasatkin if (entry->action & IMA_DO_MASK) 51845e2472eSDmitry Kasatkin actmask &= ~(entry->action | entry->action << 1); 51945e2472eSDmitry Kasatkin else 52045e2472eSDmitry Kasatkin actmask &= ~(entry->action | entry->action >> 1); 52145e2472eSDmitry Kasatkin 522725de7faSEric Richter if ((pcr) && (entry->flags & IMA_PCR)) 523725de7faSEric Richter *pcr = entry->pcr; 524725de7faSEric Richter 52519453ce0SMatthew Garrett if (template_desc && entry->template) 52619453ce0SMatthew Garrett *template_desc = entry->template; 52719453ce0SMatthew Garrett 5282fe5d6deSMimi Zohar if (!actmask) 5292fe5d6deSMimi Zohar break; 5303323eec9SMimi Zohar } 53138d859f9SPetko Manolov rcu_read_unlock(); 5322fe5d6deSMimi Zohar 5332fe5d6deSMimi Zohar return action; 5343323eec9SMimi Zohar } 5353323eec9SMimi Zohar 536a756024eSRoberto Sassu /* 537a756024eSRoberto Sassu * Initialize the ima_policy_flag variable based on the currently 538a756024eSRoberto Sassu * loaded policy. Based on this flag, the decision to short circuit 539a756024eSRoberto Sassu * out of a function or not call the function in the first place 540a756024eSRoberto Sassu * can be made earlier. 541a756024eSRoberto Sassu */ 542a756024eSRoberto Sassu void ima_update_policy_flag(void) 543a756024eSRoberto Sassu { 544a756024eSRoberto Sassu struct ima_rule_entry *entry; 545a756024eSRoberto Sassu 546a756024eSRoberto Sassu list_for_each_entry(entry, ima_rules, list) { 547a756024eSRoberto Sassu if (entry->action & IMA_DO_MASK) 548a756024eSRoberto Sassu ima_policy_flag |= entry->action; 549a756024eSRoberto Sassu } 550a756024eSRoberto Sassu 551ef96837bSMimi Zohar ima_appraise |= (build_ima_appraise | temp_ima_appraise); 552a756024eSRoberto Sassu if (!ima_appraise) 553a756024eSRoberto Sassu ima_policy_flag &= ~IMA_APPRAISE; 554a756024eSRoberto Sassu } 555a756024eSRoberto Sassu 5566f0911a6SMimi Zohar static int ima_appraise_flag(enum ima_hooks func) 5576f0911a6SMimi Zohar { 5586f0911a6SMimi Zohar if (func == MODULE_CHECK) 5596f0911a6SMimi Zohar return IMA_APPRAISE_MODULES; 5606f0911a6SMimi Zohar else if (func == FIRMWARE_CHECK) 5616f0911a6SMimi Zohar return IMA_APPRAISE_FIRMWARE; 5626f0911a6SMimi Zohar else if (func == POLICY_CHECK) 5636f0911a6SMimi Zohar return IMA_APPRAISE_POLICY; 56416c267aaSMimi Zohar else if (func == KEXEC_KERNEL_CHECK) 56516c267aaSMimi Zohar return IMA_APPRAISE_KEXEC; 5666f0911a6SMimi Zohar return 0; 5676f0911a6SMimi Zohar } 5686f0911a6SMimi Zohar 569c52657d9SNayna Jain static void add_rules(struct ima_rule_entry *entries, int count, 570c52657d9SNayna Jain enum policy_rule_list policy_rule) 571c52657d9SNayna Jain { 572c52657d9SNayna Jain int i = 0; 573c52657d9SNayna Jain 574c52657d9SNayna Jain for (i = 0; i < count; i++) { 575c52657d9SNayna Jain struct ima_rule_entry *entry; 576c52657d9SNayna Jain 577c52657d9SNayna Jain if (policy_rule & IMA_DEFAULT_POLICY) 578c52657d9SNayna Jain list_add_tail(&entries[i].list, &ima_default_rules); 579c52657d9SNayna Jain 580c52657d9SNayna Jain if (policy_rule & IMA_CUSTOM_POLICY) { 581c52657d9SNayna Jain entry = kmemdup(&entries[i], sizeof(*entry), 582c52657d9SNayna Jain GFP_KERNEL); 583c52657d9SNayna Jain if (!entry) 584c52657d9SNayna Jain continue; 585c52657d9SNayna Jain 586c52657d9SNayna Jain list_add_tail(&entry->list, &ima_policy_rules); 587c52657d9SNayna Jain } 588f4001947SPetr Vorel if (entries[i].action == APPRAISE) { 589c52657d9SNayna Jain temp_ima_appraise |= ima_appraise_flag(entries[i].func); 590c52657d9SNayna Jain if (entries[i].func == POLICY_CHECK) 591c52657d9SNayna Jain temp_ima_appraise |= IMA_APPRAISE_POLICY; 592c52657d9SNayna Jain } 593c52657d9SNayna Jain } 594f4001947SPetr Vorel } 595c52657d9SNayna Jain 59661917062SNayna Jain static int ima_parse_rule(char *rule, struct ima_rule_entry *entry); 59761917062SNayna Jain 59861917062SNayna Jain static int __init ima_init_arch_policy(void) 59961917062SNayna Jain { 60061917062SNayna Jain const char * const *arch_rules; 60161917062SNayna Jain const char * const *rules; 60261917062SNayna Jain int arch_entries = 0; 60361917062SNayna Jain int i = 0; 60461917062SNayna Jain 60561917062SNayna Jain arch_rules = arch_get_ima_policy(); 60661917062SNayna Jain if (!arch_rules) 60761917062SNayna Jain return arch_entries; 60861917062SNayna Jain 60961917062SNayna Jain /* Get number of rules */ 61061917062SNayna Jain for (rules = arch_rules; *rules != NULL; rules++) 61161917062SNayna Jain arch_entries++; 61261917062SNayna Jain 61361917062SNayna Jain arch_policy_entry = kcalloc(arch_entries + 1, 61461917062SNayna Jain sizeof(*arch_policy_entry), GFP_KERNEL); 61561917062SNayna Jain if (!arch_policy_entry) 61661917062SNayna Jain return 0; 61761917062SNayna Jain 61861917062SNayna Jain /* Convert each policy string rules to struct ima_rule_entry format */ 61961917062SNayna Jain for (rules = arch_rules, i = 0; *rules != NULL; rules++) { 62061917062SNayna Jain char rule[255]; 62161917062SNayna Jain int result; 62261917062SNayna Jain 62361917062SNayna Jain result = strlcpy(rule, *rules, sizeof(rule)); 62461917062SNayna Jain 62561917062SNayna Jain INIT_LIST_HEAD(&arch_policy_entry[i].list); 62661917062SNayna Jain result = ima_parse_rule(rule, &arch_policy_entry[i]); 62761917062SNayna Jain if (result) { 62861917062SNayna Jain pr_warn("Skipping unknown architecture policy rule: %s\n", 62961917062SNayna Jain rule); 63061917062SNayna Jain memset(&arch_policy_entry[i], 0, 63161917062SNayna Jain sizeof(*arch_policy_entry)); 63261917062SNayna Jain continue; 63361917062SNayna Jain } 63461917062SNayna Jain i++; 63561917062SNayna Jain } 63661917062SNayna Jain return i; 63761917062SNayna Jain } 63861917062SNayna Jain 6393323eec9SMimi Zohar /** 6403323eec9SMimi Zohar * ima_init_policy - initialize the default measure rules. 6413323eec9SMimi Zohar * 64207f6a794SMimi Zohar * ima_rules points to either the ima_default_rules or the 64307f6a794SMimi Zohar * the new ima_policy_rules. 6443323eec9SMimi Zohar */ 645932995f0SEric Paris void __init ima_init_policy(void) 6463323eec9SMimi Zohar { 64761917062SNayna Jain int build_appraise_entries, arch_entries; 6483323eec9SMimi Zohar 649c52657d9SNayna Jain /* if !ima_policy, we load NO default rules */ 650c52657d9SNayna Jain if (ima_policy) 651c52657d9SNayna Jain add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules), 652c52657d9SNayna Jain IMA_DEFAULT_POLICY); 65324fd03c8SMimi Zohar 65424fd03c8SMimi Zohar switch (ima_policy) { 65524fd03c8SMimi Zohar case ORIGINAL_TCB: 656c52657d9SNayna Jain add_rules(original_measurement_rules, 657c52657d9SNayna Jain ARRAY_SIZE(original_measurement_rules), 658c52657d9SNayna Jain IMA_DEFAULT_POLICY); 65924fd03c8SMimi Zohar break; 66024fd03c8SMimi Zohar case DEFAULT_TCB: 661c52657d9SNayna Jain add_rules(default_measurement_rules, 662c52657d9SNayna Jain ARRAY_SIZE(default_measurement_rules), 663c52657d9SNayna Jain IMA_DEFAULT_POLICY); 66424fd03c8SMimi Zohar default: 66524fd03c8SMimi Zohar break; 66624fd03c8SMimi Zohar } 66707f6a794SMimi Zohar 668503ceaefSMimi Zohar /* 66961917062SNayna Jain * Based on runtime secure boot flags, insert arch specific measurement 67061917062SNayna Jain * and appraise rules requiring file signatures for both the initial 67161917062SNayna Jain * and custom policies, prior to other appraise rules. 67261917062SNayna Jain * (Highest priority) 673503ceaefSMimi Zohar */ 67461917062SNayna Jain arch_entries = ima_init_arch_policy(); 67561917062SNayna Jain if (!arch_entries) 67661917062SNayna Jain pr_info("No architecture policies found\n"); 67761917062SNayna Jain else 67861917062SNayna Jain add_rules(arch_policy_entry, arch_entries, 67961917062SNayna Jain IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); 68061917062SNayna Jain 68161917062SNayna Jain /* 682503ceaefSMimi Zohar * Insert the builtin "secure_boot" policy rules requiring file 68361917062SNayna Jain * signatures, prior to other appraise rules. 684503ceaefSMimi Zohar */ 685c52657d9SNayna Jain if (ima_use_secure_boot) 686c52657d9SNayna Jain add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules), 687c52657d9SNayna Jain IMA_DEFAULT_POLICY); 688503ceaefSMimi Zohar 689ef96837bSMimi Zohar /* 690ef96837bSMimi Zohar * Insert the build time appraise rules requiring file signatures 691ef96837bSMimi Zohar * for both the initial and custom policies, prior to other appraise 692c52657d9SNayna Jain * rules. As the secure boot rules includes all of the build time 693c52657d9SNayna Jain * rules, include either one or the other set of rules, but not both. 694ef96837bSMimi Zohar */ 695c52657d9SNayna Jain build_appraise_entries = ARRAY_SIZE(build_appraise_rules); 696c52657d9SNayna Jain if (build_appraise_entries) { 697c52657d9SNayna Jain if (ima_use_secure_boot) 698c52657d9SNayna Jain add_rules(build_appraise_rules, build_appraise_entries, 699c52657d9SNayna Jain IMA_CUSTOM_POLICY); 700c52657d9SNayna Jain else 701c52657d9SNayna Jain add_rules(build_appraise_rules, build_appraise_entries, 702c52657d9SNayna Jain IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); 703ef96837bSMimi Zohar } 704ef96837bSMimi Zohar 705c52657d9SNayna Jain if (ima_use_appraise_tcb) 706c52657d9SNayna Jain add_rules(default_appraise_rules, 707c52657d9SNayna Jain ARRAY_SIZE(default_appraise_rules), 708c52657d9SNayna Jain IMA_DEFAULT_POLICY); 70907f6a794SMimi Zohar 71007f6a794SMimi Zohar ima_rules = &ima_default_rules; 71195ee08faSMimi Zohar ima_update_policy_flag(); 7123323eec9SMimi Zohar } 7134af4662fSMimi Zohar 7140112721dSSasha Levin /* Make sure we have a valid policy, at least containing some rules. */ 715c75d8e96SColin Ian King int ima_check_policy(void) 7160112721dSSasha Levin { 7170112721dSSasha Levin if (list_empty(&ima_temp_rules)) 7180112721dSSasha Levin return -EINVAL; 7190112721dSSasha Levin return 0; 7200112721dSSasha Levin } 7210112721dSSasha Levin 7224af4662fSMimi Zohar /** 7234af4662fSMimi Zohar * ima_update_policy - update default_rules with new measure rules 7244af4662fSMimi Zohar * 7254af4662fSMimi Zohar * Called on file .release to update the default rules with a complete new 72638d859f9SPetko Manolov * policy. What we do here is to splice ima_policy_rules and ima_temp_rules so 72738d859f9SPetko Manolov * they make a queue. The policy may be updated multiple times and this is the 72838d859f9SPetko Manolov * RCU updater. 72938d859f9SPetko Manolov * 73038d859f9SPetko Manolov * Policy rules are never deleted so ima_policy_flag gets zeroed only once when 73138d859f9SPetko Manolov * we switch from the default policy to user defined. 7324af4662fSMimi Zohar */ 7334af4662fSMimi Zohar void ima_update_policy(void) 7344af4662fSMimi Zohar { 73553b626f9SPetko Manolov struct list_head *policy = &ima_policy_rules; 73638d859f9SPetko Manolov 73753b626f9SPetko Manolov list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); 73838d859f9SPetko Manolov 73938d859f9SPetko Manolov if (ima_rules != policy) { 74038d859f9SPetko Manolov ima_policy_flag = 0; 74138d859f9SPetko Manolov ima_rules = policy; 74261917062SNayna Jain 74361917062SNayna Jain /* 74461917062SNayna Jain * IMA architecture specific policy rules are specified 74561917062SNayna Jain * as strings and converted to an array of ima_entry_rules 74661917062SNayna Jain * on boot. After loading a custom policy, free the 74761917062SNayna Jain * architecture specific rules stored as an array. 74861917062SNayna Jain */ 74961917062SNayna Jain kfree(arch_policy_entry); 75038d859f9SPetko Manolov } 751a756024eSRoberto Sassu ima_update_policy_flag(); 7524af4662fSMimi Zohar } 7534af4662fSMimi Zohar 7541a9430dbSMimi Zohar /* Keep the enumeration in sync with the policy_tokens! */ 7554af4662fSMimi Zohar enum { 7561a9430dbSMimi Zohar Opt_measure, Opt_dont_measure, 75707f6a794SMimi Zohar Opt_appraise, Opt_dont_appraise, 758da1b0029SMimi Zohar Opt_audit, Opt_hash, Opt_dont_hash, 7594af4662fSMimi Zohar Opt_obj_user, Opt_obj_role, Opt_obj_type, 7604af4662fSMimi Zohar Opt_subj_user, Opt_subj_role, Opt_subj_type, 761f1b08bbcSMimi Zohar Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, 7623dd0c8d0SMikhail Kurinnoi Opt_fsuuid, Opt_uid_eq, Opt_euid_eq, Opt_fowner_eq, 7633dd0c8d0SMikhail Kurinnoi Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, 7643dd0c8d0SMikhail Kurinnoi Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, 7650260643cSEric Richter Opt_appraise_type, Opt_permit_directio, 76619453ce0SMatthew Garrett Opt_pcr, Opt_template, Opt_err 7674af4662fSMimi Zohar }; 7684af4662fSMimi Zohar 7691a9430dbSMimi Zohar static const match_table_t policy_tokens = { 7704af4662fSMimi Zohar {Opt_measure, "measure"}, 7714af4662fSMimi Zohar {Opt_dont_measure, "dont_measure"}, 77207f6a794SMimi Zohar {Opt_appraise, "appraise"}, 77307f6a794SMimi Zohar {Opt_dont_appraise, "dont_appraise"}, 774e7c568e0SPeter Moody {Opt_audit, "audit"}, 775da1b0029SMimi Zohar {Opt_hash, "hash"}, 776da1b0029SMimi Zohar {Opt_dont_hash, "dont_hash"}, 7774af4662fSMimi Zohar {Opt_obj_user, "obj_user=%s"}, 7784af4662fSMimi Zohar {Opt_obj_role, "obj_role=%s"}, 7794af4662fSMimi Zohar {Opt_obj_type, "obj_type=%s"}, 7804af4662fSMimi Zohar {Opt_subj_user, "subj_user=%s"}, 7814af4662fSMimi Zohar {Opt_subj_role, "subj_role=%s"}, 7824af4662fSMimi Zohar {Opt_subj_type, "subj_type=%s"}, 7834af4662fSMimi Zohar {Opt_func, "func=%s"}, 7844af4662fSMimi Zohar {Opt_mask, "mask=%s"}, 7854af4662fSMimi Zohar {Opt_fsmagic, "fsmagic=%s"}, 786f1b08bbcSMimi Zohar {Opt_fsname, "fsname=%s"}, 78785865c1fSDmitry Kasatkin {Opt_fsuuid, "fsuuid=%s"}, 7883dd0c8d0SMikhail Kurinnoi {Opt_uid_eq, "uid=%s"}, 7893dd0c8d0SMikhail Kurinnoi {Opt_euid_eq, "euid=%s"}, 7903dd0c8d0SMikhail Kurinnoi {Opt_fowner_eq, "fowner=%s"}, 7913dd0c8d0SMikhail Kurinnoi {Opt_uid_gt, "uid>%s"}, 7923dd0c8d0SMikhail Kurinnoi {Opt_euid_gt, "euid>%s"}, 7933dd0c8d0SMikhail Kurinnoi {Opt_fowner_gt, "fowner>%s"}, 7943dd0c8d0SMikhail Kurinnoi {Opt_uid_lt, "uid<%s"}, 7953dd0c8d0SMikhail Kurinnoi {Opt_euid_lt, "euid<%s"}, 7963dd0c8d0SMikhail Kurinnoi {Opt_fowner_lt, "fowner<%s"}, 7970e5a247cSDmitry Kasatkin {Opt_appraise_type, "appraise_type=%s"}, 798f9b2a735SMimi Zohar {Opt_permit_directio, "permit_directio"}, 7990260643cSEric Richter {Opt_pcr, "pcr=%s"}, 80019453ce0SMatthew Garrett {Opt_template, "template=%s"}, 8014af4662fSMimi Zohar {Opt_err, NULL} 8024af4662fSMimi Zohar }; 8034af4662fSMimi Zohar 80407f6a794SMimi Zohar static int ima_lsm_rule_init(struct ima_rule_entry *entry, 8057163a993SMimi Zohar substring_t *args, int lsm_rule, int audit_type) 8064af4662fSMimi Zohar { 8074af4662fSMimi Zohar int result; 8084af4662fSMimi Zohar 8097b62e162SEric Paris if (entry->lsm[lsm_rule].rule) 8107b62e162SEric Paris return -EINVAL; 8117b62e162SEric Paris 8127163a993SMimi Zohar entry->lsm[lsm_rule].args_p = match_strdup(args); 8137163a993SMimi Zohar if (!entry->lsm[lsm_rule].args_p) 8147163a993SMimi Zohar return -ENOMEM; 8157163a993SMimi Zohar 8164af4662fSMimi Zohar entry->lsm[lsm_rule].type = audit_type; 8174af4662fSMimi Zohar result = security_filter_rule_init(entry->lsm[lsm_rule].type, 8187163a993SMimi Zohar Audit_equal, 8197163a993SMimi Zohar entry->lsm[lsm_rule].args_p, 8204af4662fSMimi Zohar &entry->lsm[lsm_rule].rule); 8217163a993SMimi Zohar if (!entry->lsm[lsm_rule].rule) { 8227163a993SMimi Zohar kfree(entry->lsm[lsm_rule].args_p); 823867c2026SMimi Zohar return -EINVAL; 8247163a993SMimi Zohar } 8257163a993SMimi Zohar 8264af4662fSMimi Zohar return result; 8274af4662fSMimi Zohar } 8284af4662fSMimi Zohar 8293dd0c8d0SMikhail Kurinnoi static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value, 8303dd0c8d0SMikhail Kurinnoi bool (*rule_operator)(kuid_t, kuid_t)) 8312f1506cdSEric Paris { 8322afd020aSStefan Berger if (!ab) 8332afd020aSStefan Berger return; 8342afd020aSStefan Berger 8353dd0c8d0SMikhail Kurinnoi if (rule_operator == &uid_gt) 8363dd0c8d0SMikhail Kurinnoi audit_log_format(ab, "%s>", key); 8373dd0c8d0SMikhail Kurinnoi else if (rule_operator == &uid_lt) 8383dd0c8d0SMikhail Kurinnoi audit_log_format(ab, "%s<", key); 8393dd0c8d0SMikhail Kurinnoi else 8402f1506cdSEric Paris audit_log_format(ab, "%s=", key); 8413d2859d5SStefan Berger audit_log_format(ab, "%s ", value); 8422f1506cdSEric Paris } 8433dd0c8d0SMikhail Kurinnoi static void ima_log_string(struct audit_buffer *ab, char *key, char *value) 8443dd0c8d0SMikhail Kurinnoi { 8453dd0c8d0SMikhail Kurinnoi ima_log_string_op(ab, key, value, NULL); 8463dd0c8d0SMikhail Kurinnoi } 8472f1506cdSEric Paris 84807f6a794SMimi Zohar static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) 8494af4662fSMimi Zohar { 8504af4662fSMimi Zohar struct audit_buffer *ab; 8514351c294SMimi Zohar char *from; 8524af4662fSMimi Zohar char *p; 8533dd0c8d0SMikhail Kurinnoi bool uid_token; 85419453ce0SMatthew Garrett struct ima_template_desc *template_desc; 8554af4662fSMimi Zohar int result = 0; 8564af4662fSMimi Zohar 857dba31ee7SStefan Berger ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, 858dba31ee7SStefan Berger AUDIT_INTEGRITY_POLICY_RULE); 8594af4662fSMimi Zohar 8608b94eea4SEric W. Biederman entry->uid = INVALID_UID; 86188265322SLinus Torvalds entry->fowner = INVALID_UID; 8623dd0c8d0SMikhail Kurinnoi entry->uid_op = &uid_eq; 8633dd0c8d0SMikhail Kurinnoi entry->fowner_op = &uid_eq; 864b9035b1fSEric Paris entry->action = UNKNOWN; 86528ef4002SEric Paris while ((p = strsep(&rule, " \t")) != NULL) { 8664af4662fSMimi Zohar substring_t args[MAX_OPT_ARGS]; 8674af4662fSMimi Zohar int token; 8684af4662fSMimi Zohar unsigned long lnum; 8694af4662fSMimi Zohar 8704af4662fSMimi Zohar if (result < 0) 8714af4662fSMimi Zohar break; 87228ef4002SEric Paris if ((*p == '\0') || (*p == ' ') || (*p == '\t')) 87328ef4002SEric Paris continue; 8744af4662fSMimi Zohar token = match_token(p, policy_tokens, args); 8754af4662fSMimi Zohar switch (token) { 8764af4662fSMimi Zohar case Opt_measure: 8772f1506cdSEric Paris ima_log_string(ab, "action", "measure"); 8787b62e162SEric Paris 8797b62e162SEric Paris if (entry->action != UNKNOWN) 8807b62e162SEric Paris result = -EINVAL; 8817b62e162SEric Paris 8824af4662fSMimi Zohar entry->action = MEASURE; 8834af4662fSMimi Zohar break; 8844af4662fSMimi Zohar case Opt_dont_measure: 8852f1506cdSEric Paris ima_log_string(ab, "action", "dont_measure"); 8867b62e162SEric Paris 8877b62e162SEric Paris if (entry->action != UNKNOWN) 8887b62e162SEric Paris result = -EINVAL; 8897b62e162SEric Paris 8904af4662fSMimi Zohar entry->action = DONT_MEASURE; 8914af4662fSMimi Zohar break; 89207f6a794SMimi Zohar case Opt_appraise: 89307f6a794SMimi Zohar ima_log_string(ab, "action", "appraise"); 89407f6a794SMimi Zohar 89507f6a794SMimi Zohar if (entry->action != UNKNOWN) 89607f6a794SMimi Zohar result = -EINVAL; 89707f6a794SMimi Zohar 89807f6a794SMimi Zohar entry->action = APPRAISE; 89907f6a794SMimi Zohar break; 90007f6a794SMimi Zohar case Opt_dont_appraise: 90107f6a794SMimi Zohar ima_log_string(ab, "action", "dont_appraise"); 90207f6a794SMimi Zohar 90307f6a794SMimi Zohar if (entry->action != UNKNOWN) 90407f6a794SMimi Zohar result = -EINVAL; 90507f6a794SMimi Zohar 90607f6a794SMimi Zohar entry->action = DONT_APPRAISE; 90707f6a794SMimi Zohar break; 908e7c568e0SPeter Moody case Opt_audit: 909e7c568e0SPeter Moody ima_log_string(ab, "action", "audit"); 910e7c568e0SPeter Moody 911e7c568e0SPeter Moody if (entry->action != UNKNOWN) 912e7c568e0SPeter Moody result = -EINVAL; 913e7c568e0SPeter Moody 914e7c568e0SPeter Moody entry->action = AUDIT; 915e7c568e0SPeter Moody break; 916da1b0029SMimi Zohar case Opt_hash: 917da1b0029SMimi Zohar ima_log_string(ab, "action", "hash"); 918da1b0029SMimi Zohar 919da1b0029SMimi Zohar if (entry->action != UNKNOWN) 920da1b0029SMimi Zohar result = -EINVAL; 921da1b0029SMimi Zohar 922da1b0029SMimi Zohar entry->action = HASH; 923da1b0029SMimi Zohar break; 924da1b0029SMimi Zohar case Opt_dont_hash: 925da1b0029SMimi Zohar ima_log_string(ab, "action", "dont_hash"); 926da1b0029SMimi Zohar 927da1b0029SMimi Zohar if (entry->action != UNKNOWN) 928da1b0029SMimi Zohar result = -EINVAL; 929da1b0029SMimi Zohar 930da1b0029SMimi Zohar entry->action = DONT_HASH; 931da1b0029SMimi Zohar break; 9324af4662fSMimi Zohar case Opt_func: 9332f1506cdSEric Paris ima_log_string(ab, "func", args[0].from); 9347b62e162SEric Paris 9357b62e162SEric Paris if (entry->func) 9367b62e162SEric Paris result = -EINVAL; 9377b62e162SEric Paris 9381e93d005SMimi Zohar if (strcmp(args[0].from, "FILE_CHECK") == 0) 9391e93d005SMimi Zohar entry->func = FILE_CHECK; 9401e93d005SMimi Zohar /* PATH_CHECK is for backwards compat */ 9411e93d005SMimi Zohar else if (strcmp(args[0].from, "PATH_CHECK") == 0) 9421e93d005SMimi Zohar entry->func = FILE_CHECK; 943fdf90729SMimi Zohar else if (strcmp(args[0].from, "MODULE_CHECK") == 0) 944fdf90729SMimi Zohar entry->func = MODULE_CHECK; 9455a9196d7SMimi Zohar else if (strcmp(args[0].from, "FIRMWARE_CHECK") == 0) 9465a9196d7SMimi Zohar entry->func = FIRMWARE_CHECK; 94716cac49fSMimi Zohar else if ((strcmp(args[0].from, "FILE_MMAP") == 0) 94816cac49fSMimi Zohar || (strcmp(args[0].from, "MMAP_CHECK") == 0)) 94916cac49fSMimi Zohar entry->func = MMAP_CHECK; 9504af4662fSMimi Zohar else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 9514af4662fSMimi Zohar entry->func = BPRM_CHECK; 952d906c10dSMatthew Garrett else if (strcmp(args[0].from, "CREDS_CHECK") == 0) 953d906c10dSMatthew Garrett entry->func = CREDS_CHECK; 954d9ddf077SMimi Zohar else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") == 955d9ddf077SMimi Zohar 0) 956d9ddf077SMimi Zohar entry->func = KEXEC_KERNEL_CHECK; 957d9ddf077SMimi Zohar else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK") 958d9ddf077SMimi Zohar == 0) 959d9ddf077SMimi Zohar entry->func = KEXEC_INITRAMFS_CHECK; 96019f8a847SMimi Zohar else if (strcmp(args[0].from, "POLICY_CHECK") == 0) 96119f8a847SMimi Zohar entry->func = POLICY_CHECK; 962b0935123SPrakhar Srivastava else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0) 963b0935123SPrakhar Srivastava entry->func = KEXEC_CMDLINE; 9644af4662fSMimi Zohar else 9654af4662fSMimi Zohar result = -EINVAL; 9664af4662fSMimi Zohar if (!result) 9674af4662fSMimi Zohar entry->flags |= IMA_FUNC; 9684af4662fSMimi Zohar break; 9694af4662fSMimi Zohar case Opt_mask: 9702f1506cdSEric Paris ima_log_string(ab, "mask", args[0].from); 9717b62e162SEric Paris 9727b62e162SEric Paris if (entry->mask) 9737b62e162SEric Paris result = -EINVAL; 9747b62e162SEric Paris 9754351c294SMimi Zohar from = args[0].from; 9764351c294SMimi Zohar if (*from == '^') 9774351c294SMimi Zohar from++; 9784351c294SMimi Zohar 9794351c294SMimi Zohar if ((strcmp(from, "MAY_EXEC")) == 0) 9804af4662fSMimi Zohar entry->mask = MAY_EXEC; 9814351c294SMimi Zohar else if (strcmp(from, "MAY_WRITE") == 0) 9824af4662fSMimi Zohar entry->mask = MAY_WRITE; 9834351c294SMimi Zohar else if (strcmp(from, "MAY_READ") == 0) 9844af4662fSMimi Zohar entry->mask = MAY_READ; 9854351c294SMimi Zohar else if (strcmp(from, "MAY_APPEND") == 0) 9864af4662fSMimi Zohar entry->mask = MAY_APPEND; 9874af4662fSMimi Zohar else 9884af4662fSMimi Zohar result = -EINVAL; 9894af4662fSMimi Zohar if (!result) 9904351c294SMimi Zohar entry->flags |= (*args[0].from == '^') 9914351c294SMimi Zohar ? IMA_INMASK : IMA_MASK; 9924af4662fSMimi Zohar break; 9934af4662fSMimi Zohar case Opt_fsmagic: 9942f1506cdSEric Paris ima_log_string(ab, "fsmagic", args[0].from); 9957b62e162SEric Paris 9967b62e162SEric Paris if (entry->fsmagic) { 9977b62e162SEric Paris result = -EINVAL; 9987b62e162SEric Paris break; 9997b62e162SEric Paris } 10007b62e162SEric Paris 10012bb930abSDmitry Kasatkin result = kstrtoul(args[0].from, 16, &entry->fsmagic); 10024af4662fSMimi Zohar if (!result) 10034af4662fSMimi Zohar entry->flags |= IMA_FSMAGIC; 10044af4662fSMimi Zohar break; 1005f1b08bbcSMimi Zohar case Opt_fsname: 1006f1b08bbcSMimi Zohar ima_log_string(ab, "fsname", args[0].from); 1007f1b08bbcSMimi Zohar 1008f1b08bbcSMimi Zohar entry->fsname = kstrdup(args[0].from, GFP_KERNEL); 1009f1b08bbcSMimi Zohar if (!entry->fsname) { 1010f1b08bbcSMimi Zohar result = -ENOMEM; 1011f1b08bbcSMimi Zohar break; 1012f1b08bbcSMimi Zohar } 1013f1b08bbcSMimi Zohar result = 0; 1014f1b08bbcSMimi Zohar entry->flags |= IMA_FSNAME; 1015f1b08bbcSMimi Zohar break; 101685865c1fSDmitry Kasatkin case Opt_fsuuid: 101785865c1fSDmitry Kasatkin ima_log_string(ab, "fsuuid", args[0].from); 101885865c1fSDmitry Kasatkin 101936447456SMike Rapoport if (!uuid_is_null(&entry->fsuuid)) { 102085865c1fSDmitry Kasatkin result = -EINVAL; 102185865c1fSDmitry Kasatkin break; 102285865c1fSDmitry Kasatkin } 102385865c1fSDmitry Kasatkin 1024787d8c53SChristoph Hellwig result = uuid_parse(args[0].from, &entry->fsuuid); 1025446d64e3SMimi Zohar if (!result) 102685865c1fSDmitry Kasatkin entry->flags |= IMA_FSUUID; 102785865c1fSDmitry Kasatkin break; 10283dd0c8d0SMikhail Kurinnoi case Opt_uid_gt: 10293dd0c8d0SMikhail Kurinnoi case Opt_euid_gt: 10303dd0c8d0SMikhail Kurinnoi entry->uid_op = &uid_gt; 103109186e50SGustavo A. R. Silva /* fall through */ 10323dd0c8d0SMikhail Kurinnoi case Opt_uid_lt: 10333dd0c8d0SMikhail Kurinnoi case Opt_euid_lt: 10343dd0c8d0SMikhail Kurinnoi if ((token == Opt_uid_lt) || (token == Opt_euid_lt)) 10353dd0c8d0SMikhail Kurinnoi entry->uid_op = &uid_lt; 103609186e50SGustavo A. R. Silva /* fall through */ 10373dd0c8d0SMikhail Kurinnoi case Opt_uid_eq: 10383dd0c8d0SMikhail Kurinnoi case Opt_euid_eq: 10393dd0c8d0SMikhail Kurinnoi uid_token = (token == Opt_uid_eq) || 10403dd0c8d0SMikhail Kurinnoi (token == Opt_uid_gt) || 10413dd0c8d0SMikhail Kurinnoi (token == Opt_uid_lt); 10423dd0c8d0SMikhail Kurinnoi 10433dd0c8d0SMikhail Kurinnoi ima_log_string_op(ab, uid_token ? "uid" : "euid", 10443dd0c8d0SMikhail Kurinnoi args[0].from, entry->uid_op); 10457b62e162SEric Paris 10468b94eea4SEric W. Biederman if (uid_valid(entry->uid)) { 10477b62e162SEric Paris result = -EINVAL; 10487b62e162SEric Paris break; 10497b62e162SEric Paris } 10507b62e162SEric Paris 105129707b20SJingoo Han result = kstrtoul(args[0].from, 10, &lnum); 10524af4662fSMimi Zohar if (!result) { 1053139069efSMimi Zohar entry->uid = make_kuid(current_user_ns(), 1054139069efSMimi Zohar (uid_t) lnum); 1055139069efSMimi Zohar if (!uid_valid(entry->uid) || 1056139069efSMimi Zohar (uid_t)lnum != lnum) 10574af4662fSMimi Zohar result = -EINVAL; 10584af4662fSMimi Zohar else 10593dd0c8d0SMikhail Kurinnoi entry->flags |= uid_token 1060139069efSMimi Zohar ? IMA_UID : IMA_EUID; 10614af4662fSMimi Zohar } 10624af4662fSMimi Zohar break; 10633dd0c8d0SMikhail Kurinnoi case Opt_fowner_gt: 10643dd0c8d0SMikhail Kurinnoi entry->fowner_op = &uid_gt; 106509186e50SGustavo A. R. Silva /* fall through */ 10663dd0c8d0SMikhail Kurinnoi case Opt_fowner_lt: 10673dd0c8d0SMikhail Kurinnoi if (token == Opt_fowner_lt) 10683dd0c8d0SMikhail Kurinnoi entry->fowner_op = &uid_lt; 106909186e50SGustavo A. R. Silva /* fall through */ 10703dd0c8d0SMikhail Kurinnoi case Opt_fowner_eq: 10713dd0c8d0SMikhail Kurinnoi ima_log_string_op(ab, "fowner", args[0].from, 10723dd0c8d0SMikhail Kurinnoi entry->fowner_op); 107307f6a794SMimi Zohar 107488265322SLinus Torvalds if (uid_valid(entry->fowner)) { 107507f6a794SMimi Zohar result = -EINVAL; 107607f6a794SMimi Zohar break; 107707f6a794SMimi Zohar } 107807f6a794SMimi Zohar 107929707b20SJingoo Han result = kstrtoul(args[0].from, 10, &lnum); 108007f6a794SMimi Zohar if (!result) { 108188265322SLinus Torvalds entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum); 108288265322SLinus Torvalds if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum)) 108307f6a794SMimi Zohar result = -EINVAL; 108407f6a794SMimi Zohar else 108507f6a794SMimi Zohar entry->flags |= IMA_FOWNER; 108607f6a794SMimi Zohar } 108707f6a794SMimi Zohar break; 10884af4662fSMimi Zohar case Opt_obj_user: 10892f1506cdSEric Paris ima_log_string(ab, "obj_user", args[0].from); 10907163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 10914af4662fSMimi Zohar LSM_OBJ_USER, 10924af4662fSMimi Zohar AUDIT_OBJ_USER); 10934af4662fSMimi Zohar break; 10944af4662fSMimi Zohar case Opt_obj_role: 10952f1506cdSEric Paris ima_log_string(ab, "obj_role", args[0].from); 10967163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 10974af4662fSMimi Zohar LSM_OBJ_ROLE, 10984af4662fSMimi Zohar AUDIT_OBJ_ROLE); 10994af4662fSMimi Zohar break; 11004af4662fSMimi Zohar case Opt_obj_type: 11012f1506cdSEric Paris ima_log_string(ab, "obj_type", args[0].from); 11027163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 11034af4662fSMimi Zohar LSM_OBJ_TYPE, 11044af4662fSMimi Zohar AUDIT_OBJ_TYPE); 11054af4662fSMimi Zohar break; 11064af4662fSMimi Zohar case Opt_subj_user: 11072f1506cdSEric Paris ima_log_string(ab, "subj_user", args[0].from); 11087163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 11094af4662fSMimi Zohar LSM_SUBJ_USER, 11104af4662fSMimi Zohar AUDIT_SUBJ_USER); 11114af4662fSMimi Zohar break; 11124af4662fSMimi Zohar case Opt_subj_role: 11132f1506cdSEric Paris ima_log_string(ab, "subj_role", args[0].from); 11147163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 11154af4662fSMimi Zohar LSM_SUBJ_ROLE, 11164af4662fSMimi Zohar AUDIT_SUBJ_ROLE); 11174af4662fSMimi Zohar break; 11184af4662fSMimi Zohar case Opt_subj_type: 11192f1506cdSEric Paris ima_log_string(ab, "subj_type", args[0].from); 11207163a993SMimi Zohar result = ima_lsm_rule_init(entry, args, 11214af4662fSMimi Zohar LSM_SUBJ_TYPE, 11224af4662fSMimi Zohar AUDIT_SUBJ_TYPE); 11234af4662fSMimi Zohar break; 11240e5a247cSDmitry Kasatkin case Opt_appraise_type: 11250e5a247cSDmitry Kasatkin if (entry->action != APPRAISE) { 11260e5a247cSDmitry Kasatkin result = -EINVAL; 11270e5a247cSDmitry Kasatkin break; 11280e5a247cSDmitry Kasatkin } 11290e5a247cSDmitry Kasatkin 11300e5a247cSDmitry Kasatkin ima_log_string(ab, "appraise_type", args[0].from); 11310e5a247cSDmitry Kasatkin if ((strcmp(args[0].from, "imasig")) == 0) 11320e5a247cSDmitry Kasatkin entry->flags |= IMA_DIGSIG_REQUIRED; 11330e5a247cSDmitry Kasatkin else 11340e5a247cSDmitry Kasatkin result = -EINVAL; 11350e5a247cSDmitry Kasatkin break; 1136f9b2a735SMimi Zohar case Opt_permit_directio: 1137f9b2a735SMimi Zohar entry->flags |= IMA_PERMIT_DIRECTIO; 1138f9b2a735SMimi Zohar break; 11390260643cSEric Richter case Opt_pcr: 11400260643cSEric Richter if (entry->action != MEASURE) { 11410260643cSEric Richter result = -EINVAL; 11420260643cSEric Richter break; 11430260643cSEric Richter } 11440260643cSEric Richter ima_log_string(ab, "pcr", args[0].from); 11450260643cSEric Richter 11460260643cSEric Richter result = kstrtoint(args[0].from, 10, &entry->pcr); 11470260643cSEric Richter if (result || INVALID_PCR(entry->pcr)) 11480260643cSEric Richter result = -EINVAL; 11490260643cSEric Richter else 11500260643cSEric Richter entry->flags |= IMA_PCR; 11510260643cSEric Richter 11520260643cSEric Richter break; 115319453ce0SMatthew Garrett case Opt_template: 115419453ce0SMatthew Garrett ima_log_string(ab, "template", args[0].from); 115519453ce0SMatthew Garrett if (entry->action != MEASURE) { 115619453ce0SMatthew Garrett result = -EINVAL; 115719453ce0SMatthew Garrett break; 115819453ce0SMatthew Garrett } 115919453ce0SMatthew Garrett template_desc = lookup_template_desc(args[0].from); 116019453ce0SMatthew Garrett if (!template_desc || entry->template) { 116119453ce0SMatthew Garrett result = -EINVAL; 116219453ce0SMatthew Garrett break; 116319453ce0SMatthew Garrett } 116419453ce0SMatthew Garrett 116519453ce0SMatthew Garrett /* 116619453ce0SMatthew Garrett * template_desc_init_fields() does nothing if 116719453ce0SMatthew Garrett * the template is already initialised, so 116819453ce0SMatthew Garrett * it's safe to do this unconditionally 116919453ce0SMatthew Garrett */ 117019453ce0SMatthew Garrett template_desc_init_fields(template_desc->fmt, 117119453ce0SMatthew Garrett &(template_desc->fields), 117219453ce0SMatthew Garrett &(template_desc->num_fields)); 117319453ce0SMatthew Garrett entry->template = template_desc; 117419453ce0SMatthew Garrett break; 11754af4662fSMimi Zohar case Opt_err: 11762f1506cdSEric Paris ima_log_string(ab, "UNKNOWN", p); 1177e9d393bfSEric Paris result = -EINVAL; 11784af4662fSMimi Zohar break; 11794af4662fSMimi Zohar } 11804af4662fSMimi Zohar } 11817b62e162SEric Paris if (!result && (entry->action == UNKNOWN)) 11824af4662fSMimi Zohar result = -EINVAL; 11836f0911a6SMimi Zohar else if (entry->action == APPRAISE) 11846f0911a6SMimi Zohar temp_ima_appraise |= ima_appraise_flag(entry->func); 11856f0911a6SMimi Zohar 1186b0d5de4dSEric Paris audit_log_format(ab, "res=%d", !result); 11874af4662fSMimi Zohar audit_log_end(ab); 11884af4662fSMimi Zohar return result; 11894af4662fSMimi Zohar } 11904af4662fSMimi Zohar 11914af4662fSMimi Zohar /** 119207f6a794SMimi Zohar * ima_parse_add_rule - add a rule to ima_policy_rules 11934af4662fSMimi Zohar * @rule - ima measurement policy rule 11944af4662fSMimi Zohar * 119538d859f9SPetko Manolov * Avoid locking by allowing just one writer at a time in ima_write_policy() 11966ccd0456SEric Paris * Returns the length of the rule parsed, an error code on failure 11974af4662fSMimi Zohar */ 11986ccd0456SEric Paris ssize_t ima_parse_add_rule(char *rule) 11994af4662fSMimi Zohar { 120052a13284SMimi Zohar static const char op[] = "update_policy"; 12016ccd0456SEric Paris char *p; 120207f6a794SMimi Zohar struct ima_rule_entry *entry; 12036ccd0456SEric Paris ssize_t result, len; 12044af4662fSMimi Zohar int audit_info = 0; 12054af4662fSMimi Zohar 1206272a6e90SDmitry Kasatkin p = strsep(&rule, "\n"); 1207272a6e90SDmitry Kasatkin len = strlen(p) + 1; 12087178784fSDmitry Kasatkin p += strspn(p, " \t"); 1209272a6e90SDmitry Kasatkin 12107178784fSDmitry Kasatkin if (*p == '#' || *p == '\0') 1211272a6e90SDmitry Kasatkin return len; 1212272a6e90SDmitry Kasatkin 12134af4662fSMimi Zohar entry = kzalloc(sizeof(*entry), GFP_KERNEL); 12144af4662fSMimi Zohar if (!entry) { 12154af4662fSMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 12164af4662fSMimi Zohar NULL, op, "-ENOMEM", -ENOMEM, audit_info); 12174af4662fSMimi Zohar return -ENOMEM; 12184af4662fSMimi Zohar } 12194af4662fSMimi Zohar 12204af4662fSMimi Zohar INIT_LIST_HEAD(&entry->list); 12214af4662fSMimi Zohar 12226ccd0456SEric Paris result = ima_parse_rule(p, entry); 12237233e3eeSEric Paris if (result) { 12244af4662fSMimi Zohar kfree(entry); 1225523979adSMimi Zohar integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, 12267e9001f6SRichard Guy Briggs NULL, op, "invalid-policy", result, 1227523979adSMimi Zohar audit_info); 12284af4662fSMimi Zohar return result; 12294af4662fSMimi Zohar } 12304af4662fSMimi Zohar 123138d859f9SPetko Manolov list_add_tail(&entry->list, &ima_temp_rules); 12327233e3eeSEric Paris 12337233e3eeSEric Paris return len; 12347233e3eeSEric Paris } 12357233e3eeSEric Paris 123638d859f9SPetko Manolov /** 123738d859f9SPetko Manolov * ima_delete_rules() called to cleanup invalid in-flight policy. 123838d859f9SPetko Manolov * We don't need locking as we operate on the temp list, which is 123938d859f9SPetko Manolov * different from the active one. There is also only one user of 124038d859f9SPetko Manolov * ima_delete_rules() at a time. 124138d859f9SPetko Manolov */ 124264c61d80SJames Morris void ima_delete_rules(void) 12434af4662fSMimi Zohar { 124407f6a794SMimi Zohar struct ima_rule_entry *entry, *tmp; 12457163a993SMimi Zohar int i; 12464af4662fSMimi Zohar 12476ad6afa1SMimi Zohar temp_ima_appraise = 0; 124838d859f9SPetko Manolov list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { 12497163a993SMimi Zohar for (i = 0; i < MAX_LSM_RULES; i++) 12507163a993SMimi Zohar kfree(entry->lsm[i].args_p); 12517163a993SMimi Zohar 12524af4662fSMimi Zohar list_del(&entry->list); 12534af4662fSMimi Zohar kfree(entry); 12544af4662fSMimi Zohar } 12554af4662fSMimi Zohar } 125680eae209SPetko Manolov 125780eae209SPetko Manolov #ifdef CONFIG_IMA_READ_POLICY 125880eae209SPetko Manolov enum { 125980eae209SPetko Manolov mask_exec = 0, mask_write, mask_read, mask_append 126080eae209SPetko Manolov }; 126180eae209SPetko Manolov 1262bb543e39SThiago Jung Bauermann static const char *const mask_tokens[] = { 12638cdc23a3SRoberto Sassu "^MAY_EXEC", 12648cdc23a3SRoberto Sassu "^MAY_WRITE", 12658cdc23a3SRoberto Sassu "^MAY_READ", 12668cdc23a3SRoberto Sassu "^MAY_APPEND" 126780eae209SPetko Manolov }; 126880eae209SPetko Manolov 12692663218bSThiago Jung Bauermann #define __ima_hook_stringify(str) (#str), 127080eae209SPetko Manolov 1271bb543e39SThiago Jung Bauermann static const char *const func_tokens[] = { 12722663218bSThiago Jung Bauermann __ima_hooks(__ima_hook_stringify) 127380eae209SPetko Manolov }; 127480eae209SPetko Manolov 127580eae209SPetko Manolov void *ima_policy_start(struct seq_file *m, loff_t *pos) 127680eae209SPetko Manolov { 127780eae209SPetko Manolov loff_t l = *pos; 127880eae209SPetko Manolov struct ima_rule_entry *entry; 127980eae209SPetko Manolov 128080eae209SPetko Manolov rcu_read_lock(); 128180eae209SPetko Manolov list_for_each_entry_rcu(entry, ima_rules, list) { 128280eae209SPetko Manolov if (!l--) { 128380eae209SPetko Manolov rcu_read_unlock(); 128480eae209SPetko Manolov return entry; 128580eae209SPetko Manolov } 128680eae209SPetko Manolov } 128780eae209SPetko Manolov rcu_read_unlock(); 128880eae209SPetko Manolov return NULL; 128980eae209SPetko Manolov } 129080eae209SPetko Manolov 129180eae209SPetko Manolov void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) 129280eae209SPetko Manolov { 129380eae209SPetko Manolov struct ima_rule_entry *entry = v; 129480eae209SPetko Manolov 129580eae209SPetko Manolov rcu_read_lock(); 129680eae209SPetko Manolov entry = list_entry_rcu(entry->list.next, struct ima_rule_entry, list); 129780eae209SPetko Manolov rcu_read_unlock(); 129880eae209SPetko Manolov (*pos)++; 129980eae209SPetko Manolov 130080eae209SPetko Manolov return (&entry->list == ima_rules) ? NULL : entry; 130180eae209SPetko Manolov } 130280eae209SPetko Manolov 130380eae209SPetko Manolov void ima_policy_stop(struct seq_file *m, void *v) 130480eae209SPetko Manolov { 130580eae209SPetko Manolov } 130680eae209SPetko Manolov 13071a9430dbSMimi Zohar #define pt(token) policy_tokens[token].pattern 130880eae209SPetko Manolov #define mt(token) mask_tokens[token] 130980eae209SPetko Manolov 1310b5269ab3SMimi Zohar /* 1311b5269ab3SMimi Zohar * policy_func_show - display the ima_hooks policy rule 1312b5269ab3SMimi Zohar */ 1313b5269ab3SMimi Zohar static void policy_func_show(struct seq_file *m, enum ima_hooks func) 1314b5269ab3SMimi Zohar { 13152663218bSThiago Jung Bauermann if (func > 0 && func < MAX_CHECK) 13162663218bSThiago Jung Bauermann seq_printf(m, "func=%s ", func_tokens[func]); 13172663218bSThiago Jung Bauermann else 13182663218bSThiago Jung Bauermann seq_printf(m, "func=%d ", func); 1319b5269ab3SMimi Zohar } 1320b5269ab3SMimi Zohar 132180eae209SPetko Manolov int ima_policy_show(struct seq_file *m, void *v) 132280eae209SPetko Manolov { 132380eae209SPetko Manolov struct ima_rule_entry *entry = v; 1324b8b57278SAndy Shevchenko int i; 132580eae209SPetko Manolov char tbuf[64] = {0,}; 13268cdc23a3SRoberto Sassu int offset = 0; 132780eae209SPetko Manolov 132880eae209SPetko Manolov rcu_read_lock(); 132980eae209SPetko Manolov 133080eae209SPetko Manolov if (entry->action & MEASURE) 133180eae209SPetko Manolov seq_puts(m, pt(Opt_measure)); 133280eae209SPetko Manolov if (entry->action & DONT_MEASURE) 133380eae209SPetko Manolov seq_puts(m, pt(Opt_dont_measure)); 133480eae209SPetko Manolov if (entry->action & APPRAISE) 133580eae209SPetko Manolov seq_puts(m, pt(Opt_appraise)); 133680eae209SPetko Manolov if (entry->action & DONT_APPRAISE) 133780eae209SPetko Manolov seq_puts(m, pt(Opt_dont_appraise)); 133880eae209SPetko Manolov if (entry->action & AUDIT) 133980eae209SPetko Manolov seq_puts(m, pt(Opt_audit)); 1340da1b0029SMimi Zohar if (entry->action & HASH) 1341da1b0029SMimi Zohar seq_puts(m, pt(Opt_hash)); 1342da1b0029SMimi Zohar if (entry->action & DONT_HASH) 1343da1b0029SMimi Zohar seq_puts(m, pt(Opt_dont_hash)); 134480eae209SPetko Manolov 134580eae209SPetko Manolov seq_puts(m, " "); 134680eae209SPetko Manolov 1347b5269ab3SMimi Zohar if (entry->flags & IMA_FUNC) 1348b5269ab3SMimi Zohar policy_func_show(m, entry->func); 134980eae209SPetko Manolov 13508cdc23a3SRoberto Sassu if ((entry->flags & IMA_MASK) || (entry->flags & IMA_INMASK)) { 13518cdc23a3SRoberto Sassu if (entry->flags & IMA_MASK) 13528cdc23a3SRoberto Sassu offset = 1; 135380eae209SPetko Manolov if (entry->mask & MAY_EXEC) 13548cdc23a3SRoberto Sassu seq_printf(m, pt(Opt_mask), mt(mask_exec) + offset); 135580eae209SPetko Manolov if (entry->mask & MAY_WRITE) 13568cdc23a3SRoberto Sassu seq_printf(m, pt(Opt_mask), mt(mask_write) + offset); 135780eae209SPetko Manolov if (entry->mask & MAY_READ) 13588cdc23a3SRoberto Sassu seq_printf(m, pt(Opt_mask), mt(mask_read) + offset); 135980eae209SPetko Manolov if (entry->mask & MAY_APPEND) 13608cdc23a3SRoberto Sassu seq_printf(m, pt(Opt_mask), mt(mask_append) + offset); 136180eae209SPetko Manolov seq_puts(m, " "); 136280eae209SPetko Manolov } 136380eae209SPetko Manolov 136480eae209SPetko Manolov if (entry->flags & IMA_FSMAGIC) { 136580eae209SPetko Manolov snprintf(tbuf, sizeof(tbuf), "0x%lx", entry->fsmagic); 136680eae209SPetko Manolov seq_printf(m, pt(Opt_fsmagic), tbuf); 136780eae209SPetko Manolov seq_puts(m, " "); 136880eae209SPetko Manolov } 136980eae209SPetko Manolov 1370f1b08bbcSMimi Zohar if (entry->flags & IMA_FSNAME) { 1371f1b08bbcSMimi Zohar snprintf(tbuf, sizeof(tbuf), "%s", entry->fsname); 1372f1b08bbcSMimi Zohar seq_printf(m, pt(Opt_fsname), tbuf); 1373f1b08bbcSMimi Zohar seq_puts(m, " "); 1374f1b08bbcSMimi Zohar } 1375f1b08bbcSMimi Zohar 13760260643cSEric Richter if (entry->flags & IMA_PCR) { 13770260643cSEric Richter snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr); 13780260643cSEric Richter seq_printf(m, pt(Opt_pcr), tbuf); 13790260643cSEric Richter seq_puts(m, " "); 13800260643cSEric Richter } 13810260643cSEric Richter 138280eae209SPetko Manolov if (entry->flags & IMA_FSUUID) { 1383787d8c53SChristoph Hellwig seq_printf(m, "fsuuid=%pU", &entry->fsuuid); 138480eae209SPetko Manolov seq_puts(m, " "); 138580eae209SPetko Manolov } 138680eae209SPetko Manolov 138780eae209SPetko Manolov if (entry->flags & IMA_UID) { 138880eae209SPetko Manolov snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); 13893dd0c8d0SMikhail Kurinnoi if (entry->uid_op == &uid_gt) 13903dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_uid_gt), tbuf); 13913dd0c8d0SMikhail Kurinnoi else if (entry->uid_op == &uid_lt) 13923dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_uid_lt), tbuf); 13933dd0c8d0SMikhail Kurinnoi else 13943dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_uid_eq), tbuf); 139580eae209SPetko Manolov seq_puts(m, " "); 139680eae209SPetko Manolov } 139780eae209SPetko Manolov 139880eae209SPetko Manolov if (entry->flags & IMA_EUID) { 139980eae209SPetko Manolov snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->uid)); 14003dd0c8d0SMikhail Kurinnoi if (entry->uid_op == &uid_gt) 14013dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_euid_gt), tbuf); 14023dd0c8d0SMikhail Kurinnoi else if (entry->uid_op == &uid_lt) 14033dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_euid_lt), tbuf); 14043dd0c8d0SMikhail Kurinnoi else 14053dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_euid_eq), tbuf); 140680eae209SPetko Manolov seq_puts(m, " "); 140780eae209SPetko Manolov } 140880eae209SPetko Manolov 140980eae209SPetko Manolov if (entry->flags & IMA_FOWNER) { 141080eae209SPetko Manolov snprintf(tbuf, sizeof(tbuf), "%d", __kuid_val(entry->fowner)); 14113dd0c8d0SMikhail Kurinnoi if (entry->fowner_op == &uid_gt) 14123dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_fowner_gt), tbuf); 14133dd0c8d0SMikhail Kurinnoi else if (entry->fowner_op == &uid_lt) 14143dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_fowner_lt), tbuf); 14153dd0c8d0SMikhail Kurinnoi else 14163dd0c8d0SMikhail Kurinnoi seq_printf(m, pt(Opt_fowner_eq), tbuf); 141780eae209SPetko Manolov seq_puts(m, " "); 141880eae209SPetko Manolov } 141980eae209SPetko Manolov 142080eae209SPetko Manolov for (i = 0; i < MAX_LSM_RULES; i++) { 142180eae209SPetko Manolov if (entry->lsm[i].rule) { 142280eae209SPetko Manolov switch (i) { 142380eae209SPetko Manolov case LSM_OBJ_USER: 142480eae209SPetko Manolov seq_printf(m, pt(Opt_obj_user), 142580eae209SPetko Manolov (char *)entry->lsm[i].args_p); 142680eae209SPetko Manolov break; 142780eae209SPetko Manolov case LSM_OBJ_ROLE: 142880eae209SPetko Manolov seq_printf(m, pt(Opt_obj_role), 142980eae209SPetko Manolov (char *)entry->lsm[i].args_p); 143080eae209SPetko Manolov break; 143180eae209SPetko Manolov case LSM_OBJ_TYPE: 143280eae209SPetko Manolov seq_printf(m, pt(Opt_obj_type), 143380eae209SPetko Manolov (char *)entry->lsm[i].args_p); 143480eae209SPetko Manolov break; 143580eae209SPetko Manolov case LSM_SUBJ_USER: 143680eae209SPetko Manolov seq_printf(m, pt(Opt_subj_user), 143780eae209SPetko Manolov (char *)entry->lsm[i].args_p); 143880eae209SPetko Manolov break; 143980eae209SPetko Manolov case LSM_SUBJ_ROLE: 144080eae209SPetko Manolov seq_printf(m, pt(Opt_subj_role), 144180eae209SPetko Manolov (char *)entry->lsm[i].args_p); 144280eae209SPetko Manolov break; 144380eae209SPetko Manolov case LSM_SUBJ_TYPE: 144480eae209SPetko Manolov seq_printf(m, pt(Opt_subj_type), 144580eae209SPetko Manolov (char *)entry->lsm[i].args_p); 144680eae209SPetko Manolov break; 144780eae209SPetko Manolov } 144880eae209SPetko Manolov } 144980eae209SPetko Manolov } 145019453ce0SMatthew Garrett if (entry->template) 145119453ce0SMatthew Garrett seq_printf(m, "template=%s ", entry->template->name); 145280eae209SPetko Manolov if (entry->flags & IMA_DIGSIG_REQUIRED) 145380eae209SPetko Manolov seq_puts(m, "appraise_type=imasig "); 145480eae209SPetko Manolov if (entry->flags & IMA_PERMIT_DIRECTIO) 145580eae209SPetko Manolov seq_puts(m, "permit_directio "); 145680eae209SPetko Manolov rcu_read_unlock(); 145780eae209SPetko Manolov seq_puts(m, "\n"); 145880eae209SPetko Manolov return 0; 145980eae209SPetko Manolov } 146080eae209SPetko Manolov #endif /* CONFIG_IMA_READ_POLICY */ 1461