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 18 static 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 38 static int run_measured_process(const char *measured_dir, u32 *monitored_pid) 39 { 40 return _run_measured_process(measured_dir, monitored_pid, "run"); 41 } 42 43 static u64 ima_hash_from_bpf[MAX_SAMPLES]; 44 static int ima_hash_from_bpf_idx; 45 46 static 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 55 static 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 65 void 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, fresh_digest_idx = 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: 133 * 1 sample (/bin/true: fresh) if commit 62622dab0a28 applied 134 * 2 samples (/bin/true: non-fresh, fresh) if commit 62622dab0a28 is 135 * not applied 136 * 137 * If commit 62622dab0a28 ("ima: return IMA digest value only when 138 * IMA_COLLECTED flag is set") is applied, bpf_ima_inode_hash() refuses 139 * to give a non-fresh digest, hence the correct result is 1 instead of 140 * 2. 141 */ 142 test_init(skel->bss); 143 144 err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 145 "modify-bin"); 146 if (CHECK(err, "modify-bin #3", "err = %d\n", err)) 147 goto close_clean; 148 149 skel->bss->enable_bprm_creds_for_exec = true; 150 err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 151 if (CHECK(err, "run_measured_process #3", "err = %d\n", err)) 152 goto close_clean; 153 154 err = ring_buffer__consume(ringbuf); 155 ASSERT_GE(err, 1, "num_samples_or_err"); 156 if (err == 2) { 157 ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 158 ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, 159 "sample_equal_or_err"); 160 fresh_digest_idx = 1; 161 } 162 163 ASSERT_NEQ(ima_hash_from_bpf[fresh_digest_idx], 0, "ima_hash"); 164 /* IMA refreshed the digest. */ 165 ASSERT_NEQ(ima_hash_from_bpf[fresh_digest_idx], bin_true_sample, 166 "sample_equal_or_err"); 167 168 /* 169 * Test #4 170 * - Goal: verify that bpf_ima_file_hash() returns a fresh digest 171 * - Expected result: 4 samples (./ima_setup.sh: fresh, fresh; 172 * /bin/true: fresh, fresh) 173 */ 174 test_init(skel->bss); 175 skel->bss->use_ima_file_hash = true; 176 skel->bss->enable_bprm_creds_for_exec = true; 177 err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 178 if (CHECK(err, "run_measured_process #4", "err = %d\n", err)) 179 goto close_clean; 180 181 err = ring_buffer__consume(ringbuf); 182 ASSERT_EQ(err, 4, "num_samples_or_err"); 183 ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 184 ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 185 ASSERT_NEQ(ima_hash_from_bpf[2], 0, "ima_hash"); 186 ASSERT_NEQ(ima_hash_from_bpf[3], 0, "ima_hash"); 187 ASSERT_NEQ(ima_hash_from_bpf[2], bin_true_sample, 188 "sample_different_or_err"); 189 ASSERT_EQ(ima_hash_from_bpf[3], ima_hash_from_bpf[2], 190 "sample_equal_or_err"); 191 192 skel->bss->use_ima_file_hash = false; 193 skel->bss->enable_bprm_creds_for_exec = false; 194 err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 195 "restore-bin"); 196 if (CHECK(err, "restore-bin #3", "err = %d\n", err)) 197 goto close_clean; 198 199 /* 200 * Test #5 201 * - Goal: obtain a sample from the kernel_read_file hook 202 * - Expected result: 2 samples (./ima_setup.sh, policy_test) 203 */ 204 test_init(skel->bss); 205 skel->bss->use_ima_file_hash = true; 206 skel->bss->enable_kernel_read_file = true; 207 err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 208 "load-policy"); 209 if (CHECK(err, "run_measured_process #5", "err = %d\n", err)) 210 goto close_clean; 211 212 err = ring_buffer__consume(ringbuf); 213 ASSERT_EQ(err, 2, "num_samples_or_err"); 214 ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 215 ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 216 217 /* 218 * Test #6 219 * - Goal: ensure that the kernel_read_file hook denies an operation 220 * - Expected result: 0 samples 221 */ 222 test_init(skel->bss); 223 skel->bss->enable_kernel_read_file = true; 224 skel->bss->test_deny = true; 225 err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 226 "load-policy"); 227 if (CHECK(!err, "run_measured_process #6", "err = %d\n", err)) 228 goto close_clean; 229 230 err = ring_buffer__consume(ringbuf); 231 ASSERT_EQ(err, 0, "num_samples_or_err"); 232 233 close_clean: 234 snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir); 235 err = system(cmd); 236 CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno); 237 close_prog: 238 ring_buffer__free(ringbuf); 239 ima__destroy(skel); 240 } 241