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

ima: define a new template field named 'd-ngv2' and templates

In preparation to differentiate between unsigned regular IMA file
hashes and fs-verity's file digests in the IMA measurement list,
define a new template field named 'd-ngv2'.

Also define two new templates named 'ima-ngv2' and 'ima-sigv2', which
include the new 'd-ngv2' field.

Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

+79 -12
+2 -1
Documentation/admin-guide/kernel-parameters.txt
··· 1903 1903 1904 1904 ima_template= [IMA] 1905 1905 Select one of defined IMA measurements template formats. 1906 - Formats: { "ima" | "ima-ng" | "ima-sig" } 1906 + Formats: { "ima" | "ima-ng" | "ima-ngv2" | "ima-sig" | 1907 + "ima-sigv2" } 1907 1908 Default: "ima-ng" 1908 1909 1909 1910 ima_template_fmt=
+4
Documentation/security/IMA-templates.rst
··· 67 67 - 'n': the name of the event (i.e. the file name), with size up to 255 bytes; 68 68 - 'd-ng': the digest of the event, calculated with an arbitrary hash 69 69 algorithm (field format: <hash algo>:digest); 70 + - 'd-ngv2': same as d-ng, but prefixed with the "ima" digest type 71 + (field format: <digest type>:<hash algo>:digest); 70 72 - 'd-modsig': the digest of the event without the appended modsig; 71 73 - 'n-ng': the name of the event, without size limitations; 72 74 - 'sig': the file signature, or the EVM portable signature if the file ··· 89 87 90 88 - "ima": its format is ``d|n``; 91 89 - "ima-ng" (default): its format is ``d-ng|n-ng``; 90 + - "ima-ngv2": its format is ``d-ngv2|n-ng``; 92 91 - "ima-sig": its format is ``d-ng|n-ng|sig``; 92 + - "ima-sigv2": its format is ``d-ngv2|n-ng|sig``; 93 93 - "ima-buf": its format is ``d-ng|n-ng|buf``; 94 94 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``; 95 95 - "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;
+4
security/integrity/ima/ima_template.c
··· 20 20 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, 21 21 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 22 22 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 23 + {.name = "ima-ngv2", .fmt = "d-ngv2|n-ng"}, 24 + {.name = "ima-sigv2", .fmt = "d-ngv2|n-ng|sig"}, 23 25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, 24 26 {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"}, 25 27 {.name = "evm-sig", ··· 40 38 .field_show = ima_show_template_string}, 41 39 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init, 42 40 .field_show = ima_show_template_digest_ng}, 41 + {.field_id = "d-ngv2", .field_init = ima_eventdigest_ngv2_init, 42 + .field_show = ima_show_template_digest_ngv2}, 43 43 {.field_id = "n-ng", .field_init = ima_eventname_ng_init, 44 44 .field_show = ima_show_template_string}, 45 45 {.field_id = "sig", .field_init = ima_eventsig_init,
+65 -11
security/integrity/ima/ima_template_lib.c
··· 24 24 enum data_formats { 25 25 DATA_FMT_DIGEST = 0, 26 26 DATA_FMT_DIGEST_WITH_ALGO, 27 + DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO, 27 28 DATA_FMT_STRING, 28 29 DATA_FMT_HEX, 29 30 DATA_FMT_UINT 31 + }; 32 + 33 + enum digest_type { 34 + DIGEST_TYPE_IMA, 35 + DIGEST_TYPE__LAST 36 + }; 37 + 38 + #define DIGEST_TYPE_NAME_LEN_MAX 4 /* including NUL */ 39 + static const char * const digest_type_name[DIGEST_TYPE__LAST] = { 40 + [DIGEST_TYPE_IMA] = "ima" 30 41 }; 31 42 32 43 static int ima_write_template_field_data(const void *data, const u32 datalen, ··· 83 72 u32 buflen = field_data->len; 84 73 85 74 switch (datafmt) { 75 + case DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO: 86 76 case DATA_FMT_DIGEST_WITH_ALGO: 87 - buf_ptr = strnchr(field_data->data, buflen, ':'); 77 + buf_ptr = strrchr(field_data->data, ':'); 88 78 if (buf_ptr != field_data->data) 89 79 seq_printf(m, "%s", field_data->data); 90 80 ··· 190 178 field_data); 191 179 } 192 180 181 + void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show, 182 + struct ima_field_data *field_data) 183 + { 184 + ima_show_template_field_data(m, show, 185 + DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO, 186 + field_data); 187 + } 188 + 193 189 void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 194 190 struct ima_field_data *field_data) 195 191 { ··· 285 265 } 286 266 287 267 static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize, 288 - u8 hash_algo, 268 + u8 digest_type, u8 hash_algo, 289 269 struct ima_field_data *field_data) 290 270 { 291 271 /* 292 272 * digest formats: 293 273 * - DATA_FMT_DIGEST: digest 294 274 * - DATA_FMT_DIGEST_WITH_ALGO: <hash algo> + ':' + '\0' + digest, 275 + * - DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO: 276 + * <digest type> + ':' + <hash algo> + ':' + '\0' + digest, 295 277 * 296 278 * where 'DATA_FMT_DIGEST' is the original digest format ('d') 297 279 * with a hash size limitation of 20 bytes, 280 + * where <digest type> is "ima", 298 281 * where <hash algo> is the hash_algo_name[] string. 299 282 */ 300 - u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 }; 283 + u8 buffer[DIGEST_TYPE_NAME_LEN_MAX + CRYPTO_MAX_ALG_NAME + 2 + 284 + IMA_MAX_DIGEST_SIZE] = { 0 }; 301 285 enum data_formats fmt = DATA_FMT_DIGEST; 302 286 u32 offset = 0; 303 287 304 - if (hash_algo < HASH_ALGO__LAST) { 288 + if (digest_type < DIGEST_TYPE__LAST && hash_algo < HASH_ALGO__LAST) { 289 + fmt = DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO; 290 + offset += 1 + sprintf(buffer, "%s:%s:", 291 + digest_type_name[digest_type], 292 + hash_algo_name[hash_algo]); 293 + } else if (hash_algo < HASH_ALGO__LAST) { 305 294 fmt = DATA_FMT_DIGEST_WITH_ALGO; 306 - offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", 307 - hash_algo_name[hash_algo]); 308 - buffer[offset] = ':'; 309 - offset += 2; 295 + offset += 1 + sprintf(buffer, "%s:", 296 + hash_algo_name[hash_algo]); 310 297 } 311 298 312 299 if (digest) ··· 388 361 cur_digestsize = hash.hdr.length; 389 362 out: 390 363 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 391 - HASH_ALGO__LAST, field_data); 364 + DIGEST_TYPE__LAST, HASH_ALGO__LAST, 365 + field_data); 392 366 } 393 367 394 368 /* ··· 410 382 hash_algo = event_data->iint->ima_hash->algo; 411 383 out: 412 384 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 413 - hash_algo, field_data); 385 + DIGEST_TYPE__LAST, hash_algo, 386 + field_data); 387 + } 388 + 389 + /* 390 + * This function writes the digest of an event (without size limit), 391 + * prefixed with both the digest type and hash algorithm. 392 + */ 393 + int ima_eventdigest_ngv2_init(struct ima_event_data *event_data, 394 + struct ima_field_data *field_data) 395 + { 396 + u8 *cur_digest = NULL, hash_algo = ima_hash_algo; 397 + u32 cur_digestsize = 0; 398 + u8 digest_type = DIGEST_TYPE_IMA; 399 + 400 + if (event_data->violation) /* recording a violation. */ 401 + goto out; 402 + 403 + cur_digest = event_data->iint->ima_hash->digest; 404 + cur_digestsize = event_data->iint->ima_hash->length; 405 + 406 + hash_algo = event_data->iint->ima_hash->algo; 407 + out: 408 + return ima_eventdigest_init_common(cur_digest, cur_digestsize, 409 + digest_type, hash_algo, 410 + field_data); 414 411 } 415 412 416 413 /* ··· 470 417 } 471 418 472 419 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 473 - hash_algo, field_data); 420 + DIGEST_TYPE__LAST, hash_algo, 421 + field_data); 474 422 } 475 423 476 424 static int ima_eventname_init_common(struct ima_event_data *event_data,
+4
security/integrity/ima/ima_template_lib.h
··· 21 21 struct ima_field_data *field_data); 22 22 void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, 23 23 struct ima_field_data *field_data); 24 + void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show, 25 + struct ima_field_data *field_data); 24 26 void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 25 27 struct ima_field_data *field_data); 26 28 void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, ··· 40 38 struct ima_field_data *field_data); 41 39 int ima_eventdigest_ng_init(struct ima_event_data *event_data, 42 40 struct ima_field_data *field_data); 41 + int ima_eventdigest_ngv2_init(struct ima_event_data *event_data, 42 + struct ima_field_data *field_data); 43 43 int ima_eventdigest_modsig_init(struct ima_event_data *event_data, 44 44 struct ima_field_data *field_data); 45 45 int ima_eventname_ng_init(struct ima_event_data *event_data,