Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * Copyright (C) 2020 Google LLC.
0005  */
0006 
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <unistd.h>
0010 #include <sys/wait.h>
0011 #include <test_progs.h>
0012 #include <linux/ring_buffer.h>
0013 
0014 #include "ima.skel.h"
0015 
0016 #define MAX_SAMPLES 4
0017 
0018 static int _run_measured_process(const char *measured_dir, u32 *monitored_pid,
0019                  const char *cmd)
0020 {
0021     int child_pid, child_status;
0022 
0023     child_pid = fork();
0024     if (child_pid == 0) {
0025         *monitored_pid = getpid();
0026         execlp("./ima_setup.sh", "./ima_setup.sh", cmd, measured_dir,
0027                NULL);
0028         exit(errno);
0029 
0030     } else if (child_pid > 0) {
0031         waitpid(child_pid, &child_status, 0);
0032         return WEXITSTATUS(child_status);
0033     }
0034 
0035     return -EINVAL;
0036 }
0037 
0038 static int run_measured_process(const char *measured_dir, u32 *monitored_pid)
0039 {
0040     return _run_measured_process(measured_dir, monitored_pid, "run");
0041 }
0042 
0043 static u64 ima_hash_from_bpf[MAX_SAMPLES];
0044 static int ima_hash_from_bpf_idx;
0045 
0046 static int process_sample(void *ctx, void *data, size_t len)
0047 {
0048     if (ima_hash_from_bpf_idx >= MAX_SAMPLES)
0049         return -ENOSPC;
0050 
0051     ima_hash_from_bpf[ima_hash_from_bpf_idx++] = *((u64 *)data);
0052     return 0;
0053 }
0054 
0055 static void test_init(struct ima__bss *bss)
0056 {
0057     ima_hash_from_bpf_idx = 0;
0058 
0059     bss->use_ima_file_hash = false;
0060     bss->enable_bprm_creds_for_exec = false;
0061     bss->enable_kernel_read_file = false;
0062     bss->test_deny = false;
0063 }
0064 
0065 void test_test_ima(void)
0066 {
0067     char measured_dir_template[] = "/tmp/ima_measuredXXXXXX";
0068     struct ring_buffer *ringbuf = NULL;
0069     const char *measured_dir;
0070     u64 bin_true_sample;
0071     char cmd[256];
0072 
0073     int err, duration = 0;
0074     struct ima *skel = NULL;
0075 
0076     skel = ima__open_and_load();
0077     if (CHECK(!skel, "skel_load", "skeleton failed\n"))
0078         goto close_prog;
0079 
0080     ringbuf = ring_buffer__new(bpf_map__fd(skel->maps.ringbuf),
0081                    process_sample, NULL, NULL);
0082     if (!ASSERT_OK_PTR(ringbuf, "ringbuf"))
0083         goto close_prog;
0084 
0085     err = ima__attach(skel);
0086     if (CHECK(err, "attach", "attach failed: %d\n", err))
0087         goto close_prog;
0088 
0089     measured_dir = mkdtemp(measured_dir_template);
0090     if (CHECK(measured_dir == NULL, "mkdtemp", "err %d\n", errno))
0091         goto close_prog;
0092 
0093     snprintf(cmd, sizeof(cmd), "./ima_setup.sh setup %s", measured_dir);
0094     err = system(cmd);
0095     if (CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno))
0096         goto close_clean;
0097 
0098     /*
0099      * Test #1
0100      * - Goal: obtain a sample with the bpf_ima_inode_hash() helper
0101      * - Expected result:  1 sample (/bin/true)
0102      */
0103     test_init(skel->bss);
0104     err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
0105     if (CHECK(err, "run_measured_process #1", "err = %d\n", err))
0106         goto close_clean;
0107 
0108     err = ring_buffer__consume(ringbuf);
0109     ASSERT_EQ(err, 1, "num_samples_or_err");
0110     ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
0111 
0112     /*
0113      * Test #2
0114      * - Goal: obtain samples with the bpf_ima_file_hash() helper
0115      * - Expected result: 2 samples (./ima_setup.sh, /bin/true)
0116      */
0117     test_init(skel->bss);
0118     skel->bss->use_ima_file_hash = true;
0119     err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
0120     if (CHECK(err, "run_measured_process #2", "err = %d\n", err))
0121         goto close_clean;
0122 
0123     err = ring_buffer__consume(ringbuf);
0124     ASSERT_EQ(err, 2, "num_samples_or_err");
0125     ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
0126     ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
0127     bin_true_sample = ima_hash_from_bpf[1];
0128 
0129     /*
0130      * Test #3
0131      * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest
0132      * - Expected result: 2 samples (/bin/true: non-fresh, fresh)
0133      */
0134     test_init(skel->bss);
0135 
0136     err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
0137                     "modify-bin");
0138     if (CHECK(err, "modify-bin #3", "err = %d\n", err))
0139         goto close_clean;
0140 
0141     skel->bss->enable_bprm_creds_for_exec = true;
0142     err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
0143     if (CHECK(err, "run_measured_process #3", "err = %d\n", err))
0144         goto close_clean;
0145 
0146     err = ring_buffer__consume(ringbuf);
0147     ASSERT_EQ(err, 2, "num_samples_or_err");
0148     ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
0149     ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
0150     ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, "sample_equal_or_err");
0151     /* IMA refreshed the digest. */
0152     ASSERT_NEQ(ima_hash_from_bpf[1], bin_true_sample,
0153            "sample_different_or_err");
0154 
0155     /*
0156      * Test #4
0157      * - Goal: verify that bpf_ima_file_hash() returns a fresh digest
0158      * - Expected result: 4 samples (./ima_setup.sh: fresh, fresh;
0159      *                               /bin/true: fresh, fresh)
0160      */
0161     test_init(skel->bss);
0162     skel->bss->use_ima_file_hash = true;
0163     skel->bss->enable_bprm_creds_for_exec = true;
0164     err = run_measured_process(measured_dir, &skel->bss->monitored_pid);
0165     if (CHECK(err, "run_measured_process #4", "err = %d\n", err))
0166         goto close_clean;
0167 
0168     err = ring_buffer__consume(ringbuf);
0169     ASSERT_EQ(err, 4, "num_samples_or_err");
0170     ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
0171     ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
0172     ASSERT_NEQ(ima_hash_from_bpf[2], 0, "ima_hash");
0173     ASSERT_NEQ(ima_hash_from_bpf[3], 0, "ima_hash");
0174     ASSERT_NEQ(ima_hash_from_bpf[2], bin_true_sample,
0175            "sample_different_or_err");
0176     ASSERT_EQ(ima_hash_from_bpf[3], ima_hash_from_bpf[2],
0177           "sample_equal_or_err");
0178 
0179     skel->bss->use_ima_file_hash = false;
0180     skel->bss->enable_bprm_creds_for_exec = false;
0181     err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
0182                     "restore-bin");
0183     if (CHECK(err, "restore-bin #3", "err = %d\n", err))
0184         goto close_clean;
0185 
0186     /*
0187      * Test #5
0188      * - Goal: obtain a sample from the kernel_read_file hook
0189      * - Expected result: 2 samples (./ima_setup.sh, policy_test)
0190      */
0191     test_init(skel->bss);
0192     skel->bss->use_ima_file_hash = true;
0193     skel->bss->enable_kernel_read_file = true;
0194     err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
0195                     "load-policy");
0196     if (CHECK(err, "run_measured_process #5", "err = %d\n", err))
0197         goto close_clean;
0198 
0199     err = ring_buffer__consume(ringbuf);
0200     ASSERT_EQ(err, 2, "num_samples_or_err");
0201     ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash");
0202     ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash");
0203 
0204     /*
0205      * Test #6
0206      * - Goal: ensure that the kernel_read_file hook denies an operation
0207      * - Expected result: 0 samples
0208      */
0209     test_init(skel->bss);
0210     skel->bss->enable_kernel_read_file = true;
0211     skel->bss->test_deny = true;
0212     err = _run_measured_process(measured_dir, &skel->bss->monitored_pid,
0213                     "load-policy");
0214     if (CHECK(!err, "run_measured_process #6", "err = %d\n", err))
0215         goto close_clean;
0216 
0217     err = ring_buffer__consume(ringbuf);
0218     ASSERT_EQ(err, 0, "num_samples_or_err");
0219 
0220 close_clean:
0221     snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir);
0222     err = system(cmd);
0223     CHECK(err, "failed to run command", "%s, errno = %d\n", cmd, errno);
0224 close_prog:
0225     ring_buffer__free(ringbuf);
0226     ima__destroy(skel);
0227 }