Skip to content

Commit 989dc72

Browse files
committed
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>
1 parent 246d921 commit 989dc72

File tree

5 files changed

+79
-12
lines changed

5 files changed

+79
-12
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,8 @@
19031903

19041904
ima_template= [IMA]
19051905
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" }
19071908
Default: "ima-ng"
19081909

19091910
ima_template_fmt=

Documentation/security/IMA-templates.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ descriptors by adding their identifier to the format string
6767
- 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
6868
- 'd-ng': the digest of the event, calculated with an arbitrary hash
6969
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);
7072
- 'd-modsig': the digest of the event without the appended modsig;
7173
- 'n-ng': the name of the event, without size limitations;
7274
- 'sig': the file signature, or the EVM portable signature if the file
@@ -87,7 +89,9 @@ Below, there is the list of defined template descriptors:
8789

8890
- "ima": its format is ``d|n``;
8991
- "ima-ng" (default): its format is ``d-ng|n-ng``;
92+
- "ima-ngv2": its format is ``d-ngv2|n-ng``;
9093
- "ima-sig": its format is ``d-ng|n-ng|sig``;
94+
- "ima-sigv2": its format is ``d-ngv2|n-ng|sig``;
9195
- "ima-buf": its format is ``d-ng|n-ng|buf``;
9296
- "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
9397
- "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;

security/integrity/ima/ima_template.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ static struct ima_template_desc builtin_templates[] = {
2020
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
2121
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
2222
{.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"},
2325
{.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
2426
{.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
2527
{.name = "evm-sig",
@@ -38,6 +40,8 @@ static const struct ima_template_field supported_fields[] = {
3840
.field_show = ima_show_template_string},
3941
{.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
4042
.field_show = ima_show_template_digest_ng},
43+
{.field_id = "d-ngv2", .field_init = ima_eventdigest_ngv2_init,
44+
.field_show = ima_show_template_digest_ngv2},
4145
{.field_id = "n-ng", .field_init = ima_eventname_ng_init,
4246
.field_show = ima_show_template_string},
4347
{.field_id = "sig", .field_init = ima_eventsig_init,

security/integrity/ima/ima_template_lib.c

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,22 @@ static bool ima_template_hash_algo_allowed(u8 algo)
2424
enum data_formats {
2525
DATA_FMT_DIGEST = 0,
2626
DATA_FMT_DIGEST_WITH_ALGO,
27+
DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
2728
DATA_FMT_STRING,
2829
DATA_FMT_HEX,
2930
DATA_FMT_UINT
3031
};
3132

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"
41+
};
42+
3243
static int ima_write_template_field_data(const void *data, const u32 datalen,
3344
enum data_formats datafmt,
3445
struct ima_field_data *field_data)
@@ -72,8 +83,9 @@ static void ima_show_template_data_ascii(struct seq_file *m,
7283
u32 buflen = field_data->len;
7384

7485
switch (datafmt) {
86+
case DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
7587
case DATA_FMT_DIGEST_WITH_ALGO:
76-
buf_ptr = strnchr(field_data->data, buflen, ':');
88+
buf_ptr = strrchr(field_data->data, ':');
7789
if (buf_ptr != field_data->data)
7890
seq_printf(m, "%s", field_data->data);
7991

@@ -178,6 +190,14 @@ void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
178190
field_data);
179191
}
180192

193+
void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show,
194+
struct ima_field_data *field_data)
195+
{
196+
ima_show_template_field_data(m, show,
197+
DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
198+
field_data);
199+
}
200+
181201
void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
182202
struct ima_field_data *field_data)
183203
{
@@ -265,28 +285,35 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
265285
}
266286

267287
static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
268-
u8 hash_algo,
288+
u8 digest_type, u8 hash_algo,
269289
struct ima_field_data *field_data)
270290
{
271291
/*
272292
* digest formats:
273293
* - DATA_FMT_DIGEST: digest
274294
* - DATA_FMT_DIGEST_WITH_ALGO: <hash algo> + ':' + '\0' + digest,
295+
* - DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
296+
* <digest type> + ':' + <hash algo> + ':' + '\0' + digest,
275297
*
276298
* where 'DATA_FMT_DIGEST' is the original digest format ('d')
277299
* with a hash size limitation of 20 bytes,
300+
* where <digest type> is "ima",
278301
* where <hash algo> is the hash_algo_name[] string.
279302
*/
280-
u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
303+
u8 buffer[DIGEST_TYPE_NAME_LEN_MAX + CRYPTO_MAX_ALG_NAME + 2 +
304+
IMA_MAX_DIGEST_SIZE] = { 0 };
281305
enum data_formats fmt = DATA_FMT_DIGEST;
282306
u32 offset = 0;
283307

284-
if (hash_algo < HASH_ALGO__LAST) {
308+
if (digest_type < DIGEST_TYPE__LAST && hash_algo < HASH_ALGO__LAST) {
309+
fmt = DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO;
310+
offset += 1 + sprintf(buffer, "%s:%s:",
311+
digest_type_name[digest_type],
312+
hash_algo_name[hash_algo]);
313+
} else if (hash_algo < HASH_ALGO__LAST) {
285314
fmt = DATA_FMT_DIGEST_WITH_ALGO;
286-
offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s",
287-
hash_algo_name[hash_algo]);
288-
buffer[offset] = ':';
289-
offset += 2;
315+
offset += 1 + sprintf(buffer, "%s:",
316+
hash_algo_name[hash_algo]);
290317
}
291318

292319
if (digest)
@@ -361,7 +388,8 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
361388
cur_digestsize = hash.hdr.length;
362389
out:
363390
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
364-
HASH_ALGO__LAST, field_data);
391+
DIGEST_TYPE__LAST, HASH_ALGO__LAST,
392+
field_data);
365393
}
366394

367395
/*
@@ -382,7 +410,32 @@ int ima_eventdigest_ng_init(struct ima_event_data *event_data,
382410
hash_algo = event_data->iint->ima_hash->algo;
383411
out:
384412
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
385-
hash_algo, field_data);
413+
DIGEST_TYPE__LAST, hash_algo,
414+
field_data);
415+
}
416+
417+
/*
418+
* This function writes the digest of an event (without size limit),
419+
* prefixed with both the digest type and hash algorithm.
420+
*/
421+
int ima_eventdigest_ngv2_init(struct ima_event_data *event_data,
422+
struct ima_field_data *field_data)
423+
{
424+
u8 *cur_digest = NULL, hash_algo = ima_hash_algo;
425+
u32 cur_digestsize = 0;
426+
u8 digest_type = DIGEST_TYPE_IMA;
427+
428+
if (event_data->violation) /* recording a violation. */
429+
goto out;
430+
431+
cur_digest = event_data->iint->ima_hash->digest;
432+
cur_digestsize = event_data->iint->ima_hash->length;
433+
434+
hash_algo = event_data->iint->ima_hash->algo;
435+
out:
436+
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
437+
digest_type, hash_algo,
438+
field_data);
386439
}
387440

388441
/*
@@ -417,7 +470,8 @@ int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
417470
}
418471

419472
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
420-
hash_algo, field_data);
473+
DIGEST_TYPE__LAST, hash_algo,
474+
field_data);
421475
}
422476

423477
static int ima_eventname_init_common(struct ima_event_data *event_data,

security/integrity/ima/ima_template_lib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
2121
struct ima_field_data *field_data);
2222
void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
2323
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);
2426
void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
2527
struct ima_field_data *field_data);
2628
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
@@ -38,6 +40,8 @@ int ima_eventname_init(struct ima_event_data *event_data,
3840
struct ima_field_data *field_data);
3941
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
4042
struct ima_field_data *field_data);
43+
int ima_eventdigest_ngv2_init(struct ima_event_data *event_data,
44+
struct ima_field_data *field_data);
4145
int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
4246
struct ima_field_data *field_data);
4347
int ima_eventname_ng_init(struct ima_event_data *event_data,

0 commit comments

Comments
 (0)