xref: /llvm-project/compiler-rt/test/msan/Linux/xattr.cpp (revision d21b3d346af2f6189638d853182e389555e7ccb9)
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