|
8 | 8 | #include <unistd.h>
|
9 | 9 | #include <test_progs.h>
|
10 | 10 | #include "test_get_xattr.skel.h"
|
| 11 | +#include "test_set_remove_xattr.skel.h" |
11 | 12 | #include "test_fsverity.skel.h"
|
12 | 13 |
|
13 | 14 | static const char testfile[] = "/tmp/test_progs_fs_kfuncs";
|
@@ -72,6 +73,127 @@ static void test_get_xattr(const char *name, const char *value, bool allow_acces
|
72 | 73 | remove(testfile);
|
73 | 74 | }
|
74 | 75 |
|
| 76 | +/* xattr value we will set to security.bpf.foo */ |
| 77 | +static const char value_foo[] = "hello"; |
| 78 | + |
| 79 | +static void read_and_validate_foo(struct test_set_remove_xattr *skel) |
| 80 | +{ |
| 81 | + char value_out[32]; |
| 82 | + int err; |
| 83 | + |
| 84 | + err = getxattr(testfile, skel->rodata->xattr_foo, value_out, sizeof(value_out)); |
| 85 | + ASSERT_EQ(err, sizeof(value_foo), "getxattr size foo"); |
| 86 | + ASSERT_EQ(strncmp(value_out, value_foo, sizeof(value_foo)), 0, "strncmp value_foo"); |
| 87 | +} |
| 88 | + |
| 89 | +static void set_foo(struct test_set_remove_xattr *skel) |
| 90 | +{ |
| 91 | + ASSERT_OK(setxattr(testfile, skel->rodata->xattr_foo, value_foo, strlen(value_foo) + 1, 0), |
| 92 | + "setxattr foo"); |
| 93 | +} |
| 94 | + |
| 95 | +static void validate_bar_match(struct test_set_remove_xattr *skel) |
| 96 | +{ |
| 97 | + char value_out[32]; |
| 98 | + int err; |
| 99 | + |
| 100 | + err = getxattr(testfile, skel->rodata->xattr_bar, value_out, sizeof(value_out)); |
| 101 | + ASSERT_EQ(err, sizeof(skel->data->value_bar), "getxattr size bar"); |
| 102 | + ASSERT_EQ(strncmp(value_out, skel->data->value_bar, sizeof(skel->data->value_bar)), 0, |
| 103 | + "strncmp value_bar"); |
| 104 | +} |
| 105 | + |
| 106 | +static void validate_bar_removed(struct test_set_remove_xattr *skel) |
| 107 | +{ |
| 108 | + char value_out[32]; |
| 109 | + int err; |
| 110 | + |
| 111 | + err = getxattr(testfile, skel->rodata->xattr_bar, value_out, sizeof(value_out)); |
| 112 | + ASSERT_LT(err, 0, "getxattr size bar should fail"); |
| 113 | +} |
| 114 | + |
| 115 | +static void test_set_remove_xattr(void) |
| 116 | +{ |
| 117 | + struct test_set_remove_xattr *skel = NULL; |
| 118 | + int fd = -1, err; |
| 119 | + |
| 120 | + fd = open(testfile, O_CREAT | O_RDONLY, 0644); |
| 121 | + if (!ASSERT_GE(fd, 0, "create_file")) |
| 122 | + return; |
| 123 | + |
| 124 | + close(fd); |
| 125 | + fd = -1; |
| 126 | + |
| 127 | + skel = test_set_remove_xattr__open_and_load(); |
| 128 | + if (!ASSERT_OK_PTR(skel, "test_set_remove_xattr__open_and_load")) |
| 129 | + return; |
| 130 | + |
| 131 | + /* Set security.bpf.foo to "hello" */ |
| 132 | + err = setxattr(testfile, skel->rodata->xattr_foo, value_foo, strlen(value_foo) + 1, 0); |
| 133 | + if (err && errno == EOPNOTSUPP) { |
| 134 | + printf("%s:SKIP:local fs doesn't support xattr (%d)\n" |
| 135 | + "To run this test, make sure /tmp filesystem supports xattr.\n", |
| 136 | + __func__, errno); |
| 137 | + test__skip(); |
| 138 | + goto out; |
| 139 | + } |
| 140 | + |
| 141 | + if (!ASSERT_OK(err, "setxattr")) |
| 142 | + goto out; |
| 143 | + |
| 144 | + skel->bss->monitored_pid = getpid(); |
| 145 | + err = test_set_remove_xattr__attach(skel); |
| 146 | + if (!ASSERT_OK(err, "test_set_remove_xattr__attach")) |
| 147 | + goto out; |
| 148 | + |
| 149 | + /* First, test not _locked version of the kfuncs with getxattr. */ |
| 150 | + |
| 151 | + /* Read security.bpf.foo and trigger test_inode_getxattr. This |
| 152 | + * bpf program will set security.bpf.bar to "world". |
| 153 | + */ |
| 154 | + read_and_validate_foo(skel); |
| 155 | + validate_bar_match(skel); |
| 156 | + |
| 157 | + /* Read security.bpf.foo and trigger test_inode_getxattr again. |
| 158 | + * This will remove xattr security.bpf.bar. |
| 159 | + */ |
| 160 | + read_and_validate_foo(skel); |
| 161 | + validate_bar_removed(skel); |
| 162 | + |
| 163 | + ASSERT_TRUE(skel->bss->set_security_bpf_bar_success, "set_security_bpf_bar_success"); |
| 164 | + ASSERT_TRUE(skel->bss->remove_security_bpf_bar_success, "remove_security_bpf_bar_success"); |
| 165 | + ASSERT_TRUE(skel->bss->set_security_selinux_fail, "set_security_selinux_fail"); |
| 166 | + ASSERT_TRUE(skel->bss->remove_security_selinux_fail, "remove_security_selinux_fail"); |
| 167 | + |
| 168 | + /* Second, test _locked version of the kfuncs, with setxattr */ |
| 169 | + |
| 170 | + /* Set security.bpf.foo and trigger test_inode_setxattr. This |
| 171 | + * bpf program will set security.bpf.bar to "world". |
| 172 | + */ |
| 173 | + set_foo(skel); |
| 174 | + validate_bar_match(skel); |
| 175 | + |
| 176 | + /* Set security.bpf.foo and trigger test_inode_setxattr again. |
| 177 | + * This will remove xattr security.bpf.bar. |
| 178 | + */ |
| 179 | + set_foo(skel); |
| 180 | + validate_bar_removed(skel); |
| 181 | + |
| 182 | + ASSERT_TRUE(skel->bss->locked_set_security_bpf_bar_success, |
| 183 | + "locked_set_security_bpf_bar_success"); |
| 184 | + ASSERT_TRUE(skel->bss->locked_remove_security_bpf_bar_success, |
| 185 | + "locked_remove_security_bpf_bar_success"); |
| 186 | + ASSERT_TRUE(skel->bss->locked_set_security_selinux_fail, |
| 187 | + "locked_set_security_selinux_fail"); |
| 188 | + ASSERT_TRUE(skel->bss->locked_remove_security_selinux_fail, |
| 189 | + "locked_remove_security_selinux_fail"); |
| 190 | + |
| 191 | +out: |
| 192 | + close(fd); |
| 193 | + test_set_remove_xattr__destroy(skel); |
| 194 | + remove(testfile); |
| 195 | +} |
| 196 | + |
75 | 197 | #ifndef SHA256_DIGEST_SIZE
|
76 | 198 | #define SHA256_DIGEST_SIZE 32
|
77 | 199 | #endif
|
@@ -161,6 +283,9 @@ void test_fs_kfuncs(void)
|
161 | 283 | if (test__start_subtest("security_selinux_xattr_error"))
|
162 | 284 | test_get_xattr("security.selinux", "hello", false);
|
163 | 285 |
|
| 286 | + if (test__start_subtest("set_remove_xattr")) |
| 287 | + test_set_remove_xattr(); |
| 288 | + |
164 | 289 | if (test__start_subtest("fsverity"))
|
165 | 290 | test_fsverity();
|
166 | 291 | }
|
0 commit comments