1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 23ce1217dSRoberto Sassu /* 33ce1217dSRoberto Sassu * Copyright (C) 2013 Politecnico di Torino, Italy 43ce1217dSRoberto Sassu * TORSEC group -- http://security.polito.it 53ce1217dSRoberto Sassu * 63ce1217dSRoberto Sassu * Author: Roberto Sassu <roberto.sassu@polito.it> 73ce1217dSRoberto Sassu * 83ce1217dSRoberto Sassu * File: ima_template_lib.c 93ce1217dSRoberto Sassu * Library of supported template fields. 103ce1217dSRoberto Sassu */ 114d7aeee7SRoberto Sassu 123ce1217dSRoberto Sassu #include "ima_template_lib.h" 133ce1217dSRoberto Sassu 144d7aeee7SRoberto Sassu static bool ima_template_hash_algo_allowed(u8 algo) 154d7aeee7SRoberto Sassu { 164d7aeee7SRoberto Sassu if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5) 174d7aeee7SRoberto Sassu return true; 184d7aeee7SRoberto Sassu 194d7aeee7SRoberto Sassu return false; 204d7aeee7SRoberto Sassu } 214d7aeee7SRoberto Sassu 224d7aeee7SRoberto Sassu enum data_formats { 234d7aeee7SRoberto Sassu DATA_FMT_DIGEST = 0, 244d7aeee7SRoberto Sassu DATA_FMT_DIGEST_WITH_ALGO, 25bcbc9b0cSMimi Zohar DATA_FMT_STRING, 26bcbc9b0cSMimi Zohar DATA_FMT_HEX 274d7aeee7SRoberto Sassu }; 284d7aeee7SRoberto Sassu 293ce1217dSRoberto Sassu static int ima_write_template_field_data(const void *data, const u32 datalen, 303ce1217dSRoberto Sassu enum data_formats datafmt, 313ce1217dSRoberto Sassu struct ima_field_data *field_data) 323ce1217dSRoberto Sassu { 333ce1217dSRoberto Sassu u8 *buf, *buf_ptr; 34e3b64c26SRoberto Sassu u32 buflen = datalen; 353ce1217dSRoberto Sassu 36e3b64c26SRoberto Sassu if (datafmt == DATA_FMT_STRING) 373ce1217dSRoberto Sassu buflen = datalen + 1; 383ce1217dSRoberto Sassu 393ce1217dSRoberto Sassu buf = kzalloc(buflen, GFP_KERNEL); 403ce1217dSRoberto Sassu if (!buf) 413ce1217dSRoberto Sassu return -ENOMEM; 423ce1217dSRoberto Sassu 433ce1217dSRoberto Sassu memcpy(buf, data, datalen); 443ce1217dSRoberto Sassu 453ce1217dSRoberto Sassu /* 463ce1217dSRoberto Sassu * Replace all space characters with underscore for event names and 473ce1217dSRoberto Sassu * strings. This avoid that, during the parsing of a measurements list, 483ce1217dSRoberto Sassu * filenames with spaces or that end with the suffix ' (deleted)' are 493ce1217dSRoberto Sassu * split into multiple template fields (the space is the delimitator 503ce1217dSRoberto Sassu * character for measurements lists in ASCII format). 513ce1217dSRoberto Sassu */ 52e3b64c26SRoberto Sassu if (datafmt == DATA_FMT_STRING) { 533ce1217dSRoberto Sassu for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++) 543ce1217dSRoberto Sassu if (*buf_ptr == ' ') 553ce1217dSRoberto Sassu *buf_ptr = '_'; 563ce1217dSRoberto Sassu } 573ce1217dSRoberto Sassu 583ce1217dSRoberto Sassu field_data->data = buf; 593ce1217dSRoberto Sassu field_data->len = buflen; 603ce1217dSRoberto Sassu return 0; 613ce1217dSRoberto Sassu } 623ce1217dSRoberto Sassu 633ce1217dSRoberto Sassu static void ima_show_template_data_ascii(struct seq_file *m, 643ce1217dSRoberto Sassu enum ima_show_type show, 653ce1217dSRoberto Sassu enum data_formats datafmt, 663ce1217dSRoberto Sassu struct ima_field_data *field_data) 673ce1217dSRoberto Sassu { 6845b26133SMimi Zohar u8 *buf_ptr = field_data->data; 6945b26133SMimi Zohar u32 buflen = field_data->len; 704d7aeee7SRoberto Sassu 713ce1217dSRoberto Sassu switch (datafmt) { 724d7aeee7SRoberto Sassu case DATA_FMT_DIGEST_WITH_ALGO: 734d7aeee7SRoberto Sassu buf_ptr = strnchr(field_data->data, buflen, ':'); 744d7aeee7SRoberto Sassu if (buf_ptr != field_data->data) 754d7aeee7SRoberto Sassu seq_printf(m, "%s", field_data->data); 764d7aeee7SRoberto Sassu 774d7aeee7SRoberto Sassu /* skip ':' and '\0' */ 784d7aeee7SRoberto Sassu buf_ptr += 2; 794d7aeee7SRoberto Sassu buflen -= buf_ptr - field_data->data; 8009186e50SGustavo A. R. Silva /* fall through */ 813ce1217dSRoberto Sassu case DATA_FMT_DIGEST: 82bcbc9b0cSMimi Zohar case DATA_FMT_HEX: 83bcbc9b0cSMimi Zohar if (!buflen) 84bcbc9b0cSMimi Zohar break; 854d7aeee7SRoberto Sassu ima_print_digest(m, buf_ptr, buflen); 863ce1217dSRoberto Sassu break; 873ce1217dSRoberto Sassu case DATA_FMT_STRING: 884d7aeee7SRoberto Sassu seq_printf(m, "%s", buf_ptr); 893ce1217dSRoberto Sassu break; 903ce1217dSRoberto Sassu default: 913ce1217dSRoberto Sassu break; 923ce1217dSRoberto Sassu } 933ce1217dSRoberto Sassu } 943ce1217dSRoberto Sassu 953ce1217dSRoberto Sassu static void ima_show_template_data_binary(struct seq_file *m, 963ce1217dSRoberto Sassu enum ima_show_type show, 973ce1217dSRoberto Sassu enum data_formats datafmt, 983ce1217dSRoberto Sassu struct ima_field_data *field_data) 993ce1217dSRoberto Sassu { 100c019e307SRoberto Sassu u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ? 101c019e307SRoberto Sassu strlen(field_data->data) : field_data->len; 1023e8e5503SRoberto Sassu 103d68a6fe9SMimi Zohar if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) { 104d68a6fe9SMimi Zohar u32 field_len = !ima_canonical_fmt ? len : cpu_to_le32(len); 105d68a6fe9SMimi Zohar 106d68a6fe9SMimi Zohar ima_putc(m, &field_len, sizeof(field_len)); 107d68a6fe9SMimi Zohar } 108c019e307SRoberto Sassu 109c019e307SRoberto Sassu if (!len) 1103ce1217dSRoberto Sassu return; 1113e8e5503SRoberto Sassu 112c019e307SRoberto Sassu ima_putc(m, field_data->data, len); 1133ce1217dSRoberto Sassu } 1143ce1217dSRoberto Sassu 1153ce1217dSRoberto Sassu static void ima_show_template_field_data(struct seq_file *m, 1163ce1217dSRoberto Sassu enum ima_show_type show, 1173ce1217dSRoberto Sassu enum data_formats datafmt, 1183ce1217dSRoberto Sassu struct ima_field_data *field_data) 1193ce1217dSRoberto Sassu { 1203ce1217dSRoberto Sassu switch (show) { 1213ce1217dSRoberto Sassu case IMA_SHOW_ASCII: 1223ce1217dSRoberto Sassu ima_show_template_data_ascii(m, show, datafmt, field_data); 1233ce1217dSRoberto Sassu break; 1243ce1217dSRoberto Sassu case IMA_SHOW_BINARY: 1253e8e5503SRoberto Sassu case IMA_SHOW_BINARY_NO_FIELD_LEN: 126c019e307SRoberto Sassu case IMA_SHOW_BINARY_OLD_STRING_FMT: 1273ce1217dSRoberto Sassu ima_show_template_data_binary(m, show, datafmt, field_data); 1283ce1217dSRoberto Sassu break; 1293ce1217dSRoberto Sassu default: 1303ce1217dSRoberto Sassu break; 1313ce1217dSRoberto Sassu } 1323ce1217dSRoberto Sassu } 1333ce1217dSRoberto Sassu 1343ce1217dSRoberto Sassu void ima_show_template_digest(struct seq_file *m, enum ima_show_type show, 1353ce1217dSRoberto Sassu struct ima_field_data *field_data) 1363ce1217dSRoberto Sassu { 1373ce1217dSRoberto Sassu ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data); 1383ce1217dSRoberto Sassu } 1393ce1217dSRoberto Sassu 1404d7aeee7SRoberto Sassu void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, 1414d7aeee7SRoberto Sassu struct ima_field_data *field_data) 1424d7aeee7SRoberto Sassu { 1434d7aeee7SRoberto Sassu ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO, 1444d7aeee7SRoberto Sassu field_data); 1454d7aeee7SRoberto Sassu } 1464d7aeee7SRoberto Sassu 1473ce1217dSRoberto Sassu void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 1483ce1217dSRoberto Sassu struct ima_field_data *field_data) 1493ce1217dSRoberto Sassu { 1503ce1217dSRoberto Sassu ima_show_template_field_data(m, show, DATA_FMT_STRING, field_data); 1513ce1217dSRoberto Sassu } 1523ce1217dSRoberto Sassu 153bcbc9b0cSMimi Zohar void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, 154bcbc9b0cSMimi Zohar struct ima_field_data *field_data) 155bcbc9b0cSMimi Zohar { 156bcbc9b0cSMimi Zohar ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data); 157bcbc9b0cSMimi Zohar } 158bcbc9b0cSMimi Zohar 15986b4da8cSPrakhar Srivastava void ima_show_template_buf(struct seq_file *m, enum ima_show_type show, 16086b4da8cSPrakhar Srivastava struct ima_field_data *field_data) 16186b4da8cSPrakhar Srivastava { 16286b4da8cSPrakhar Srivastava ima_show_template_field_data(m, show, DATA_FMT_HEX, field_data); 16386b4da8cSPrakhar Srivastava } 16486b4da8cSPrakhar Srivastava 165b17fd9ecSRoberto Sassu /** 166b17fd9ecSRoberto Sassu * ima_parse_buf() - Parses lengths and data from an input buffer 167b17fd9ecSRoberto Sassu * @bufstartp: Buffer start address. 168b17fd9ecSRoberto Sassu * @bufendp: Buffer end address. 169b17fd9ecSRoberto Sassu * @bufcurp: Pointer to remaining (non-parsed) data. 170b17fd9ecSRoberto Sassu * @maxfields: Length of fields array. 171b17fd9ecSRoberto Sassu * @fields: Array containing lengths and pointers of parsed data. 172b17fd9ecSRoberto Sassu * @curfields: Number of array items containing parsed data. 173b17fd9ecSRoberto Sassu * @len_mask: Bitmap (if bit is set, data length should not be parsed). 174b17fd9ecSRoberto Sassu * @enforce_mask: Check if curfields == maxfields and/or bufcurp == bufendp. 175b17fd9ecSRoberto Sassu * @bufname: String identifier of the input buffer. 176b17fd9ecSRoberto Sassu * 177b17fd9ecSRoberto Sassu * Return: 0 on success, -EINVAL on error. 178b17fd9ecSRoberto Sassu */ 179b17fd9ecSRoberto Sassu int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp, 180b17fd9ecSRoberto Sassu int maxfields, struct ima_field_data *fields, int *curfields, 181b17fd9ecSRoberto Sassu unsigned long *len_mask, int enforce_mask, char *bufname) 182b17fd9ecSRoberto Sassu { 183b17fd9ecSRoberto Sassu void *bufp = bufstartp; 184b17fd9ecSRoberto Sassu int i; 185b17fd9ecSRoberto Sassu 186b17fd9ecSRoberto Sassu for (i = 0; i < maxfields; i++) { 187b17fd9ecSRoberto Sassu if (len_mask == NULL || !test_bit(i, len_mask)) { 188b17fd9ecSRoberto Sassu if (bufp > (bufendp - sizeof(u32))) 189b17fd9ecSRoberto Sassu break; 190b17fd9ecSRoberto Sassu 191b17fd9ecSRoberto Sassu fields[i].len = *(u32 *)bufp; 192b17fd9ecSRoberto Sassu if (ima_canonical_fmt) 193b17fd9ecSRoberto Sassu fields[i].len = le32_to_cpu(fields[i].len); 194b17fd9ecSRoberto Sassu 195b17fd9ecSRoberto Sassu bufp += sizeof(u32); 196b17fd9ecSRoberto Sassu } 197b17fd9ecSRoberto Sassu 198b17fd9ecSRoberto Sassu if (bufp > (bufendp - fields[i].len)) 199b17fd9ecSRoberto Sassu break; 200b17fd9ecSRoberto Sassu 201b17fd9ecSRoberto Sassu fields[i].data = bufp; 202b17fd9ecSRoberto Sassu bufp += fields[i].len; 203b17fd9ecSRoberto Sassu } 204b17fd9ecSRoberto Sassu 205b17fd9ecSRoberto Sassu if ((enforce_mask & ENFORCE_FIELDS) && i != maxfields) { 206b17fd9ecSRoberto Sassu pr_err("%s: nr of fields mismatch: expected: %d, current: %d\n", 207b17fd9ecSRoberto Sassu bufname, maxfields, i); 208b17fd9ecSRoberto Sassu return -EINVAL; 209b17fd9ecSRoberto Sassu } 210b17fd9ecSRoberto Sassu 211b17fd9ecSRoberto Sassu if ((enforce_mask & ENFORCE_BUFEND) && bufp != bufendp) { 212b17fd9ecSRoberto Sassu pr_err("%s: buf end mismatch: expected: %p, current: %p\n", 213b17fd9ecSRoberto Sassu bufname, bufendp, bufp); 214b17fd9ecSRoberto Sassu return -EINVAL; 215b17fd9ecSRoberto Sassu } 216b17fd9ecSRoberto Sassu 217b17fd9ecSRoberto Sassu if (curfields) 218b17fd9ecSRoberto Sassu *curfields = i; 219b17fd9ecSRoberto Sassu 220b17fd9ecSRoberto Sassu if (bufcurp) 221b17fd9ecSRoberto Sassu *bufcurp = bufp; 222b17fd9ecSRoberto Sassu 223b17fd9ecSRoberto Sassu return 0; 224b17fd9ecSRoberto Sassu } 225b17fd9ecSRoberto Sassu 2263878d505SThiago Jung Bauermann static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize, 2273878d505SThiago Jung Bauermann u8 hash_algo, 228dcf4e392SRoberto Sassu struct ima_field_data *field_data) 2294d7aeee7SRoberto Sassu { 2303ce1217dSRoberto Sassu /* 2314d7aeee7SRoberto Sassu * digest formats: 2324d7aeee7SRoberto Sassu * - DATA_FMT_DIGEST: digest 2334d7aeee7SRoberto Sassu * - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest, 2344d7aeee7SRoberto Sassu * where <hash algo> is provided if the hash algoritm is not 2354d7aeee7SRoberto Sassu * SHA1 or MD5 2364d7aeee7SRoberto Sassu */ 2374d7aeee7SRoberto Sassu u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 }; 2384d7aeee7SRoberto Sassu enum data_formats fmt = DATA_FMT_DIGEST; 2394d7aeee7SRoberto Sassu u32 offset = 0; 2404d7aeee7SRoberto Sassu 241dcf4e392SRoberto Sassu if (hash_algo < HASH_ALGO__LAST) { 2424d7aeee7SRoberto Sassu fmt = DATA_FMT_DIGEST_WITH_ALGO; 243dcf4e392SRoberto Sassu offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", 244dcf4e392SRoberto Sassu hash_algo_name[hash_algo]); 2454d7aeee7SRoberto Sassu buffer[offset] = ':'; 2464d7aeee7SRoberto Sassu offset += 2; 2474d7aeee7SRoberto Sassu } 2484d7aeee7SRoberto Sassu 2494d7aeee7SRoberto Sassu if (digest) 2504d7aeee7SRoberto Sassu memcpy(buffer + offset, digest, digestsize); 2514d7aeee7SRoberto Sassu else 2524d7aeee7SRoberto Sassu /* 2534d7aeee7SRoberto Sassu * If digest is NULL, the event being recorded is a violation. 2544d7aeee7SRoberto Sassu * Make room for the digest by increasing the offset of 2554d7aeee7SRoberto Sassu * IMA_DIGEST_SIZE. 2564d7aeee7SRoberto Sassu */ 2574d7aeee7SRoberto Sassu offset += IMA_DIGEST_SIZE; 2584d7aeee7SRoberto Sassu 2594d7aeee7SRoberto Sassu return ima_write_template_field_data(buffer, offset + digestsize, 2604d7aeee7SRoberto Sassu fmt, field_data); 2614d7aeee7SRoberto Sassu } 2624d7aeee7SRoberto Sassu 2634d7aeee7SRoberto Sassu /* 2644d7aeee7SRoberto Sassu * This function writes the digest of an event (with size limit). 2653ce1217dSRoberto Sassu */ 26623b57419SRoberto Sassu int ima_eventdigest_init(struct ima_event_data *event_data, 2673ce1217dSRoberto Sassu struct ima_field_data *field_data) 2683ce1217dSRoberto Sassu { 2693ce1217dSRoberto Sassu struct { 2703ce1217dSRoberto Sassu struct ima_digest_data hdr; 2713ce1217dSRoberto Sassu char digest[IMA_MAX_DIGEST_SIZE]; 2723ce1217dSRoberto Sassu } hash; 2734d7aeee7SRoberto Sassu u8 *cur_digest = NULL; 2744d7aeee7SRoberto Sassu u32 cur_digestsize = 0; 2753ce1217dSRoberto Sassu struct inode *inode; 2763ce1217dSRoberto Sassu int result; 2773ce1217dSRoberto Sassu 2783ce1217dSRoberto Sassu memset(&hash, 0, sizeof(hash)); 2793ce1217dSRoberto Sassu 2808d94eb9bSRoberto Sassu if (event_data->violation) /* recording a violation. */ 2813ce1217dSRoberto Sassu goto out; 2823ce1217dSRoberto Sassu 28323b57419SRoberto Sassu if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) { 28423b57419SRoberto Sassu cur_digest = event_data->iint->ima_hash->digest; 28523b57419SRoberto Sassu cur_digestsize = event_data->iint->ima_hash->length; 2863ce1217dSRoberto Sassu goto out; 2873ce1217dSRoberto Sassu } 2883ce1217dSRoberto Sassu 289*6cc7c266SRoberto Sassu if ((const char *)event_data->filename == boot_aggregate_name) { 290*6cc7c266SRoberto Sassu if (ima_tpm_chip) { 291*6cc7c266SRoberto Sassu hash.hdr.algo = HASH_ALGO_SHA1; 292*6cc7c266SRoberto Sassu result = ima_calc_boot_aggregate(&hash.hdr); 293*6cc7c266SRoberto Sassu 294*6cc7c266SRoberto Sassu /* algo can change depending on available PCR banks */ 295*6cc7c266SRoberto Sassu if (!result && hash.hdr.algo != HASH_ALGO_SHA1) 296*6cc7c266SRoberto Sassu result = -EINVAL; 297*6cc7c266SRoberto Sassu 298*6cc7c266SRoberto Sassu if (result < 0) 299*6cc7c266SRoberto Sassu memset(&hash, 0, sizeof(hash)); 300*6cc7c266SRoberto Sassu } 301*6cc7c266SRoberto Sassu 302*6cc7c266SRoberto Sassu cur_digest = hash.hdr.digest; 303*6cc7c266SRoberto Sassu cur_digestsize = hash_digest_size[HASH_ALGO_SHA1]; 304*6cc7c266SRoberto Sassu goto out; 305*6cc7c266SRoberto Sassu } 306*6cc7c266SRoberto Sassu 30723b57419SRoberto Sassu if (!event_data->file) /* missing info to re-calculate the digest */ 3083ce1217dSRoberto Sassu return -EINVAL; 3093ce1217dSRoberto Sassu 31023b57419SRoberto Sassu inode = file_inode(event_data->file); 3114d7aeee7SRoberto Sassu hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ? 3124d7aeee7SRoberto Sassu ima_hash_algo : HASH_ALGO_SHA1; 31323b57419SRoberto Sassu result = ima_calc_file_hash(event_data->file, &hash.hdr); 3143ce1217dSRoberto Sassu if (result) { 3153ce1217dSRoberto Sassu integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 31623b57419SRoberto Sassu event_data->filename, "collect_data", 3173ce1217dSRoberto Sassu "failed", result, 0); 3183ce1217dSRoberto Sassu return result; 3193ce1217dSRoberto Sassu } 3204d7aeee7SRoberto Sassu cur_digest = hash.hdr.digest; 3214d7aeee7SRoberto Sassu cur_digestsize = hash.hdr.length; 3223ce1217dSRoberto Sassu out: 323712a49bdSRoberto Sassu return ima_eventdigest_init_common(cur_digest, cur_digestsize, 324dcf4e392SRoberto Sassu HASH_ALGO__LAST, field_data); 3253ce1217dSRoberto Sassu } 3263ce1217dSRoberto Sassu 3273ce1217dSRoberto Sassu /* 3284d7aeee7SRoberto Sassu * This function writes the digest of an event (without size limit). 3293ce1217dSRoberto Sassu */ 33023b57419SRoberto Sassu int ima_eventdigest_ng_init(struct ima_event_data *event_data, 33123b57419SRoberto Sassu struct ima_field_data *field_data) 3323ce1217dSRoberto Sassu { 333c502c78bSRoberto Sassu u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; 3344d7aeee7SRoberto Sassu u32 cur_digestsize = 0; 3354d7aeee7SRoberto Sassu 3368d94eb9bSRoberto Sassu if (event_data->violation) /* recording a violation. */ 3374d7aeee7SRoberto Sassu goto out; 3384d7aeee7SRoberto Sassu 33923b57419SRoberto Sassu cur_digest = event_data->iint->ima_hash->digest; 34023b57419SRoberto Sassu cur_digestsize = event_data->iint->ima_hash->length; 3414d7aeee7SRoberto Sassu 34223b57419SRoberto Sassu hash_algo = event_data->iint->ima_hash->algo; 3434d7aeee7SRoberto Sassu out: 3444d7aeee7SRoberto Sassu return ima_eventdigest_init_common(cur_digest, cur_digestsize, 345dcf4e392SRoberto Sassu hash_algo, field_data); 3464d7aeee7SRoberto Sassu } 3474d7aeee7SRoberto Sassu 3483878d505SThiago Jung Bauermann /* 3493878d505SThiago Jung Bauermann * This function writes the digest of the file which is expected to match the 3503878d505SThiago Jung Bauermann * digest contained in the file's appended signature. 3513878d505SThiago Jung Bauermann */ 3523878d505SThiago Jung Bauermann int ima_eventdigest_modsig_init(struct ima_event_data *event_data, 3533878d505SThiago Jung Bauermann struct ima_field_data *field_data) 3543878d505SThiago Jung Bauermann { 3553878d505SThiago Jung Bauermann enum hash_algo hash_algo; 3563878d505SThiago Jung Bauermann const u8 *cur_digest; 3573878d505SThiago Jung Bauermann u32 cur_digestsize; 3583878d505SThiago Jung Bauermann 3593878d505SThiago Jung Bauermann if (!event_data->modsig) 3603878d505SThiago Jung Bauermann return 0; 3613878d505SThiago Jung Bauermann 3623878d505SThiago Jung Bauermann if (event_data->violation) { 3633878d505SThiago Jung Bauermann /* Recording a violation. */ 3643878d505SThiago Jung Bauermann hash_algo = HASH_ALGO_SHA1; 3653878d505SThiago Jung Bauermann cur_digest = NULL; 3663878d505SThiago Jung Bauermann cur_digestsize = 0; 3673878d505SThiago Jung Bauermann } else { 3683878d505SThiago Jung Bauermann int rc; 3693878d505SThiago Jung Bauermann 3703878d505SThiago Jung Bauermann rc = ima_get_modsig_digest(event_data->modsig, &hash_algo, 3713878d505SThiago Jung Bauermann &cur_digest, &cur_digestsize); 3723878d505SThiago Jung Bauermann if (rc) 3733878d505SThiago Jung Bauermann return rc; 3743878d505SThiago Jung Bauermann else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0) 3753878d505SThiago Jung Bauermann /* There was some error collecting the digest. */ 3763878d505SThiago Jung Bauermann return -EINVAL; 3773878d505SThiago Jung Bauermann } 3783878d505SThiago Jung Bauermann 3793878d505SThiago Jung Bauermann return ima_eventdigest_init_common(cur_digest, cur_digestsize, 3803878d505SThiago Jung Bauermann hash_algo, field_data); 3813878d505SThiago Jung Bauermann } 3823878d505SThiago Jung Bauermann 38323b57419SRoberto Sassu static int ima_eventname_init_common(struct ima_event_data *event_data, 3844d7aeee7SRoberto Sassu struct ima_field_data *field_data, 3854d7aeee7SRoberto Sassu bool size_limit) 3864d7aeee7SRoberto Sassu { 3873ce1217dSRoberto Sassu const char *cur_filename = NULL; 3883ce1217dSRoberto Sassu u32 cur_filename_len = 0; 3893ce1217dSRoberto Sassu 39023b57419SRoberto Sassu BUG_ON(event_data->filename == NULL && event_data->file == NULL); 3913ce1217dSRoberto Sassu 39223b57419SRoberto Sassu if (event_data->filename) { 39323b57419SRoberto Sassu cur_filename = event_data->filename; 39423b57419SRoberto Sassu cur_filename_len = strlen(event_data->filename); 3953ce1217dSRoberto Sassu 3964d7aeee7SRoberto Sassu if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX) 3973ce1217dSRoberto Sassu goto out; 3983ce1217dSRoberto Sassu } 3993ce1217dSRoberto Sassu 40023b57419SRoberto Sassu if (event_data->file) { 40123b57419SRoberto Sassu cur_filename = event_data->file->f_path.dentry->d_name.name; 4023ce1217dSRoberto Sassu cur_filename_len = strlen(cur_filename); 4033ce1217dSRoberto Sassu } else 4043ce1217dSRoberto Sassu /* 4053ce1217dSRoberto Sassu * Truncate filename if the latter is too long and 4063ce1217dSRoberto Sassu * the file descriptor is not available. 4073ce1217dSRoberto Sassu */ 4083ce1217dSRoberto Sassu cur_filename_len = IMA_EVENT_NAME_LEN_MAX; 4093ce1217dSRoberto Sassu out: 4103ce1217dSRoberto Sassu return ima_write_template_field_data(cur_filename, cur_filename_len, 411e3b64c26SRoberto Sassu DATA_FMT_STRING, field_data); 4124d7aeee7SRoberto Sassu } 4134d7aeee7SRoberto Sassu 4144d7aeee7SRoberto Sassu /* 4154d7aeee7SRoberto Sassu * This function writes the name of an event (with size limit). 4164d7aeee7SRoberto Sassu */ 41723b57419SRoberto Sassu int ima_eventname_init(struct ima_event_data *event_data, 4184d7aeee7SRoberto Sassu struct ima_field_data *field_data) 4194d7aeee7SRoberto Sassu { 42023b57419SRoberto Sassu return ima_eventname_init_common(event_data, field_data, true); 4214d7aeee7SRoberto Sassu } 4224d7aeee7SRoberto Sassu 4234d7aeee7SRoberto Sassu /* 4244d7aeee7SRoberto Sassu * This function writes the name of an event (without size limit). 4254d7aeee7SRoberto Sassu */ 42623b57419SRoberto Sassu int ima_eventname_ng_init(struct ima_event_data *event_data, 4274d7aeee7SRoberto Sassu struct ima_field_data *field_data) 4284d7aeee7SRoberto Sassu { 42923b57419SRoberto Sassu return ima_eventname_init_common(event_data, field_data, false); 4303ce1217dSRoberto Sassu } 431bcbc9b0cSMimi Zohar 432bcbc9b0cSMimi Zohar /* 433bcbc9b0cSMimi Zohar * ima_eventsig_init - include the file signature as part of the template data 434bcbc9b0cSMimi Zohar */ 43523b57419SRoberto Sassu int ima_eventsig_init(struct ima_event_data *event_data, 436bcbc9b0cSMimi Zohar struct ima_field_data *field_data) 437bcbc9b0cSMimi Zohar { 43823b57419SRoberto Sassu struct evm_ima_xattr_data *xattr_value = event_data->xattr_value; 439bcbc9b0cSMimi Zohar 440bcbc9b0cSMimi Zohar if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) 4411775cb87SThiago Jung Bauermann return 0; 442bcbc9b0cSMimi Zohar 4431775cb87SThiago Jung Bauermann return ima_write_template_field_data(xattr_value, event_data->xattr_len, 4441775cb87SThiago Jung Bauermann DATA_FMT_HEX, field_data); 445bcbc9b0cSMimi Zohar } 44686b4da8cSPrakhar Srivastava 44786b4da8cSPrakhar Srivastava /* 44886b4da8cSPrakhar Srivastava * ima_eventbuf_init - include the buffer(kexec-cmldine) as part of the 44986b4da8cSPrakhar Srivastava * template data. 45086b4da8cSPrakhar Srivastava */ 45186b4da8cSPrakhar Srivastava int ima_eventbuf_init(struct ima_event_data *event_data, 45286b4da8cSPrakhar Srivastava struct ima_field_data *field_data) 45386b4da8cSPrakhar Srivastava { 45486b4da8cSPrakhar Srivastava if ((!event_data->buf) || (event_data->buf_len == 0)) 45586b4da8cSPrakhar Srivastava return 0; 45686b4da8cSPrakhar Srivastava 45786b4da8cSPrakhar Srivastava return ima_write_template_field_data(event_data->buf, 45886b4da8cSPrakhar Srivastava event_data->buf_len, DATA_FMT_HEX, 45986b4da8cSPrakhar Srivastava field_data); 46086b4da8cSPrakhar Srivastava } 4613878d505SThiago Jung Bauermann 4623878d505SThiago Jung Bauermann /* 4633878d505SThiago Jung Bauermann * ima_eventmodsig_init - include the appended file signature as part of the 4643878d505SThiago Jung Bauermann * template data 4653878d505SThiago Jung Bauermann */ 4663878d505SThiago Jung Bauermann int ima_eventmodsig_init(struct ima_event_data *event_data, 4673878d505SThiago Jung Bauermann struct ima_field_data *field_data) 4683878d505SThiago Jung Bauermann { 4693878d505SThiago Jung Bauermann const void *data; 4703878d505SThiago Jung Bauermann u32 data_len; 4713878d505SThiago Jung Bauermann int rc; 4723878d505SThiago Jung Bauermann 4733878d505SThiago Jung Bauermann if (!event_data->modsig) 4743878d505SThiago Jung Bauermann return 0; 4753878d505SThiago Jung Bauermann 4763878d505SThiago Jung Bauermann /* 4773878d505SThiago Jung Bauermann * modsig is a runtime structure containing pointers. Get its raw data 4783878d505SThiago Jung Bauermann * instead. 4793878d505SThiago Jung Bauermann */ 4803878d505SThiago Jung Bauermann rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len); 4813878d505SThiago Jung Bauermann if (rc) 4823878d505SThiago Jung Bauermann return rc; 4833878d505SThiago Jung Bauermann 4843878d505SThiago Jung Bauermann return ima_write_template_field_data(data, data_len, DATA_FMT_HEX, 4853878d505SThiago Jung Bauermann field_data); 4863878d505SThiago Jung Bauermann } 487