Skip to content

Commit 341f06f

Browse files
liu-song-6Alexei Starovoitov
authored andcommitted
selftests/bpf: Add tests for filesystem kfuncs
Add selftests for two new filesystem kfuncs: 1. bpf_get_file_xattr 2. bpf_get_fsverity_digest These tests simply make sure the two kfuncs work. Another selftest will be added to demonstrate how to use these kfuncs to verify file signature. CONFIG_FS_VERITY is added to selftests config. However, this is not sufficient to guarantee bpf_get_fsverity_digest works. This is because fsverity need to be enabled at file system level (for example, with tune2fs on ext4). If local file system doesn't have this feature enabled, just skip the test. Signed-off-by: Song Liu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 6b0ae45 commit 341f06f

File tree

5 files changed

+223
-0
lines changed

5 files changed

+223
-0
lines changed

tools/testing/selftests/bpf/bpf_kfuncs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,7 @@ void *bpf_cast_to_kern_ctx(void *) __ksym;
5555

5656
void *bpf_rdonly_cast(void *obj, __u32 btf_id) __ksym;
5757

58+
extern int bpf_get_file_xattr(struct file *file, const char *name,
59+
struct bpf_dynptr *value_ptr) __ksym;
60+
extern int bpf_get_fsverity_digest(struct file *file, struct bpf_dynptr *digest_ptr) __ksym;
5861
#endif

tools/testing/selftests/bpf/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ CONFIG_FPROBE=y
2323
CONFIG_FTRACE_SYSCALLS=y
2424
CONFIG_FUNCTION_ERROR_INJECTION=y
2525
CONFIG_FUNCTION_TRACER=y
26+
CONFIG_FS_VERITY=y
2627
CONFIG_GENEVE=y
2728
CONFIG_IKCONFIG=y
2829
CONFIG_IKCONFIG_PROC=y
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3+
4+
#include <stdlib.h>
5+
#include <sys/types.h>
6+
#include <sys/xattr.h>
7+
#include <linux/fsverity.h>
8+
#include <unistd.h>
9+
#include <test_progs.h>
10+
#include "test_get_xattr.skel.h"
11+
#include "test_fsverity.skel.h"
12+
13+
static const char testfile[] = "/tmp/test_progs_fs_kfuncs";
14+
15+
static void test_xattr(void)
16+
{
17+
struct test_get_xattr *skel = NULL;
18+
int fd = -1, err;
19+
20+
fd = open(testfile, O_CREAT | O_RDONLY, 0644);
21+
if (!ASSERT_GE(fd, 0, "create_file"))
22+
return;
23+
24+
close(fd);
25+
fd = -1;
26+
27+
err = setxattr(testfile, "user.kfuncs", "hello", sizeof("hello"), 0);
28+
if (!ASSERT_OK(err, "setxattr"))
29+
goto out;
30+
31+
skel = test_get_xattr__open_and_load();
32+
if (!ASSERT_OK_PTR(skel, "test_get_xattr__open_and_load"))
33+
goto out;
34+
35+
skel->bss->monitored_pid = getpid();
36+
err = test_get_xattr__attach(skel);
37+
38+
if (!ASSERT_OK(err, "test_get_xattr__attach"))
39+
goto out;
40+
41+
fd = open(testfile, O_RDONLY, 0644);
42+
if (!ASSERT_GE(fd, 0, "open_file"))
43+
goto out;
44+
45+
ASSERT_EQ(skel->bss->found_xattr, 1, "found_xattr");
46+
47+
out:
48+
close(fd);
49+
test_get_xattr__destroy(skel);
50+
remove(testfile);
51+
}
52+
53+
#ifndef SHA256_DIGEST_SIZE
54+
#define SHA256_DIGEST_SIZE 32
55+
#endif
56+
57+
static void test_fsverity(void)
58+
{
59+
struct fsverity_enable_arg arg = {0};
60+
struct test_fsverity *skel = NULL;
61+
struct fsverity_digest *d;
62+
int fd, err;
63+
char buffer[4096];
64+
65+
fd = open(testfile, O_CREAT | O_RDWR, 0644);
66+
if (!ASSERT_GE(fd, 0, "create_file"))
67+
return;
68+
69+
/* Write random buffer, so the file is not empty */
70+
err = write(fd, buffer, 4096);
71+
if (!ASSERT_EQ(err, 4096, "write_file"))
72+
goto out;
73+
close(fd);
74+
75+
/* Reopen read-only, otherwise FS_IOC_ENABLE_VERITY will fail */
76+
fd = open(testfile, O_RDONLY, 0644);
77+
if (!ASSERT_GE(fd, 0, "open_file1"))
78+
return;
79+
80+
/* Enable fsverity for the file.
81+
* If the file system doesn't support verity, this will fail. Skip
82+
* the test in such case.
83+
*/
84+
arg.version = 1;
85+
arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
86+
arg.block_size = 4096;
87+
err = ioctl(fd, FS_IOC_ENABLE_VERITY, &arg);
88+
if (err) {
89+
printf("%s:SKIP:local fs doesn't support fsverity (%d)\n"
90+
"To run this test, try enable CONFIG_FS_VERITY and enable FSVerity for the filesystem.\n",
91+
__func__, errno);
92+
test__skip();
93+
goto out;
94+
}
95+
96+
skel = test_fsverity__open_and_load();
97+
if (!ASSERT_OK_PTR(skel, "test_fsverity__open_and_load"))
98+
goto out;
99+
100+
/* Get fsverity_digest from ioctl */
101+
d = (struct fsverity_digest *)skel->bss->expected_digest;
102+
d->digest_algorithm = FS_VERITY_HASH_ALG_SHA256;
103+
d->digest_size = SHA256_DIGEST_SIZE;
104+
err = ioctl(fd, FS_IOC_MEASURE_VERITY, skel->bss->expected_digest);
105+
if (!ASSERT_OK(err, "ioctl_FS_IOC_MEASURE_VERITY"))
106+
goto out;
107+
108+
skel->bss->monitored_pid = getpid();
109+
err = test_fsverity__attach(skel);
110+
if (!ASSERT_OK(err, "test_fsverity__attach"))
111+
goto out;
112+
113+
/* Reopen the file to trigger the program */
114+
close(fd);
115+
fd = open(testfile, O_RDONLY);
116+
if (!ASSERT_GE(fd, 0, "open_file2"))
117+
goto out;
118+
119+
ASSERT_EQ(skel->bss->got_fsverity, 1, "got_fsverity");
120+
ASSERT_EQ(skel->bss->digest_matches, 1, "digest_matches");
121+
out:
122+
close(fd);
123+
test_fsverity__destroy(skel);
124+
remove(testfile);
125+
}
126+
127+
void test_fs_kfuncs(void)
128+
{
129+
if (test__start_subtest("xattr"))
130+
test_xattr();
131+
132+
if (test__start_subtest("fsverity"))
133+
test_fsverity();
134+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
#include "bpf_kfuncs.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
#ifndef SHA256_DIGEST_SIZE
12+
#define SHA256_DIGEST_SIZE 32
13+
#endif
14+
15+
#define SIZEOF_STRUCT_FSVERITY_DIGEST 4 /* sizeof(struct fsverity_digest) */
16+
17+
char expected_digest[SIZEOF_STRUCT_FSVERITY_DIGEST + SHA256_DIGEST_SIZE];
18+
char digest[SIZEOF_STRUCT_FSVERITY_DIGEST + SHA256_DIGEST_SIZE];
19+
__u32 monitored_pid;
20+
__u32 got_fsverity;
21+
__u32 digest_matches;
22+
23+
SEC("lsm.s/file_open")
24+
int BPF_PROG(test_file_open, struct file *f)
25+
{
26+
struct bpf_dynptr digest_ptr;
27+
__u32 pid;
28+
int ret;
29+
int i;
30+
31+
pid = bpf_get_current_pid_tgid() >> 32;
32+
if (pid != monitored_pid)
33+
return 0;
34+
35+
bpf_dynptr_from_mem(digest, sizeof(digest), 0, &digest_ptr);
36+
ret = bpf_get_fsverity_digest(f, &digest_ptr);
37+
if (ret < 0)
38+
return 0;
39+
got_fsverity = 1;
40+
41+
for (i = 0; i < sizeof(digest); i++) {
42+
if (digest[i] != expected_digest[i])
43+
return 0;
44+
}
45+
46+
digest_matches = 1;
47+
return 0;
48+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
#include "bpf_kfuncs.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
__u32 monitored_pid;
12+
__u32 found_xattr;
13+
14+
static const char expected_value[] = "hello";
15+
char value[32];
16+
17+
SEC("lsm.s/file_open")
18+
int BPF_PROG(test_file_open, struct file *f)
19+
{
20+
struct bpf_dynptr value_ptr;
21+
__u32 pid;
22+
int ret;
23+
24+
pid = bpf_get_current_pid_tgid() >> 32;
25+
if (pid != monitored_pid)
26+
return 0;
27+
28+
bpf_dynptr_from_mem(value, sizeof(value), 0, &value_ptr);
29+
30+
ret = bpf_get_file_xattr(f, "user.kfuncs", &value_ptr);
31+
if (ret != sizeof(expected_value))
32+
return 0;
33+
if (bpf_strncmp(value, ret, expected_value))
34+
return 0;
35+
found_xattr = 1;
36+
return 0;
37+
}

0 commit comments

Comments
 (0)