Commit 989dc725 authored by Mimi Zohar's avatar Mimi Zohar
Browse files

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: default avatarMimi Zohar <zohar@linux.ibm.com>
parent 246d9216
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1903,7 +1903,8 @@

	ima_template=	[IMA]
			Select one of defined IMA measurements template formats.
			Formats: { "ima" | "ima-ng" | "ima-sig" }
			Formats: { "ima" | "ima-ng" | "ima-ngv2" | "ima-sig" |
				   "ima-sigv2" }
			Default: "ima-ng"

	ima_template_fmt=
+4 −0
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ descriptors by adding their identifier to the format string
 - 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
 - 'd-ng': the digest of the event, calculated with an arbitrary hash
   algorithm (field format: <hash algo>:digest);
 - 'd-ngv2': same as d-ng, but prefixed with the "ima" digest type
   (field format: <digest type>:<hash algo>:digest);
 - 'd-modsig': the digest of the event without the appended modsig;
 - 'n-ng': the name of the event, without size limitations;
 - '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:

 - "ima": its format is ``d|n``;
 - "ima-ng" (default): its format is ``d-ng|n-ng``;
 - "ima-ngv2": its format is ``d-ngv2|n-ng``;
 - "ima-sig": its format is ``d-ng|n-ng|sig``;
 - "ima-sigv2": its format is ``d-ngv2|n-ng|sig``;
 - "ima-buf": its format is ``d-ng|n-ng|buf``;
 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
 - "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;
+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ static struct ima_template_desc builtin_templates[] = {
	{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
	{.name = "ima-ng", .fmt = "d-ng|n-ng"},
	{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
	{.name = "ima-ngv2", .fmt = "d-ngv2|n-ng"},
	{.name = "ima-sigv2", .fmt = "d-ngv2|n-ng|sig"},
	{.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
	{.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
	{.name = "evm-sig",
@@ -38,6 +40,8 @@ static const struct ima_template_field supported_fields[] = {
	 .field_show = ima_show_template_string},
	{.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
	 .field_show = ima_show_template_digest_ng},
	{.field_id = "d-ngv2", .field_init = ima_eventdigest_ngv2_init,
	 .field_show = ima_show_template_digest_ngv2},
	{.field_id = "n-ng", .field_init = ima_eventname_ng_init,
	 .field_show = ima_show_template_string},
	{.field_id = "sig", .field_init = ima_eventsig_init,
+65 −11
Original line number Diff line number Diff line
@@ -24,11 +24,22 @@ static bool ima_template_hash_algo_allowed(u8 algo)
enum data_formats {
	DATA_FMT_DIGEST = 0,
	DATA_FMT_DIGEST_WITH_ALGO,
	DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
	DATA_FMT_STRING,
	DATA_FMT_HEX,
	DATA_FMT_UINT
};

enum digest_type {
	DIGEST_TYPE_IMA,
	DIGEST_TYPE__LAST
};

#define DIGEST_TYPE_NAME_LEN_MAX 4	/* including NUL */
static const char * const digest_type_name[DIGEST_TYPE__LAST] = {
	[DIGEST_TYPE_IMA] = "ima"
};

static int ima_write_template_field_data(const void *data, const u32 datalen,
					 enum data_formats datafmt,
					 struct ima_field_data *field_data)
@@ -72,8 +83,9 @@ static void ima_show_template_data_ascii(struct seq_file *m,
	u32 buflen = field_data->len;

	switch (datafmt) {
	case DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
	case DATA_FMT_DIGEST_WITH_ALGO:
		buf_ptr = strnchr(field_data->data, buflen, ':');
		buf_ptr = strrchr(field_data->data, ':');
		if (buf_ptr != field_data->data)
			seq_printf(m, "%s", field_data->data);

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

void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show,
				   struct ima_field_data *field_data)
{
	ima_show_template_field_data(m, show,
				     DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO,
				     field_data);
}

void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
			      struct ima_field_data *field_data)
{
@@ -265,28 +285,35 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
}

static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
				       u8 hash_algo,
				       u8 digest_type, u8 hash_algo,
				       struct ima_field_data *field_data)
{
	/*
	 * digest formats:
	 *  - DATA_FMT_DIGEST: digest
	 *  - DATA_FMT_DIGEST_WITH_ALGO: <hash algo> + ':' + '\0' + digest,
	 *  - DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO:
	 *	<digest type> + ':' + <hash algo> + ':' + '\0' + digest,
	 *
	 *    where 'DATA_FMT_DIGEST' is the original digest format ('d')
	 *      with a hash size limitation of 20 bytes,
	 *    where <digest type> is "ima",
	 *    where <hash algo> is the hash_algo_name[] string.
	 */
	u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 };
	u8 buffer[DIGEST_TYPE_NAME_LEN_MAX + CRYPTO_MAX_ALG_NAME + 2 +
		IMA_MAX_DIGEST_SIZE] = { 0 };
	enum data_formats fmt = DATA_FMT_DIGEST;
	u32 offset = 0;

	if (hash_algo < HASH_ALGO__LAST) {
	if (digest_type < DIGEST_TYPE__LAST && hash_algo < HASH_ALGO__LAST) {
		fmt = DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO;
		offset += 1 + sprintf(buffer, "%s:%s:",
				      digest_type_name[digest_type],
				      hash_algo_name[hash_algo]);
	} else if (hash_algo < HASH_ALGO__LAST) {
		fmt = DATA_FMT_DIGEST_WITH_ALGO;
		offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s",
		offset += 1 + sprintf(buffer, "%s:",
				      hash_algo_name[hash_algo]);
		buffer[offset] = ':';
		offset += 2;
	}

	if (digest)
@@ -361,7 +388,8 @@ int ima_eventdigest_init(struct ima_event_data *event_data,
	cur_digestsize = hash.hdr.length;
out:
	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
					   HASH_ALGO__LAST, field_data);
					   DIGEST_TYPE__LAST, HASH_ALGO__LAST,
					   field_data);
}

/*
@@ -382,7 +410,32 @@ int ima_eventdigest_ng_init(struct ima_event_data *event_data,
	hash_algo = event_data->iint->ima_hash->algo;
out:
	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
					   hash_algo, field_data);
					   DIGEST_TYPE__LAST, hash_algo,
					   field_data);
}

/*
 * This function writes the digest of an event (without size limit),
 * prefixed with both the digest type and hash algorithm.
 */
int ima_eventdigest_ngv2_init(struct ima_event_data *event_data,
			      struct ima_field_data *field_data)
{
	u8 *cur_digest = NULL, hash_algo = ima_hash_algo;
	u32 cur_digestsize = 0;
	u8 digest_type = DIGEST_TYPE_IMA;

	if (event_data->violation)	/* recording a violation. */
		goto out;

	cur_digest = event_data->iint->ima_hash->digest;
	cur_digestsize = event_data->iint->ima_hash->length;

	hash_algo = event_data->iint->ima_hash->algo;
out:
	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
					   digest_type, hash_algo,
					   field_data);
}

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

	return ima_eventdigest_init_common(cur_digest, cur_digestsize,
					   hash_algo, field_data);
					   DIGEST_TYPE__LAST, hash_algo,
					   field_data);
}

static int ima_eventname_init_common(struct ima_event_data *event_data,
+4 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ void ima_show_template_digest(struct seq_file *m, enum ima_show_type show,
			      struct ima_field_data *field_data);
void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
				 struct ima_field_data *field_data);
void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show,
				   struct ima_field_data *field_data);
void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
			      struct ima_field_data *field_data);
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,
		       struct ima_field_data *field_data);
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
			    struct ima_field_data *field_data);
int ima_eventdigest_ngv2_init(struct ima_event_data *event_data,
			      struct ima_field_data *field_data);
int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
				struct ima_field_data *field_data);
int ima_eventname_ng_init(struct ima_event_data *event_data,