10static int cycle(
int backend) {
12 struct xa_file file = {.fd = -1};
13 unsigned char value[257], output[274];
14 unsigned char* fault = MAP_FAILED;
15 const char* names[] = {
"user.binary",
"user.empty"};
16 for (
size_t n = 0; n <
sizeof(value); ++n)
17 value[n] = (
unsigned char)n;
18 CHECK(!xa_create(&file, backend, 0));
19 fault = mmap(NULL, 2 * xa_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
20 CHECK(fault != MAP_FAILED && !mprotect(fault + xa_page, xa_page, PROT_NONE));
21 fault[xa_page - 1] = 0x56;
22 void* bad = fault + xa_page;
23 const int first = backend == XA_MEMFD ? XA_FD : XA_PATH;
24 for (
int how = first; how <= XA_FD; ++how) {
25 CHECK(!xa_names(&file, how, NULL, 0));
26 CHECK(xa_list(&file, how, bad, 1) == 0);
27 CHECK(!xa_set(&file, how, names[0], value,
sizeof(value), XATTR_CREATE));
28 for (
int read_how = first; read_how <= XA_FD; ++read_how)
29 CHECK(!xa_value(&file, read_how, names[0], value,
sizeof(value)));
30 CHECK(xa_get(&file, how, names[0], bad, 0) ==
sizeof(value));
31 memset(output, 0xa5,
sizeof(output));
32 CHECK(xa_get(&file, how, names[0], output,
sizeof(value)) ==
sizeof(value));
33 CHECK(!memcmp(output, value,
sizeof(value)) && output[
sizeof(value)] == 0xa5);
34 memset(output, 0xa5,
sizeof(output));
35 CHECK(xa_get(&file, how, names[0], output,
sizeof(value) - 1) == -1 && errno == ERANGE);
36 for (
size_t n = 0; n <
sizeof(output); ++n)
37 CHECK(output[n] == 0xa5);
38 CHECK(xa_get(&file, how, names[0], output, SIZE_MAX) ==
sizeof(value));
39 CHECK(!memcmp(output, value,
sizeof(value)) && output[
sizeof(value)] == 0xa5);
40 CHECK(xa_set(&file, how, names[0],
"x", 1, XATTR_CREATE) == -1 && errno == EEXIST);
41 CHECK(xa_set(&file, how, names[0],
"x", 1, XATTR_CREATE | XATTR_REPLACE) == -1 &&
43 CHECK(xa_set(&file, how, names[0],
"x", 1, 4) == -1 && errno == EINVAL);
44 CHECK(xa_set(&file, how, names[0], bad, 1, XATTR_REPLACE) == -1 && errno == EFAULT);
45 CHECK(xa_set(&file, how, names[0], fault + xa_page - 1, 2, 0) == -1 && errno == EFAULT);
46 CHECK(!xa_value(&file, how, names[0], value,
sizeof(value)));
47 CHECK(xa_get(&file, how, names[0], bad,
sizeof(value)) == -1 && errno == EFAULT);
48 CHECK(!xa_value(&file, how, names[0], value,
sizeof(value)));
49 CHECK(!xa_set(&file, how, names[1], bad, 0, 0));
50 CHECK(xa_get(&file, how, names[1], bad, 1) == 0);
51 CHECK(xa_set(&file, how, names[1], NULL, 0, XATTR_CREATE) == -1 && errno == EEXIST);
52 CHECK(!xa_names(&file, how, names, 2));
53 const size_t list_size = strlen(names[0]) + strlen(names[1]) + 2;
54 CHECK(xa_list(&file, how, bad, 0) == (ssize_t)list_size);
55 memset(output, 0xa5,
sizeof(output));
56 CHECK(xa_list(&file, how, (
char*)output, list_size - 1) == -1 && errno == ERANGE);
57 for (
size_t n = 0; n <
sizeof(output); ++n)
58 CHECK(output[n] == 0xa5);
59 CHECK(xa_list(&file, how, (
char*)output, SIZE_MAX) == (ssize_t)list_size);
60 CHECK(output[list_size] == 0xa5);
61 CHECK(xa_list(&file, how, bad, list_size) == -1 && errno == EFAULT);
62 CHECK(!xa_names(&file, how, names, 2));
63 CHECK(!xa_set(&file, how, names[0], value, 191, XATTR_REPLACE));
64 CHECK(!xa_value(&file, how, names[0], value, 191));
65 CHECK(!xa_set(&file, how, names[0],
"last", 4, 0));
66 CHECK(!xa_value(&file, how, names[0],
"last", 4));
67 CHECK(!xa_remove(&file, how, names[0]));
68 CHECK(xa_remove(&file, how, names[0]) == -1 && errno == ENODATA);
69 CHECK(xa_set(&file, how, names[0],
"x", 1, XATTR_REPLACE) == -1 && errno == ENODATA);
70 CHECK(xa_set(&file, how, names[0],
"x", 1, XATTR_CREATE | XATTR_REPLACE) == -1 &&
72 CHECK(!xa_remove(&file, how, names[1]));
73 CHECK(!xa_names(&file, how, NULL, 0));
76 if (fault != MAP_FAILED)
77 munmap(fault, 2 * xa_page);
80 fprintf(stderr,
"XATTR-CONTRACT: values backend=%d\n", backend);
84static int memory_limits(
int backend) {
86 struct xa_file file = {.fd = -1};
87 unsigned char* large = malloc(65537);
88 CHECK(large != NULL && !xa_create(&file, backend, 0));
89 for (
size_t n = 0; n < 65537; ++n)
90 large[n] = (
unsigned char)(n * 29 + (n >> 8));
91 CHECK(!fsetxattr(file.fd,
"user.large", large, 65536, 0));
92 CHECK(!xa_value(&file, XA_FD,
"user.large", large, 65536));
93 CHECK(fsetxattr(file.fd,
"user.large", large, 65537, 0) == -1 && errno == E2BIG);
94 CHECK(!xa_value(&file, XA_FD,
"user.large", large, 65536));
95 CHECK(!fsetxattr(file.fd,
"user.second", large, 65536, 0));
96 CHECK(!fsetxattr(file.fd,
"user.third", large, 65536, 0));
97 CHECK(fsetxattr(file.fd,
"user.fourth", large, 65536, 0) == -1 && errno == ENOSPC);
98 CHECK(!xa_value(&file, XA_FD,
"user.large", large, 65536));
99 CHECK(!fremovexattr(file.fd,
"user.large"));
100 CHECK(!fsetxattr(file.fd,
"user.small", large, 32768, 0));
101 CHECK(!fsetxattr(file.fd,
"user.fourth", large, 65536, 0));
102 CHECK(fsetxattr(file.fd,
"user.small", large, 65536, XATTR_REPLACE) == -1 && errno == ENOSPC);
103 CHECK(!xa_value(&file, XA_FD,
"user.small", large, 32768));
105 CHECK(!xa_create(&file, backend, 0));
107 const char* pointers[128];
108 for (
size_t n = 0; n < 128; ++n) {
109 snprintf(names[n],
sizeof(names[n]),
"user.entry%03zu", n);
110 pointers[n] = names[n];
111 CHECK(!fsetxattr(file.fd, names[n], NULL, 0, XATTR_CREATE));
113 CHECK(!xa_names(&file, XA_FD, pointers, 128));
114 CHECK(fsetxattr(file.fd,
"user.overflow", NULL, 0, 0) == -1 && errno == ENOSPC);
115 CHECK(!fremovexattr(file.fd, names[17]));
116 CHECK(!fsetxattr(file.fd,
"user.overflow", NULL, 0, 0));
117 pointers[17] =
"user.overflow";
118 CHECK(!xa_names(&file, XA_FD, pointers, 128));
126 for (
int backend = XA_MEMFD; backend <= XA_EXT2; ++backend) {
130 return memory_limits(XA_MEMFD) || memory_limits(XA_RAMFS);