cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_ima.c (6705B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 * Copyright (C) 2020 Google LLC.
      5 */
      6
      7#include <stdio.h>
      8#include <stdlib.h>
      9#include <unistd.h>
     10#include <sys/wait.h>
     11#include <test_progs.h>
     12#include <linux/ring_buffer.h>
     13
     14#include "ima.skel.h"
     15
     16#define MAX_SAMPLES 4
     17
     18static int _run_measured_process(const char *measured_dir, u32 *monitored_pid,
     19				 const char *cmd)
     20{
     21	int child_pid, child_status;
     22
     23	child_pid = fork();
     24	if (child_pid == 0) {
     25		*monitored_pid = getpid();
     26		execlp("./ima_setup.sh", "./ima_setup.sh", cmd, measured_dir,
     27		       NULL);
     28		exit(errno);
     29
     30	} else if (child_pid > 0) {
     31		waitpid(child_pid, &child_status, 0);
     32		return WEXITSTATUS(child_status);
     33	}
     34
     35	return -EINVAL;
     36}
     37
     38static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
     39{
     40	return _run_measured_process(measured_dir, monitored_pid, "run");
     41}
     42
     43static u64 ima_hash_from_bpf[MAX_SAMPLES];
     44static int ima_hash_from_bpf_idx;
     45
     46static int process_sample(void *ctx, void *data, size_t len)
     47{
     48	if (ima_hash_from_bpf_idx >= MAX_SAMPLES)
     49		return -ENOSPC;
     50
     51	ima_hash_from_bpf[ima_hash_from_bpf_idx++] = *((u64 *)data);
     52	return 0;
     53}
     54
     55static void test_init(struct ima__bss *bss)
     56{
     57	ima_hash_from_bpf_idx = 0;
     58
     59	bss->use_ima_file_hash = false;
     60	bss->enable_bprm_creds_for_exec = false;
     61	bss->enable_kernel_read_file = false;
     62	bss->test_deny = false;
     63}
     64
     65void test_test_ima(void)
     66{
     67	char measured_dir_template[] = "/tmp/ima_measuredXXXXXX";
     68	struct ring_buffer *ringbuf = NULL;
     69	const char *measured_dir;
     70	u64 bin_true_sample;
     71	char cmd[256];
     72
     73	int err, duration = 0;
     74	struct ima *skel = NULL;
     75
     76	skel = ima__open_and_load();
     77	if (CHECK(!skel, "skel_load", "skeleton failed\n"))
     78		goto close_prog;
     79
     80	ringbuf = ring_buffer__new(bpf_map__fd(skel->maps.ringbuf),
     81				   process_sample, NULL, NULL);
     82	if (!ASSERT_OK_PTR(ringbuf, "ringbuf"))
     83		goto close_prog;
     84
     85	err = ima__attach(skel);
     86	if (CHECK(err, "attach", "attach failed: %d\n", err))
     87		goto close_prog;
     88
     89	measured_dir = mkdtemp(measured_dir_template);
     90	if (CHECK(measured_dir == NULL, "mkdtemp", "err %d\n", errno))
     91		goto close_prog;
     92
     93	snprintf(cmd, sizeof(cmd), "./ima_setup.sh setup %s", measured_dir);
     94	err = system(cmd);
     95	if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno))
     96		goto close_clean;
     97
     98	/*
     99	 * Test #1
    100	 * - Goal: obtain a sample with the bpf_ima_inode_hash() helper
    101	 * - Expected result:  1 sample (/bin/true)
    102	 */
    103	test_init(skel->bss);
    104	err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
    105	if (CHECK(err, "run_measured_process #1", "err = %d\n", err))
    106		goto close_clean;
    107
    108	err = ring_buffer__consume(ringbuf);
    109	ASSERT_EQ(err, 1, "num_samples_or_err");
    110	ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
    111
    112	/*
    113	 * Test #2
    114	 * - Goal: obtain samples with the bpf_ima_file_hash() helper
    115	 * - Expected result: 2 samples (./ima_setup.sh, /bin/true)
    116	 */
    117	test_init(skel->bss);
    118	skel->bss->use_ima_file_hash = true;
    119	err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
    120	if (CHECK(err, "run_measured_process #2", "err = %d\n", err))
    121		goto close_clean;
    122
    123	err = ring_buffer__consume(ringbuf);
    124	ASSERT_EQ(err, 2, "num_samples_or_err");
    125	ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
    126	ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
    127	bin_true_sample = ima_hash_from_bpf[1];
    128
    129	/*
    130	 * Test #3
    131	 * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest
    132	 * - Expected result: 2 samples (/bin/true: non-fresh, fresh)
    133	 */
    134	test_init(skel->bss);
    135
    136	err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
    137				    "modify-bin");
    138	if (CHECK(err, "modify-bin #3", "err = %d\n", err))
    139		goto close_clean;
    140
    141	skel->bss->enable_bprm_creds_for_exec = true;
    142	err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
    143	if (CHECK(err, "run_measured_process #3", "err = %d\n", err))
    144		goto close_clean;
    145
    146	err = ring_buffer__consume(ringbuf);
    147	ASSERT_EQ(err, 2, "num_samples_or_err");
    148	ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
    149	ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
    150	ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, "sample_equal_or_err");
    151	/* IMA refreshed the digest. */
    152	ASSERT_NEQ(ima_hash_from_bpf[1], bin_true_sample,
    153		   "sample_different_or_err");
    154
    155	/*
    156	 * Test #4
    157	 * - Goal: verify that bpf_ima_file_hash() returns a fresh digest
    158	 * - Expected result: 4 samples (./ima_setup.sh: fresh, fresh;
    159	 *                               /bin/true: fresh, fresh)
    160	 */
    161	test_init(skel->bss);
    162	skel->bss->use_ima_file_hash = true;
    163	skel->bss->enable_bprm_creds_for_exec = true;
    164	err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
    165	if (CHECK(err, "run_measured_process #4", "err = %d\n", err))
    166		goto close_clean;
    167
    168	err = ring_buffer__consume(ringbuf);
    169	ASSERT_EQ(err, 4, "num_samples_or_err");
    170	ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
    171	ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
    172	ASSERT_NEQ(ima_hash_from_bpf[2], 0, "ima_hash");
    173	ASSERT_NEQ(ima_hash_from_bpf[3], 0, "ima_hash");
    174	ASSERT_NEQ(ima_hash_from_bpf[2], bin_true_sample,
    175		   "sample_different_or_err");
    176	ASSERT_EQ(ima_hash_from_bpf[3], ima_hash_from_bpf[2],
    177		  "sample_equal_or_err");
    178
    179	skel->bss->use_ima_file_hash = false;
    180	skel->bss->enable_bprm_creds_for_exec = false;
    181	err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
    182				    "restore-bin");
    183	if (CHECK(err, "restore-bin #3", "err = %d\n", err))
    184		goto close_clean;
    185
    186	/*
    187	 * Test #5
    188	 * - Goal: obtain a sample from the kernel_read_file hook
    189	 * - Expected result: 2 samples (./ima_setup.sh, policy_test)
    190	 */
    191	test_init(skel->bss);
    192	skel->bss->use_ima_file_hash = true;
    193	skel->bss->enable_kernel_read_file = true;
    194	err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
    195				    "load-policy");
    196	if (CHECK(err, "run_measured_process #5", "err = %d\n", err))
    197		goto close_clean;
    198
    199	err = ring_buffer__consume(ringbuf);
    200	ASSERT_EQ(err, 2, "num_samples_or_err");
    201	ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
    202	ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
    203
    204	/*
    205	 * Test #6
    206	 * - Goal: ensure that the kernel_read_file hook denies an operation
    207	 * - Expected result: 0 samples
    208	 */
    209	test_init(skel->bss);
    210	skel->bss->enable_kernel_read_file = true;
    211	skel->bss->test_deny = true;
    212	err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
    213				    "load-policy");
    214	if (CHECK(!err, "run_measured_process #6", "err = %d\n", err))
    215		goto close_clean;
    216
    217	err = ring_buffer__consume(ringbuf);
    218	ASSERT_EQ(err, 0, "num_samples_or_err");
    219
    220close_clean:
    221	snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir);
    222	err = system(cmd);
    223	CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno);
    224close_prog:
    225	ring_buffer__free(ringbuf);
    226	ima__destroy(skel);
    227}