1*d21b3d34SFangrui Song // RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
2*d21b3d34SFangrui Song // RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
3*d21b3d34SFangrui Song // RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
4*d21b3d34SFangrui Song
5*d21b3d34SFangrui Song #include <argz.h>
6*d21b3d34SFangrui Song #include <assert.h>
7*d21b3d34SFangrui Song #include <sys/types.h>
8*d21b3d34SFangrui Song #include <errno.h>
9*d21b3d34SFangrui Song #include <fcntl.h>
10*d21b3d34SFangrui Song #include <stdio.h>
11*d21b3d34SFangrui Song #include <stdlib.h>
12*d21b3d34SFangrui Song #include <string.h>
13*d21b3d34SFangrui Song
14*d21b3d34SFangrui Song #include <sanitizer/msan_interface.h>
15*d21b3d34SFangrui Song
16*d21b3d34SFangrui Song // Do not depend on libattr headers.
17*d21b3d34SFangrui Song #ifndef ENOATTR
18*d21b3d34SFangrui Song #define ENOATTR ENODATA
19*d21b3d34SFangrui Song #endif
20*d21b3d34SFangrui Song
21*d21b3d34SFangrui Song extern "C" {
22*d21b3d34SFangrui Song ssize_t listxattr(const char *path, char *list, size_t size);
23*d21b3d34SFangrui Song ssize_t llistxattr(const char *path, char *list, size_t size);
24*d21b3d34SFangrui Song ssize_t flistxattr(int fd, char *list, size_t size);
25*d21b3d34SFangrui Song ssize_t getxattr(const char *path, const char *name, void *value, size_t size);
26*d21b3d34SFangrui Song ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size);
27*d21b3d34SFangrui Song ssize_t fgetxattr(int fd, const char *name, void *value, size_t size);
28*d21b3d34SFangrui Song }
29*d21b3d34SFangrui Song
30*d21b3d34SFangrui Song char g_path[1024];
31*d21b3d34SFangrui Song int g_fd;
32*d21b3d34SFangrui Song
33*d21b3d34SFangrui Song // Life before closures...
listxattr_wrapper(char * buf,size_t size)34*d21b3d34SFangrui Song ssize_t listxattr_wrapper(char *buf, size_t size) {
35*d21b3d34SFangrui Song return listxattr(g_path, buf, size);
36*d21b3d34SFangrui Song }
37*d21b3d34SFangrui Song
llistxattr_wrapper(char * buf,size_t size)38*d21b3d34SFangrui Song ssize_t llistxattr_wrapper(char *buf, size_t size) {
39*d21b3d34SFangrui Song return llistxattr(g_path, buf, size);
40*d21b3d34SFangrui Song }
41*d21b3d34SFangrui Song
flistxattr_wrapper(char * buf,size_t size)42*d21b3d34SFangrui Song ssize_t flistxattr_wrapper(char *buf, size_t size) {
43*d21b3d34SFangrui Song return flistxattr(g_fd, buf, size);
44*d21b3d34SFangrui Song }
45*d21b3d34SFangrui Song
getxattr_wrapper(const char * name,char * buf,size_t size)46*d21b3d34SFangrui Song ssize_t getxattr_wrapper(const char *name, char *buf, size_t size) {
47*d21b3d34SFangrui Song return getxattr(g_path, name, buf, size);
48*d21b3d34SFangrui Song }
49*d21b3d34SFangrui Song
lgetxattr_wrapper(const char * name,char * buf,size_t size)50*d21b3d34SFangrui Song ssize_t lgetxattr_wrapper(const char *name, char *buf, size_t size) {
51*d21b3d34SFangrui Song return lgetxattr(g_path, name, buf, size);
52*d21b3d34SFangrui Song }
53*d21b3d34SFangrui Song
fgetxattr_wrapper(const char * name,char * buf,size_t size)54*d21b3d34SFangrui Song ssize_t fgetxattr_wrapper(const char *name, char *buf, size_t size) {
55*d21b3d34SFangrui Song return fgetxattr(g_fd, name, buf, size);
56*d21b3d34SFangrui Song }
57*d21b3d34SFangrui Song
test_list(ssize_t fun (char *,size_t),char ** buf)58*d21b3d34SFangrui Song size_t test_list(ssize_t fun(char*, size_t), char **buf) {
59*d21b3d34SFangrui Song int buf_size = 1024;
60*d21b3d34SFangrui Song while (true) {
61*d21b3d34SFangrui Song *buf = (char *)malloc(buf_size);
62*d21b3d34SFangrui Song assert(__msan_test_shadow(*buf, buf_size) != -1);
63*d21b3d34SFangrui Song ssize_t res = fun(*buf, buf_size);
64*d21b3d34SFangrui Song if (res >= 0) {
65*d21b3d34SFangrui Song assert(__msan_test_shadow(*buf, buf_size) == res);
66*d21b3d34SFangrui Song return res;
67*d21b3d34SFangrui Song }
68*d21b3d34SFangrui Song if (errno == ENOTSUP) {
69*d21b3d34SFangrui Song printf("Extended attributes are disabled. *xattr test is a no-op.\n");
70*d21b3d34SFangrui Song exit(0);
71*d21b3d34SFangrui Song }
72*d21b3d34SFangrui Song assert(errno == ERANGE);
73*d21b3d34SFangrui Song free(*buf);
74*d21b3d34SFangrui Song buf_size *= 2;
75*d21b3d34SFangrui Song }
76*d21b3d34SFangrui Song }
77*d21b3d34SFangrui Song
78*d21b3d34SFangrui Song // True means success. False means result inconclusive because we don't have
79*d21b3d34SFangrui Song // access to this attribute.
test_get_single_attr(ssize_t fun (const char *,char *,size_t),const char * attr_name)80*d21b3d34SFangrui Song bool test_get_single_attr(ssize_t fun(const char *, char *, size_t),
81*d21b3d34SFangrui Song const char *attr_name) {
82*d21b3d34SFangrui Song char *buf;
83*d21b3d34SFangrui Song int buf_size = 1024;
84*d21b3d34SFangrui Song while (true) {
85*d21b3d34SFangrui Song buf = (char *)malloc(buf_size);
86*d21b3d34SFangrui Song assert(__msan_test_shadow(buf, buf_size) != -1);
87*d21b3d34SFangrui Song ssize_t res = fun(attr_name, buf, buf_size);
88*d21b3d34SFangrui Song if (res >= 0) {
89*d21b3d34SFangrui Song assert(__msan_test_shadow(buf, buf_size) == res);
90*d21b3d34SFangrui Song free(buf);
91*d21b3d34SFangrui Song return true;
92*d21b3d34SFangrui Song }
93*d21b3d34SFangrui Song if (errno == ENOTSUP) {
94*d21b3d34SFangrui Song printf("Extended attributes are disabled. *xattr test is a no-op.\n");
95*d21b3d34SFangrui Song exit(0);
96*d21b3d34SFangrui Song }
97*d21b3d34SFangrui Song if (errno == ENOATTR)
98*d21b3d34SFangrui Song return false;
99*d21b3d34SFangrui Song assert(errno == ERANGE);
100*d21b3d34SFangrui Song free(buf);
101*d21b3d34SFangrui Song buf_size *= 2;
102*d21b3d34SFangrui Song }
103*d21b3d34SFangrui Song }
104*d21b3d34SFangrui Song
test_get(ssize_t fun (const char *,char *,size_t),const char * attr_list,size_t attr_list_size)105*d21b3d34SFangrui Song void test_get(ssize_t fun(const char *, char *, size_t), const char *attr_list,
106*d21b3d34SFangrui Song size_t attr_list_size) {
107*d21b3d34SFangrui Song // Try every attribute, until we see one we can access. Attribute names are
108*d21b3d34SFangrui Song // null-separated strings in attr_list.
109*d21b3d34SFangrui Song size_t attr_list_len = argz_count(attr_list, attr_list_size);
110*d21b3d34SFangrui Song size_t argv_size = (attr_list_len + 1) * sizeof(char *);
111*d21b3d34SFangrui Song char **attrs = (char **)malloc(argv_size);
112*d21b3d34SFangrui Song argz_extract(attr_list, attr_list_size, attrs);
113*d21b3d34SFangrui Song // TODO(smatveev): we need proper argz_* interceptors
114*d21b3d34SFangrui Song __msan_unpoison(attrs, argv_size);
115*d21b3d34SFangrui Song for (size_t i = 0; (i < attr_list_len) && attrs[i]; i++) {
116*d21b3d34SFangrui Song if (test_get_single_attr(fun, attrs[i]))
117*d21b3d34SFangrui Song return;
118*d21b3d34SFangrui Song }
119*d21b3d34SFangrui Song printf("*xattr test could not access any attributes.\n");
120*d21b3d34SFangrui Song }
121*d21b3d34SFangrui Song
122*d21b3d34SFangrui Song // TODO: set some attributes before trying to retrieve them with *getxattr.
123*d21b3d34SFangrui Song // Currently the list is empty, so *getxattr is not tested.
main(int argc,char * argv[])124*d21b3d34SFangrui Song int main(int argc, char *argv[]) {
125*d21b3d34SFangrui Song assert(argc == 2);
126*d21b3d34SFangrui Song snprintf(g_path, sizeof(g_path), "%s/%s", argv[1], "xattr_test_root/a");
127*d21b3d34SFangrui Song
128*d21b3d34SFangrui Song g_fd = open(g_path, O_RDONLY);
129*d21b3d34SFangrui Song assert(g_fd);
130*d21b3d34SFangrui Song
131*d21b3d34SFangrui Song char *attr_list;
132*d21b3d34SFangrui Song size_t attr_list_size;
133*d21b3d34SFangrui Song attr_list_size = test_list(listxattr_wrapper, &attr_list);
134*d21b3d34SFangrui Song free(attr_list);
135*d21b3d34SFangrui Song attr_list_size = test_list(llistxattr_wrapper, &attr_list);
136*d21b3d34SFangrui Song free(attr_list);
137*d21b3d34SFangrui Song attr_list_size = test_list(flistxattr_wrapper, &attr_list);
138*d21b3d34SFangrui Song
139*d21b3d34SFangrui Song test_get(getxattr_wrapper, attr_list, attr_list_size);
140*d21b3d34SFangrui Song test_get(lgetxattr_wrapper, attr_list, attr_list_size);
141*d21b3d34SFangrui Song test_get(fgetxattr_wrapper, attr_list, attr_list_size);
142*d21b3d34SFangrui Song
143*d21b3d34SFangrui Song free(attr_list);
144*d21b3d34SFangrui Song return 0;
145*d21b3d34SFangrui Song }
146