Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IMA: support for per policy rule template formats

Admins may wish to log different measurements using different IMA
templates. Add support for overriding the default template on a per-rule
basis.

Inspired-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

authored by

Matthew Garrett and committed by
Mimi Zohar
19453ce0 8c655784

+79 -29
+3 -2
Documentation/ABI/testing/ima_policy
··· 24 24 [euid=] [fowner=] [fsname=]] 25 25 lsm: [[subj_user=] [subj_role=] [subj_type=] 26 26 [obj_user=] [obj_role=] [obj_type=]] 27 - option: [[appraise_type=]] [permit_directio] 28 - 27 + option: [[appraise_type=]] [template=] [permit_directio] 29 28 base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] 30 29 [FIRMWARE_CHECK] 31 30 [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] ··· 37 38 fowner:= decimal value 38 39 lsm: are LSM specific 39 40 option: appraise_type:= [imasig] 41 + template:= name of a defined IMA template type 42 + (eg, ima-ng). Only valid when action is "measure". 40 43 pcr:= decimal value 41 44 42 45 default policy:
+12 -4
security/integrity/ima/ima.h
··· 146 146 int ima_init_crypto(void); 147 147 void ima_putc(struct seq_file *m, void *data, int datalen); 148 148 void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); 149 + int template_desc_init_fields(const char *template_fmt, 150 + const struct ima_template_field ***fields, 151 + int *num_fields); 149 152 struct ima_template_desc *ima_template_desc_current(void); 153 + struct ima_template_desc *lookup_template_desc(const char *name); 150 154 int ima_restore_measurement_entry(struct ima_template_entry *entry); 151 155 int ima_restore_measurement_list(loff_t bufsize, void *buf); 152 156 int ima_measurements_show(struct seq_file *m, void *v); ··· 199 195 200 196 /* LIM API function definitions */ 201 197 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 202 - int mask, enum ima_hooks func, int *pcr); 198 + int mask, enum ima_hooks func, int *pcr, 199 + struct ima_template_desc **template_desc); 203 200 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); 204 201 int ima_collect_measurement(struct integrity_iint_cache *iint, 205 202 struct file *file, void *buf, loff_t size, ··· 208 203 void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 209 204 const unsigned char *filename, 210 205 struct evm_ima_xattr_data *xattr_value, 211 - int xattr_len, int pcr); 206 + int xattr_len, int pcr, 207 + struct ima_template_desc *template_desc); 212 208 void ima_audit_measurement(struct integrity_iint_cache *iint, 213 209 const unsigned char *filename); 214 210 int ima_alloc_init_template(struct ima_event_data *event_data, 215 - struct ima_template_entry **entry); 211 + struct ima_template_entry **entry, 212 + struct ima_template_desc *template_desc); 216 213 int ima_store_template(struct ima_template_entry *entry, int violation, 217 214 struct inode *inode, 218 215 const unsigned char *filename, int pcr); ··· 223 216 224 217 /* IMA policy related functions */ 225 218 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, 226 - enum ima_hooks func, int mask, int flags, int *pcr); 219 + enum ima_hooks func, int mask, int flags, int *pcr, 220 + struct ima_template_desc **template_desc); 227 221 void ima_init_policy(void); 228 222 void ima_update_policy(void); 229 223 void ima_update_policy_flag(void);
+17 -7
security/integrity/ima/ima_api.c
··· 38 38 * ima_alloc_init_template - create and initialize a new template entry 39 39 */ 40 40 int ima_alloc_init_template(struct ima_event_data *event_data, 41 - struct ima_template_entry **entry) 41 + struct ima_template_entry **entry, 42 + struct ima_template_desc *desc) 42 43 { 43 - struct ima_template_desc *template_desc = ima_template_desc_current(); 44 + struct ima_template_desc *template_desc; 44 45 int i, result = 0; 46 + 47 + if (desc) 48 + template_desc = desc; 49 + else 50 + template_desc = ima_template_desc_current(); 45 51 46 52 *entry = kzalloc(sizeof(**entry) + template_desc->num_fields * 47 53 sizeof(struct ima_field_data), GFP_NOFS); ··· 149 143 /* can overflow, only indicator */ 150 144 atomic_long_inc(&ima_htable.violations); 151 145 152 - result = ima_alloc_init_template(&event_data, &entry); 146 + result = ima_alloc_init_template(&event_data, &entry, NULL); 153 147 if (result < 0) { 154 148 result = -ENOMEM; 155 149 goto err_out; ··· 172 166 * MAY_APPEND) 173 167 * @func: caller identifier 174 168 * @pcr: pointer filled in if matched measure policy sets pcr= 169 + * @template_desc: pointer filled in if matched measure policy sets template= 175 170 * 176 171 * The policy is defined in terms of keypairs: 177 172 * subj=, obj=, type=, func=, mask=, fsmagic= ··· 185 178 * 186 179 */ 187 180 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 188 - int mask, enum ima_hooks func, int *pcr) 181 + int mask, enum ima_hooks func, int *pcr, 182 + struct ima_template_desc **template_desc) 189 183 { 190 184 int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; 191 185 192 186 flags &= ima_policy_flag; 193 187 194 - return ima_match_policy(inode, cred, secid, func, mask, flags, pcr); 188 + return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, 189 + template_desc); 195 190 } 196 191 197 192 /* ··· 288 279 void ima_store_measurement(struct integrity_iint_cache *iint, 289 280 struct file *file, const unsigned char *filename, 290 281 struct evm_ima_xattr_data *xattr_value, 291 - int xattr_len, int pcr) 282 + int xattr_len, int pcr, 283 + struct ima_template_desc *template_desc) 292 284 { 293 285 static const char op[] = "add_template_measure"; 294 286 static const char audit_cause[] = "ENOMEM"; ··· 306 296 if (iint->measured_pcrs & (0x1 << pcr)) 307 297 return; 308 298 309 - result = ima_alloc_init_template(&event_data, &entry); 299 + result = ima_alloc_init_template(&event_data, &entry, template_desc); 310 300 if (result < 0) { 311 301 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, 312 302 op, audit_cause, result, 0);
+1 -1
security/integrity/ima/ima_appraise.c
··· 57 57 58 58 security_task_getsecid(current, &secid); 59 59 return ima_match_policy(inode, current_cred(), secid, func, mask, 60 - IMA_APPRAISE | IMA_HASH, NULL); 60 + IMA_APPRAISE | IMA_HASH, NULL, NULL); 61 61 } 62 62 63 63 static int ima_fix_xattr(struct dentry *dentry,
+1 -1
security/integrity/ima/ima_init.c
··· 72 72 } 73 73 } 74 74 75 - result = ima_alloc_init_template(&event_data, &entry); 75 + result = ima_alloc_init_template(&event_data, &entry, NULL); 76 76 if (result < 0) { 77 77 audit_cause = "alloc_entry"; 78 78 goto err_out;
+5 -4
security/integrity/ima/ima_main.c
··· 199 199 { 200 200 struct inode *inode = file_inode(file); 201 201 struct integrity_iint_cache *iint = NULL; 202 - struct ima_template_desc *template_desc; 202 + struct ima_template_desc *template_desc = NULL; 203 203 char *pathbuf = NULL; 204 204 char filename[NAME_MAX]; 205 205 const char *pathname = NULL; ··· 217 217 * bitmask based on the appraise/audit/measurement policy. 218 218 * Included is the appraise submask. 219 219 */ 220 - action = ima_get_action(inode, cred, secid, mask, func, &pcr); 220 + action = ima_get_action(inode, cred, secid, mask, func, &pcr, 221 + &template_desc); 221 222 violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && 222 223 (ima_policy_flag & IMA_MEASURE)); 223 224 if (!action && !violation_check) ··· 305 304 goto out_locked; 306 305 } 307 306 308 - template_desc = ima_template_desc_current(); 309 307 if ((action & IMA_APPRAISE_SUBMASK) || 310 308 strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) 311 309 /* read 'security.ima' */ ··· 321 321 322 322 if (action & IMA_MEASURE) 323 323 ima_store_measurement(iint, file, pathname, 324 - xattr_value, xattr_len, pcr); 324 + xattr_value, xattr_len, pcr, 325 + template_desc); 325 326 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { 326 327 inode_lock(inode); 327 328 rc = ima_appraise_measurement(func, iint, file, pathname,
+36 -2
security/integrity/ima/ima_policy.c
··· 80 80 int type; /* audit type */ 81 81 } lsm[MAX_LSM_RULES]; 82 82 char *fsname; 83 + struct ima_template_desc *template; 83 84 }; 84 85 85 86 /* ··· 474 473 * @func: IMA hook identifier 475 474 * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) 476 475 * @pcr: set the pcr to extend 476 + * @template_desc: the template that should be used for this rule 477 477 * 478 478 * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) 479 479 * conditions. ··· 484 482 * than writes so ima_match_policy() is classical RCU candidate. 485 483 */ 486 484 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, 487 - enum ima_hooks func, int mask, int flags, int *pcr) 485 + enum ima_hooks func, int mask, int flags, int *pcr, 486 + struct ima_template_desc **template_desc) 488 487 { 489 488 struct ima_rule_entry *entry; 490 489 int action = 0, actmask = flags | (flags << 1); ··· 516 513 517 514 if ((pcr) && (entry->flags & IMA_PCR)) 518 515 *pcr = entry->pcr; 516 + 517 + if (template_desc && entry->template) 518 + *template_desc = entry->template; 519 + else if (template_desc) 520 + *template_desc = ima_template_desc_current(); 519 521 520 522 if (!actmask) 521 523 break; ··· 760 752 Opt_uid_gt, Opt_euid_gt, Opt_fowner_gt, 761 753 Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt, 762 754 Opt_appraise_type, Opt_permit_directio, 763 - Opt_pcr, Opt_err 755 + Opt_pcr, Opt_template, Opt_err 764 756 }; 765 757 766 758 static const match_table_t policy_tokens = { ··· 794 786 {Opt_appraise_type, "appraise_type=%s"}, 795 787 {Opt_permit_directio, "permit_directio"}, 796 788 {Opt_pcr, "pcr=%s"}, 789 + {Opt_template, "template=%s"}, 797 790 {Opt_err, NULL} 798 791 }; 799 792 ··· 848 839 char *from; 849 840 char *p; 850 841 bool uid_token; 842 + struct ima_template_desc *template_desc; 851 843 int result = 0; 852 844 853 845 ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, ··· 1145 1135 entry->flags |= IMA_PCR; 1146 1136 1147 1137 break; 1138 + case Opt_template: 1139 + ima_log_string(ab, "template", args[0].from); 1140 + if (entry->action != MEASURE) { 1141 + result = -EINVAL; 1142 + break; 1143 + } 1144 + template_desc = lookup_template_desc(args[0].from); 1145 + if (!template_desc || entry->template) { 1146 + result = -EINVAL; 1147 + break; 1148 + } 1149 + 1150 + /* 1151 + * template_desc_init_fields() does nothing if 1152 + * the template is already initialised, so 1153 + * it's safe to do this unconditionally 1154 + */ 1155 + template_desc_init_fields(template_desc->fmt, 1156 + &(template_desc->fields), 1157 + &(template_desc->num_fields)); 1158 + entry->template = template_desc; 1159 + break; 1148 1160 case Opt_err: 1149 1161 ima_log_string(ab, "UNKNOWN", p); 1150 1162 result = -EINVAL; ··· 1442 1410 } 1443 1411 } 1444 1412 } 1413 + if (entry->template) 1414 + seq_printf(m, "template=%s ", entry->template->name); 1445 1415 if (entry->flags & IMA_DIGSIG_REQUIRED) 1446 1416 seq_puts(m, "appraise_type=imasig "); 1447 1417 if (entry->flags & IMA_PERMIT_DIRECTIO)
+4 -8
security/integrity/ima/ima_template.c
··· 47 47 #define MAX_TEMPLATE_NAME_LEN 15 48 48 49 49 static struct ima_template_desc *ima_template; 50 - static struct ima_template_desc *lookup_template_desc(const char *name); 51 - static int template_desc_init_fields(const char *template_fmt, 52 - const struct ima_template_field ***fields, 53 - int *num_fields); 54 50 55 51 static int __init ima_template_setup(char *str) 56 52 { ··· 104 108 } 105 109 __setup("ima_template_fmt=", ima_template_fmt_setup); 106 110 107 - static struct ima_template_desc *lookup_template_desc(const char *name) 111 + struct ima_template_desc *lookup_template_desc(const char *name) 108 112 { 109 113 struct ima_template_desc *template_desc; 110 114 int found = 0; ··· 149 153 return j + 1; 150 154 } 151 155 152 - static int template_desc_init_fields(const char *template_fmt, 153 - const struct ima_template_field ***fields, 154 - int *num_fields) 156 + int template_desc_init_fields(const char *template_fmt, 157 + const struct ima_template_field ***fields, 158 + int *num_fields) 155 159 { 156 160 const char *template_fmt_ptr; 157 161 const struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];