xref: /linux/tools/testing/selftests/bpf/prog_tests/fs_kfuncs.c (revision 566ab427f827b0256d3e8ce0235d088e6a9c28bd)
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 	int v[32];
20 
21 	fd = open(testfile, O_CREAT | O_RDONLY, 0644);
22 	if (!ASSERT_GE(fd, 0, "create_file"))
23 		return;
24 
25 	close(fd);
26 	fd = -1;
27 
28 	err = setxattr(testfile, "user.kfuncs", "hello", sizeof("hello"), 0);
29 	if (err && errno == EOPNOTSUPP) {
30 		printf("%s:SKIP:local fs doesn't support xattr (%d)\n"
31 		       "To run this test, make sure /tmp filesystem supports xattr.\n",
32 		       __func__, errno);
33 		test__skip();
34 		goto out;
35 	}
36 
37 	if (!ASSERT_OK(err, "setxattr"))
38 		goto out;
39 
40 	skel = test_get_xattr__open_and_load();
41 	if (!ASSERT_OK_PTR(skel, "test_get_xattr__open_and_load"))
42 		goto out;
43 
44 	skel->bss->monitored_pid = getpid();
45 	err = test_get_xattr__attach(skel);
46 
47 	if (!ASSERT_OK(err, "test_get_xattr__attach"))
48 		goto out;
49 
50 	fd = open(testfile, O_RDONLY, 0644);
51 	if (!ASSERT_GE(fd, 0, "open_file"))
52 		goto out;
53 
54 	ASSERT_EQ(skel->bss->found_xattr_from_file, 1, "found_xattr_from_file");
55 
56 	/* Trigger security_inode_getxattr */
57 	err = getxattr(testfile, "user.kfuncs", v, sizeof(v));
58 	ASSERT_EQ(err, -1, "getxattr_return");
59 	ASSERT_EQ(errno, EINVAL, "getxattr_errno");
60 	ASSERT_EQ(skel->bss->found_xattr_from_dentry, 1, "found_xattr_from_dentry");
61 
62 out:
63 	close(fd);
64 	test_get_xattr__destroy(skel);
65 	remove(testfile);
66 }
67 
68 #ifndef SHA256_DIGEST_SIZE
69 #define SHA256_DIGEST_SIZE      32
70 #endif
71 
72 static void test_fsverity(void)
73 {
74 	struct fsverity_enable_arg arg = {0};
75 	struct test_fsverity *skel = NULL;
76 	struct fsverity_digest *d;
77 	int fd, err;
78 	char buffer[4096];
79 
80 	fd = open(testfile, O_CREAT | O_RDWR, 0644);
81 	if (!ASSERT_GE(fd, 0, "create_file"))
82 		return;
83 
84 	/* Write random buffer, so the file is not empty */
85 	err = write(fd, buffer, 4096);
86 	if (!ASSERT_EQ(err, 4096, "write_file"))
87 		goto out;
88 	close(fd);
89 
90 	/* Reopen read-only, otherwise FS_IOC_ENABLE_VERITY will fail */
91 	fd = open(testfile, O_RDONLY, 0644);
92 	if (!ASSERT_GE(fd, 0, "open_file1"))
93 		return;
94 
95 	/* Enable fsverity for the file.
96 	 * If the file system doesn't support verity, this will fail. Skip
97 	 * the test in such case.
98 	 */
99 	arg.version = 1;
100 	arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
101 	arg.block_size = 4096;
102 	err = ioctl(fd, FS_IOC_ENABLE_VERITY, &arg);
103 	if (err) {
104 		printf("%s:SKIP:local fs doesn't support fsverity (%d)\n"
105 		       "To run this test, try enable CONFIG_FS_VERITY and enable FSVerity for the filesystem.\n",
106 		       __func__, errno);
107 		test__skip();
108 		goto out;
109 	}
110 
111 	skel = test_fsverity__open_and_load();
112 	if (!ASSERT_OK_PTR(skel, "test_fsverity__open_and_load"))
113 		goto out;
114 
115 	/* Get fsverity_digest from ioctl */
116 	d = (struct fsverity_digest *)skel->bss->expected_digest;
117 	d->digest_algorithm = FS_VERITY_HASH_ALG_SHA256;
118 	d->digest_size = SHA256_DIGEST_SIZE;
119 	err = ioctl(fd, FS_IOC_MEASURE_VERITY, skel->bss->expected_digest);
120 	if (!ASSERT_OK(err, "ioctl_FS_IOC_MEASURE_VERITY"))
121 		goto out;
122 
123 	skel->bss->monitored_pid = getpid();
124 	err = test_fsverity__attach(skel);
125 	if (!ASSERT_OK(err, "test_fsverity__attach"))
126 		goto out;
127 
128 	/* Reopen the file to trigger the program */
129 	close(fd);
130 	fd = open(testfile, O_RDONLY);
131 	if (!ASSERT_GE(fd, 0, "open_file2"))
132 		goto out;
133 
134 	ASSERT_EQ(skel->bss->got_fsverity, 1, "got_fsverity");
135 	ASSERT_EQ(skel->bss->digest_matches, 1, "digest_matches");
136 out:
137 	close(fd);
138 	test_fsverity__destroy(skel);
139 	remove(testfile);
140 }
141 
142 void test_fs_kfuncs(void)
143 {
144 	if (test__start_subtest("xattr"))
145 		test_xattr();
146 
147 	if (test__start_subtest("fsverity"))
148 		test_fsverity();
149 }
150