134b82d3aSKP Singh // SPDX-License-Identifier: GPL-2.0 234b82d3aSKP Singh 334b82d3aSKP Singh /* 434b82d3aSKP Singh * Copyright (C) 2020 Google LLC. 534b82d3aSKP Singh */ 634b82d3aSKP Singh 734b82d3aSKP Singh #include <stdio.h> 834b82d3aSKP Singh #include <stdlib.h> 934b82d3aSKP Singh #include <unistd.h> 1034b82d3aSKP Singh #include <sys/wait.h> 1134b82d3aSKP Singh #include <test_progs.h> 12f446b570SKP Singh #include <linux/ring_buffer.h> 1334b82d3aSKP Singh 1434b82d3aSKP Singh #include "ima.skel.h" 1534b82d3aSKP Singh 1691e8fa25SRoberto Sassu #define MAX_SAMPLES 4 1727a77d0dSRoberto Sassu 1891e8fa25SRoberto Sassu static int _run_measured_process(const char *measured_dir, u32 *monitored_pid, 1991e8fa25SRoberto Sassu const char *cmd) 2034b82d3aSKP Singh { 2134b82d3aSKP Singh int child_pid, child_status; 2234b82d3aSKP Singh 2334b82d3aSKP Singh child_pid = fork(); 2434b82d3aSKP Singh if (child_pid == 0) { 2534b82d3aSKP Singh *monitored_pid = getpid(); 2691e8fa25SRoberto Sassu execlp("./ima_setup.sh", "./ima_setup.sh", cmd, measured_dir, 2734b82d3aSKP Singh NULL); 2834b82d3aSKP Singh exit(errno); 2934b82d3aSKP Singh 3034b82d3aSKP Singh } else if (child_pid > 0) { 3134b82d3aSKP Singh waitpid(child_pid, &child_status, 0); 3234b82d3aSKP Singh return WEXITSTATUS(child_status); 3334b82d3aSKP Singh } 3434b82d3aSKP Singh 3534b82d3aSKP Singh return -EINVAL; 3634b82d3aSKP Singh } 3734b82d3aSKP Singh 3891e8fa25SRoberto Sassu static int run_measured_process(const char *measured_dir, u32 *monitored_pid) 3991e8fa25SRoberto Sassu { 4091e8fa25SRoberto Sassu return _run_measured_process(measured_dir, monitored_pid, "run"); 4191e8fa25SRoberto Sassu } 4291e8fa25SRoberto Sassu 4327a77d0dSRoberto Sassu static u64 ima_hash_from_bpf[MAX_SAMPLES]; 4427a77d0dSRoberto Sassu static int ima_hash_from_bpf_idx; 45f446b570SKP Singh 46f446b570SKP Singh static int process_sample(void *ctx, void *data, size_t len) 47f446b570SKP Singh { 4827a77d0dSRoberto Sassu if (ima_hash_from_bpf_idx >= MAX_SAMPLES) 4927a77d0dSRoberto Sassu return -ENOSPC; 5027a77d0dSRoberto Sassu 5127a77d0dSRoberto Sassu ima_hash_from_bpf[ima_hash_from_bpf_idx++] = *((u64 *)data); 52f446b570SKP Singh return 0; 53f446b570SKP Singh } 54f446b570SKP Singh 5527a77d0dSRoberto Sassu static void test_init(struct ima__bss *bss) 5627a77d0dSRoberto Sassu { 5727a77d0dSRoberto Sassu ima_hash_from_bpf_idx = 0; 5827a77d0dSRoberto Sassu 5927a77d0dSRoberto Sassu bss->use_ima_file_hash = false; 6091e8fa25SRoberto Sassu bss->enable_bprm_creds_for_exec = false; 61*e6dcf7bbSRoberto Sassu bss->enable_kernel_read_file = false; 6227a77d0dSRoberto Sassu } 6327a77d0dSRoberto Sassu 6434b82d3aSKP Singh void test_test_ima(void) 6534b82d3aSKP Singh { 6634b82d3aSKP Singh char measured_dir_template[] = "/tmp/ima_measuredXXXXXX"; 67efadf2adSKumar Kartikeya Dwivedi struct ring_buffer *ringbuf = NULL; 6834b82d3aSKP Singh const char *measured_dir; 6991e8fa25SRoberto Sassu u64 bin_true_sample; 7034b82d3aSKP Singh char cmd[256]; 7134b82d3aSKP Singh 7234b82d3aSKP Singh int err, duration = 0; 7334b82d3aSKP Singh struct ima *skel = NULL; 7434b82d3aSKP Singh 7534b82d3aSKP Singh skel = ima__open_and_load(); 7634b82d3aSKP Singh if (CHECK(!skel, "skel_load", "skeleton failed\n")) 7734b82d3aSKP Singh goto close_prog; 7834b82d3aSKP Singh 79f446b570SKP Singh ringbuf = ring_buffer__new(bpf_map__fd(skel->maps.ringbuf), 80f446b570SKP Singh process_sample, NULL, NULL); 81f446b570SKP Singh if (!ASSERT_OK_PTR(ringbuf, "ringbuf")) 82f446b570SKP Singh goto close_prog; 83f446b570SKP Singh 8434b82d3aSKP Singh err = ima__attach(skel); 8534b82d3aSKP Singh if (CHECK(err, "attach", "attach failed: %d\n", err)) 8634b82d3aSKP Singh goto close_prog; 8734b82d3aSKP Singh 8834b82d3aSKP Singh measured_dir = mkdtemp(measured_dir_template); 8934b82d3aSKP Singh if (CHECK(measured_dir == NULL, "mkdtemp", "err %d\n", errno)) 9034b82d3aSKP Singh goto close_prog; 9134b82d3aSKP Singh 9234b82d3aSKP Singh snprintf(cmd, sizeof(cmd), "./ima_setup.sh setup %s", measured_dir); 93cff90846SKP Singh err = system(cmd); 94cff90846SKP Singh if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno)) 9534b82d3aSKP Singh goto close_clean; 9634b82d3aSKP Singh 9727a77d0dSRoberto Sassu /* 9827a77d0dSRoberto Sassu * Test #1 9927a77d0dSRoberto Sassu * - Goal: obtain a sample with the bpf_ima_inode_hash() helper 10027a77d0dSRoberto Sassu * - Expected result: 1 sample (/bin/true) 10127a77d0dSRoberto Sassu */ 10227a77d0dSRoberto Sassu test_init(skel->bss); 10334b82d3aSKP Singh err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 10427a77d0dSRoberto Sassu if (CHECK(err, "run_measured_process #1", "err = %d\n", err)) 10534b82d3aSKP Singh goto close_clean; 10634b82d3aSKP Singh 107f446b570SKP Singh err = ring_buffer__consume(ringbuf); 108f446b570SKP Singh ASSERT_EQ(err, 1, "num_samples_or_err"); 10927a77d0dSRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 11027a77d0dSRoberto Sassu 11127a77d0dSRoberto Sassu /* 11227a77d0dSRoberto Sassu * Test #2 11327a77d0dSRoberto Sassu * - Goal: obtain samples with the bpf_ima_file_hash() helper 11427a77d0dSRoberto Sassu * - Expected result: 2 samples (./ima_setup.sh, /bin/true) 11527a77d0dSRoberto Sassu */ 11627a77d0dSRoberto Sassu test_init(skel->bss); 11727a77d0dSRoberto Sassu skel->bss->use_ima_file_hash = true; 11827a77d0dSRoberto Sassu err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 11927a77d0dSRoberto Sassu if (CHECK(err, "run_measured_process #2", "err = %d\n", err)) 12027a77d0dSRoberto Sassu goto close_clean; 12127a77d0dSRoberto Sassu 12227a77d0dSRoberto Sassu err = ring_buffer__consume(ringbuf); 12327a77d0dSRoberto Sassu ASSERT_EQ(err, 2, "num_samples_or_err"); 12427a77d0dSRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 12527a77d0dSRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 12691e8fa25SRoberto Sassu bin_true_sample = ima_hash_from_bpf[1]; 12791e8fa25SRoberto Sassu 12891e8fa25SRoberto Sassu /* 12991e8fa25SRoberto Sassu * Test #3 13091e8fa25SRoberto Sassu * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest 13191e8fa25SRoberto Sassu * - Expected result: 2 samples (/bin/true: non-fresh, fresh) 13291e8fa25SRoberto Sassu */ 13391e8fa25SRoberto Sassu test_init(skel->bss); 13491e8fa25SRoberto Sassu 13591e8fa25SRoberto Sassu err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 13691e8fa25SRoberto Sassu "modify-bin"); 13791e8fa25SRoberto Sassu if (CHECK(err, "modify-bin #3", "err = %d\n", err)) 13891e8fa25SRoberto Sassu goto close_clean; 13991e8fa25SRoberto Sassu 14091e8fa25SRoberto Sassu skel->bss->enable_bprm_creds_for_exec = true; 14191e8fa25SRoberto Sassu err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 14291e8fa25SRoberto Sassu if (CHECK(err, "run_measured_process #3", "err = %d\n", err)) 14391e8fa25SRoberto Sassu goto close_clean; 14491e8fa25SRoberto Sassu 14591e8fa25SRoberto Sassu err = ring_buffer__consume(ringbuf); 14691e8fa25SRoberto Sassu ASSERT_EQ(err, 2, "num_samples_or_err"); 14791e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 14891e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 14991e8fa25SRoberto Sassu ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, "sample_equal_or_err"); 15091e8fa25SRoberto Sassu /* IMA refreshed the digest. */ 15191e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[1], bin_true_sample, 15291e8fa25SRoberto Sassu "sample_different_or_err"); 15391e8fa25SRoberto Sassu 15491e8fa25SRoberto Sassu /* 15591e8fa25SRoberto Sassu * Test #4 15691e8fa25SRoberto Sassu * - Goal: verify that bpf_ima_file_hash() returns a fresh digest 15791e8fa25SRoberto Sassu * - Expected result: 4 samples (./ima_setup.sh: fresh, fresh; 15891e8fa25SRoberto Sassu * /bin/true: fresh, fresh) 15991e8fa25SRoberto Sassu */ 16091e8fa25SRoberto Sassu test_init(skel->bss); 16191e8fa25SRoberto Sassu skel->bss->use_ima_file_hash = true; 16291e8fa25SRoberto Sassu skel->bss->enable_bprm_creds_for_exec = true; 16391e8fa25SRoberto Sassu err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 16491e8fa25SRoberto Sassu if (CHECK(err, "run_measured_process #4", "err = %d\n", err)) 16591e8fa25SRoberto Sassu goto close_clean; 16691e8fa25SRoberto Sassu 16791e8fa25SRoberto Sassu err = ring_buffer__consume(ringbuf); 16891e8fa25SRoberto Sassu ASSERT_EQ(err, 4, "num_samples_or_err"); 16991e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 17091e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 17191e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[2], 0, "ima_hash"); 17291e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[3], 0, "ima_hash"); 17391e8fa25SRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[2], bin_true_sample, 17491e8fa25SRoberto Sassu "sample_different_or_err"); 17591e8fa25SRoberto Sassu ASSERT_EQ(ima_hash_from_bpf[3], ima_hash_from_bpf[2], 17691e8fa25SRoberto Sassu "sample_equal_or_err"); 17791e8fa25SRoberto Sassu 17891e8fa25SRoberto Sassu skel->bss->use_ima_file_hash = false; 17991e8fa25SRoberto Sassu skel->bss->enable_bprm_creds_for_exec = false; 18091e8fa25SRoberto Sassu err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 18191e8fa25SRoberto Sassu "restore-bin"); 18291e8fa25SRoberto Sassu if (CHECK(err, "restore-bin #3", "err = %d\n", err)) 18391e8fa25SRoberto Sassu goto close_clean; 18434b82d3aSKP Singh 185*e6dcf7bbSRoberto Sassu /* 186*e6dcf7bbSRoberto Sassu * Test #5 187*e6dcf7bbSRoberto Sassu * - Goal: obtain a sample from the kernel_read_file hook 188*e6dcf7bbSRoberto Sassu * - Expected result: 2 samples (./ima_setup.sh, policy_test) 189*e6dcf7bbSRoberto Sassu */ 190*e6dcf7bbSRoberto Sassu test_init(skel->bss); 191*e6dcf7bbSRoberto Sassu skel->bss->use_ima_file_hash = true; 192*e6dcf7bbSRoberto Sassu skel->bss->enable_kernel_read_file = true; 193*e6dcf7bbSRoberto Sassu err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 194*e6dcf7bbSRoberto Sassu "load-policy"); 195*e6dcf7bbSRoberto Sassu if (CHECK(err, "run_measured_process #5", "err = %d\n", err)) 196*e6dcf7bbSRoberto Sassu goto close_clean; 197*e6dcf7bbSRoberto Sassu 198*e6dcf7bbSRoberto Sassu err = ring_buffer__consume(ringbuf); 199*e6dcf7bbSRoberto Sassu ASSERT_EQ(err, 2, "num_samples_or_err"); 200*e6dcf7bbSRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 201*e6dcf7bbSRoberto Sassu ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 202*e6dcf7bbSRoberto Sassu 20334b82d3aSKP Singh close_clean: 20434b82d3aSKP Singh snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir); 205cff90846SKP Singh err = system(cmd); 206cff90846SKP Singh CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno); 20734b82d3aSKP Singh close_prog: 208efadf2adSKumar Kartikeya Dwivedi ring_buffer__free(ringbuf); 20934b82d3aSKP Singh ima__destroy(skel); 21034b82d3aSKP Singh } 211