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}