7#include <sys/eventfd.h>
12static int names_and_faults(
void) {
13 int failed = 0, path_fd = -1, anonymous = -1;
14 struct xa_file file = {.fd = -1};
15 void* bad = MAP_FAILED;
16 char name[257], missing[224], nondirectory[224];
17 CHECK(!xa_create(&file, XA_RAMFS, 0));
18 CHECK(!fsetxattr(file.fd,
"user.keep",
"k", 1, 0));
19 bad = mmap(NULL, xa_page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
20 CHECK(bad != MAP_FAILED);
21 CHECK(fsetxattr(file.fd,
"",
"v", 1, 0) == -1 && errno == ERANGE);
22 CHECK(fgetxattr(file.fd,
"", NULL, 0) == -1 && errno == ERANGE);
23 CHECK(fremovexattr(file.fd,
"") == -1 && errno == ERANGE);
24 CHECK(fsetxattr(file.fd,
"user.",
"v", 1, 0) == -1 && errno == EINVAL);
25 memcpy(name,
"user.", 5);
26 memset(name + 5,
'n', 250);
28 CHECK(!fsetxattr(file.fd, name,
"v", 1, 0));
29 CHECK(!xa_value(&file, XA_FD, name,
"v", 1));
30 CHECK(!fremovexattr(file.fd, name));
33 CHECK(fsetxattr(file.fd, name,
"v", 1, 0) == -1 && errno == ERANGE);
34 CHECK(fgetxattr(file.fd, name, NULL, 0) == -1 && errno == ERANGE);
35 CHECK(fremovexattr(file.fd, name) == -1 && errno == ERANGE);
36 const char high_name[] = {
'u',
's',
'e',
'r',
'.', (char)0x80, (
char)0xff, 0};
37 CHECK(!fsetxattr(file.fd, high_name,
"b", 1, 0));
38 CHECK(!xa_value(&file, XA_FD, high_name,
"b", 1));
39 CHECK(!fremovexattr(file.fd, high_name));
40 CHECK(!fsetxattr(file.fd,
"user.zero\0ignored",
"z", 1, 0));
41 CHECK(!xa_value(&file, XA_FD,
"user.zero",
"z", 1));
42 CHECK(fgetxattr(file.fd,
"user.Zero", NULL, 0) == -1 && errno == ENODATA);
43 CHECK(!fremovexattr(file.fd,
"user.zero"));
44 const char* unsupported[] = {
"trusted.test",
"security.test",
"system.posix_acl_access",
45 "unknown.test",
"User.test"};
46 for (
size_t n = 0; n <
sizeof(unsupported) /
sizeof(unsupported[0]); ++n) {
47 CHECK(fsetxattr(file.fd, unsupported[n],
"v", 1, 0) == -1 && errno == EOPNOTSUPP);
48 CHECK(fgetxattr(file.fd, unsupported[n], NULL, 0) == -1 && errno == EOPNOTSUPP);
49 CHECK(fremovexattr(file.fd, unsupported[n]) == -1 && errno == EOPNOTSUPP);
51 const char* keep[] = {
"user.keep"};
52 CHECK(!xa_names(&file, XA_FD, keep, 1));
53 CHECK(fsetxattr(-1, bad, bad, 1, 4) == -1 && errno == EBADF);
54 CHECK(fgetxattr(-1, bad, bad, 1) == -1 && errno == EBADF);
55 CHECK(flistxattr(-1, bad, 1) == -1 && errno == EBADF);
56 CHECK(fremovexattr(-1, bad) == -1 && errno == EBADF);
57 CHECK(fsetxattr(file.fd, bad,
"v", 1, 0) == -1 && errno == EFAULT);
58 CHECK(fgetxattr(file.fd, bad, NULL, 0) == -1 && errno == EFAULT);
59 CHECK(fremovexattr(file.fd, bad) == -1 && errno == EFAULT);
60 snprintf(missing,
sizeof(missing),
"%s.missing", file.path);
61 CHECK(setxattr(missing, bad, bad, 1, 4) == -1 && errno == EINVAL);
62 CHECK(setxattr(missing,
"user.x", bad, 1, 0) == -1 && errno == EFAULT);
63 CHECK(getxattr(missing, bad, NULL, 0) == -1 && errno == ENOENT);
64 CHECK(removexattr(missing,
"") == -1 && errno == ERANGE);
65 CHECK(removexattr(missing,
"user.x") == -1 && errno == ENOENT);
66 snprintf(nondirectory,
sizeof(nondirectory),
"%s/child", file.path);
67 CHECK(getxattr(nondirectory,
"user.x", NULL, 0) == -1 && errno == ENOTDIR);
68 snprintf(nondirectory,
sizeof(nondirectory),
"%s/", file.path);
69 CHECK(lgetxattr(nondirectory,
"user.keep", NULL, 0) == -1 && errno == ENOTDIR);
70 CHECK(lsetxattr(nondirectory,
"user.keep",
"x", 1, 0) == -1 && errno == ENOTDIR);
71 CHECK((path_fd = open(file.path, O_PATH | O_CLOEXEC)) >= 0);
72 CHECK(fsetxattr(path_fd,
"user.x",
"x", 1, 0) == -1 && errno == EBADF);
73 CHECK(fgetxattr(path_fd,
"user.keep", NULL, 0) == -1 && errno == EBADF);
74 CHECK(flistxattr(path_fd, NULL, 0) == -1 && errno == EBADF);
75 CHECK(fremovexattr(path_fd,
"user.keep") == -1 && errno == EBADF);
76 CHECK((anonymous = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) >= 0);
77 CHECK(fsetxattr(anonymous,
"user.x",
"x", 1, 0) == -1 && errno == EOPNOTSUPP);
78 CHECK(fgetxattr(anonymous,
"user.x", NULL, 0) == -1 && errno == EOPNOTSUPP);
79 CHECK(flistxattr(anonymous, NULL, 0) == -1 && errno == EOPNOTSUPP);
80 CHECK(fremovexattr(anonymous,
"user.x") == -1 && errno == EOPNOTSUPP);
81 CHECK(!xa_value(&file, XA_PATH,
"user.keep",
"k", 1));
87 if (bad != MAP_FAILED)
93static int link_resolution(
void) {
95 struct xa_file file = {.fd = -1}, directory = {.fd = -1};
96 char link_path[224] = {0}, loop_path[224] = {0}, intermediate[448], parent_link[224] = {0};
97 char directory_link[224] = {0}, trailing[256];
98 CHECK(!xa_create(&file, XA_EXT2, 0));
99 CHECK(!fsetxattr(file.fd,
"user.key",
"a", 1, 0));
100 snprintf(link_path,
sizeof(link_path),
"%s.link", file.path);
101 snprintf(loop_path,
sizeof(loop_path),
"%s.loop", file.path);
102 snprintf(parent_link,
sizeof(parent_link),
"%s.parent", file.path);
103 CHECK(!symlink(file.path + 1, link_path));
104 CHECK(!symlink(loop_path + 1, loop_path));
105 CHECK(!symlink(
".", parent_link));
108 CHECK(getxattr(link_path,
"user.key", &value, 1) == 1 && value ==
'a');
109 CHECK(!setxattr(link_path,
"user.key",
"b", 1, XATTR_REPLACE));
110 CHECK(!xa_value(&file, XA_FD,
"user.key",
"b", 1));
111 CHECK(lgetxattr(link_path,
"user.key", NULL, 0) == -1 && errno == ENODATA);
112 CHECK(lsetxattr(link_path,
"user.key",
"x", 1, 0) == -1 && errno == EPERM);
113 CHECK(lremovexattr(link_path,
"user.key") == -1 && errno == EPERM);
114 CHECK(llistxattr(link_path, NULL, 0) == 0);
115 CHECK(listxattr(link_path, NULL, 0) == (ssize_t)
sizeof(
"user.key"));
116 snprintf(intermediate,
sizeof(intermediate),
"%s%s", parent_link, file.path);
117 CHECK(!lsetxattr(intermediate,
"user.key",
"c", 1, 0));
118 CHECK(lgetxattr(file.path + 1,
"user.key", &value, 1) == 1 && value ==
'c');
119 CHECK(!xa_create(&directory, XA_EXT2, 1));
120 snprintf(directory_link,
sizeof(directory_link),
"%s.link", directory.path);
121 CHECK(!symlink(directory.path + 1, directory_link));
122 snprintf(trailing,
sizeof(trailing),
"%s/", directory_link);
123 CHECK(!lsetxattr(trailing,
"user.directory",
"d", 1, 0));
124 CHECK(lgetxattr(trailing,
"user.directory", &value, 1) == 1 && value ==
'd');
125 CHECK(llistxattr(trailing, NULL, 0) == (ssize_t)
sizeof(
"user.directory"));
126 CHECK(!lremovexattr(trailing,
"user.directory"));
127 CHECK(!removexattr(link_path,
"user.key"));
128 CHECK(fgetxattr(file.fd,
"user.key", NULL, 0) == -1 && errno == ENODATA);
129 CHECK(getxattr(loop_path,
"user.key", NULL, 0) == -1 && errno == ELOOP);
130 CHECK(!unlink(file.path));
132 CHECK(getxattr(link_path,
"user.key", NULL, 0) == -1 && errno == ENOENT);
133 CHECK(lgetxattr(link_path,
"user.key", NULL, 0) == -1 && errno == ENODATA);
135 if (directory_link[0])
136 unlink(directory_link);
137 xa_close(&directory);
148int xa_admission(
void) {
149 return names_and_faults() || link_resolution();