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