Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests/bpf: Check if the digest is refreshed after a file write

Verify that bpf_ima_inode_hash() returns a non-fresh digest after a file
write, and that bpf_ima_file_hash() returns a fresh digest. Verification is
done by requesting the digest from the bprm_creds_for_exec hook, called
before ima_bprm_check().

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20220302111404.193900-7-roberto.sassu@huawei.com

authored by

Roberto Sassu and committed by
Alexei Starovoitov
91e8fa25 27a77d0d

+103 -4
+23 -1
tools/testing/selftests/bpf/ima_setup.sh
··· 12 12 13 13 usage() 14 14 { 15 - echo "Usage: $0 <setup|cleanup|run> <existing_tmp_dir>" 15 + echo "Usage: $0 <setup|cleanup|run|modify-bin|restore-bin> <existing_tmp_dir>" 16 16 exit 1 17 17 } 18 18 ··· 77 77 exec "${copied_bin_path}" 78 78 } 79 79 80 + modify_bin() 81 + { 82 + local tmp_dir="$1" 83 + local mount_dir="${tmp_dir}/mnt" 84 + local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})" 85 + 86 + echo "mod" >> "${copied_bin_path}" 87 + } 88 + 89 + restore_bin() 90 + { 91 + local tmp_dir="$1" 92 + local mount_dir="${tmp_dir}/mnt" 93 + local copied_bin_path="${mount_dir}/$(basename ${TEST_BINARY})" 94 + 95 + truncate -s -4 "${copied_bin_path}" 96 + } 97 + 80 98 catch() 81 99 { 82 100 local exit_code="$1" ··· 123 105 cleanup "${tmp_dir}" 124 106 elif [[ "${action}" == "run" ]]; then 125 107 run "${tmp_dir}" 108 + elif [[ "${action}" == "modify-bin" ]]; then 109 + modify_bin "${tmp_dir}" 110 + elif [[ "${action}" == "restore-bin" ]]; then 111 + restore_bin "${tmp_dir}" 126 112 else 127 113 echo "Unknown action: ${action}" 128 114 exit 1
+69 -3
tools/testing/selftests/bpf/prog_tests/test_ima.c
··· 13 13 14 14 #include "ima.skel.h" 15 15 16 - #define MAX_SAMPLES 2 16 + #define MAX_SAMPLES 4 17 17 18 - static int run_measured_process(const char *measured_dir, u32 *monitored_pid) 18 + static int _run_measured_process(const char *measured_dir, u32 *monitored_pid, 19 + const char *cmd) 19 20 { 20 21 int child_pid, child_status; 21 22 22 23 child_pid = fork(); 23 24 if (child_pid == 0) { 24 25 *monitored_pid = getpid(); 25 - execlp("./ima_setup.sh", "./ima_setup.sh", "run", measured_dir, 26 + execlp("./ima_setup.sh", "./ima_setup.sh", cmd, measured_dir, 26 27 NULL); 27 28 exit(errno); 28 29 ··· 33 32 } 34 33 35 34 return -EINVAL; 35 + } 36 + 37 + static int run_measured_process(const char *measured_dir, u32 *monitored_pid) 38 + { 39 + return _run_measured_process(measured_dir, monitored_pid, "run"); 36 40 } 37 41 38 42 static u64 ima_hash_from_bpf[MAX_SAMPLES]; ··· 57 51 ima_hash_from_bpf_idx = 0; 58 52 59 53 bss->use_ima_file_hash = false; 54 + bss->enable_bprm_creds_for_exec = false; 60 55 } 61 56 62 57 void test_test_ima(void) ··· 65 58 char measured_dir_template[] = "/tmp/ima_measuredXXXXXX"; 66 59 struct ring_buffer *ringbuf = NULL; 67 60 const char *measured_dir; 61 + u64 bin_true_sample; 68 62 char cmd[256]; 69 63 70 64 int err, duration = 0; ··· 122 114 ASSERT_EQ(err, 2, "num_samples_or_err"); 123 115 ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 124 116 ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 117 + bin_true_sample = ima_hash_from_bpf[1]; 118 + 119 + /* 120 + * Test #3 121 + * - Goal: confirm that bpf_ima_inode_hash() returns a non-fresh digest 122 + * - Expected result: 2 samples (/bin/true: non-fresh, fresh) 123 + */ 124 + test_init(skel->bss); 125 + 126 + err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 127 + "modify-bin"); 128 + if (CHECK(err, "modify-bin #3", "err = %d\n", err)) 129 + goto close_clean; 130 + 131 + skel->bss->enable_bprm_creds_for_exec = true; 132 + err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 133 + if (CHECK(err, "run_measured_process #3", "err = %d\n", err)) 134 + goto close_clean; 135 + 136 + err = ring_buffer__consume(ringbuf); 137 + ASSERT_EQ(err, 2, "num_samples_or_err"); 138 + ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 139 + ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 140 + ASSERT_EQ(ima_hash_from_bpf[0], bin_true_sample, "sample_equal_or_err"); 141 + /* IMA refreshed the digest. */ 142 + ASSERT_NEQ(ima_hash_from_bpf[1], bin_true_sample, 143 + "sample_different_or_err"); 144 + 145 + /* 146 + * Test #4 147 + * - Goal: verify that bpf_ima_file_hash() returns a fresh digest 148 + * - Expected result: 4 samples (./ima_setup.sh: fresh, fresh; 149 + * /bin/true: fresh, fresh) 150 + */ 151 + test_init(skel->bss); 152 + skel->bss->use_ima_file_hash = true; 153 + skel->bss->enable_bprm_creds_for_exec = true; 154 + err = run_measured_process(measured_dir, &skel->bss->monitored_pid); 155 + if (CHECK(err, "run_measured_process #4", "err = %d\n", err)) 156 + goto close_clean; 157 + 158 + err = ring_buffer__consume(ringbuf); 159 + ASSERT_EQ(err, 4, "num_samples_or_err"); 160 + ASSERT_NEQ(ima_hash_from_bpf[0], 0, "ima_hash"); 161 + ASSERT_NEQ(ima_hash_from_bpf[1], 0, "ima_hash"); 162 + ASSERT_NEQ(ima_hash_from_bpf[2], 0, "ima_hash"); 163 + ASSERT_NEQ(ima_hash_from_bpf[3], 0, "ima_hash"); 164 + ASSERT_NEQ(ima_hash_from_bpf[2], bin_true_sample, 165 + "sample_different_or_err"); 166 + ASSERT_EQ(ima_hash_from_bpf[3], ima_hash_from_bpf[2], 167 + "sample_equal_or_err"); 168 + 169 + skel->bss->use_ima_file_hash = false; 170 + skel->bss->enable_bprm_creds_for_exec = false; 171 + err = _run_measured_process(measured_dir, &skel->bss->monitored_pid, 172 + "restore-bin"); 173 + if (CHECK(err, "restore-bin #3", "err = %d\n", err)) 174 + goto close_clean; 125 175 126 176 close_clean: 127 177 snprintf(cmd, sizeof(cmd), "./ima_setup.sh cleanup %s", measured_dir);
+11
tools/testing/selftests/bpf/progs/ima.c
··· 19 19 char _license[] SEC("license") = "GPL"; 20 20 21 21 bool use_ima_file_hash; 22 + bool enable_bprm_creds_for_exec; 22 23 23 24 static void ima_test_common(struct file *file) 24 25 { ··· 54 53 void BPF_PROG(bprm_committed_creds, struct linux_binprm *bprm) 55 54 { 56 55 ima_test_common(bprm->file); 56 + } 57 + 58 + SEC("lsm.s/bprm_creds_for_exec") 59 + int BPF_PROG(bprm_creds_for_exec, struct linux_binprm *bprm) 60 + { 61 + if (!enable_bprm_creds_for_exec) 62 + return 0; 63 + 64 + ima_test_common(bprm->file); 65 + return 0; 57 66 }