drivers/md/dm-ima.c

Source file repositories/reference/linux-study-clean/drivers/md/dm-ima.c

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-ima.c
Extension
.c
Size
18205 bytes
Lines
651
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (unlikely(cur_total_buf_len >= DM_IMA_MEASUREMENT_BUF_LEN)) {
			dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
			sha256_update(&hash_ctx, (const u8 *)ima_buf, l);

			memset(ima_buf, 0, DM_IMA_MEASUREMENT_BUF_LEN);
			l = 0;

			/*
			 * Each new "dm_table_load" entry in IMA log should have device data
			 * prefix, so that multiple records from the same "dm_table_load" for
			 * a given device can be linked together.
			 */
			memcpy(ima_buf + l, DM_IMA_VERSION_STR, strlen(DM_IMA_VERSION_STR));
			l += strlen(DM_IMA_VERSION_STR);

			memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
			l += device_data_buf_len;
		}

		/*
		 * Fill-in all the target metadata, so that multiple targets for the same
		 * device can be linked together.
		 */
		memcpy(ima_buf + l, target_metadata_buf, target_metadata_buf_len);
		l += target_metadata_buf_len;

		memcpy(ima_buf + l, target_data_buf, target_data_buf_len);
		l += target_data_buf_len;
	}

	dm_ima_measure_data(table_load_event_name, ima_buf, l, noio);
	sha256_update(&hash_ctx, (const u8 *)ima_buf, l);

	/*
	 * Finalize the table hash, and store it in table->md->ima.inactive_table.hash,
	 * so that the table data can be verified against the future device state change
	 * events, e.g. resume, rename, remove, table-clear etc.
	 */
	sha256_final(&hash_ctx, digest);

	digest_buf = kasprintf(GFP_KERNEL, "sha256:%*phN", SHA256_DIGEST_SIZE,
			       digest);
	if (!digest_buf)
		goto error;

	kfree(table->md->ima.inactive_table.hash);
	table->md->ima.inactive_table.hash = digest_buf;
	table->md->ima.inactive_table.hash_len = strlen(digest_buf);
	table->md->ima.inactive_table.num_targets = num_targets;
	table->md->ima.inactive_table.capacity = dm_table_get_size(table);


	kfree(table->md->ima.inactive_table.device_metadata);
	table->md->ima.inactive_table.device_metadata = device_data_buf;
	table->md->ima.inactive_table.device_metadata_len = device_data_buf_len;

	goto exit;
error:
	kfree(digest_buf);
	kfree(device_data_buf);
exit:
	kfree(ima_buf);
	kfree(target_metadata_buf);
	kfree(target_data_buf);

	wake_next_measure(&table->md->ima);
}

/*
 * Measure IMA data on device resume.
 */
void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap,
				     struct dm_ima_context *context)
{
	char *device_table_data = NULL;
	char active[] = "active_table_hash=";
	unsigned int active_len = strlen(active);
	unsigned int l = 0;
	bool noio = true;
	bool nodata = true;

	if (unlikely(!context))
		return;

	wait_to_measure(&md->ima, context->update_idx);

	if (swap) {
		kfree(md->ima.active_table.hash);
		kfree(md->ima.active_table.device_metadata);
		md->ima.active_table = context->table;

Annotation

Implementation Notes