241 lines · c
1// SPDX-License-Identifier: GPL-2.02 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 417 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, 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 #1100 * - Goal: obtain a sample with the bpf_ima_inode_hash() helper101 * - 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 #2114 * - Goal: obtain samples with the bpf_ima_file_hash() helper115 * - 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 #3131 * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest132 * - Expected result:133 * 1 sample (/bin/true: fresh) if commit 62622dab0a28 applied134 * 2 samples (/bin/true: non-fresh, fresh) if commit 62622dab0a28 is135 * not applied136 *137 * If commit 62622dab0a28 ("ima: return IMA digest value only when138 * IMA_COLLECTED flag is set") is applied, bpf_ima_inode_hash() refuses139 * to give a non-fresh digest, hence the correct result is 1 instead of140 * 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 #4170 * - Goal: verify that bpf_ima_file_hash() returns a fresh digest171 * - 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 #5201 * - Goal: obtain a sample from the kernel_read_file hook202 * - 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 #6219 * - Goal: ensure that the kernel_read_file hook denies an operation220 * - Expected result: 0 samples221 */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 233close_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);237close_prog:238 ring_buffer__free(ringbuf);239 ima__destroy(skel);240}241