1 #include <dirent.h>
2 #include <dlfcn.h>
3 #include <fcntl.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <string>
7 #include <unordered_map>
8 
9 #define LOG_TAG "GCH_libc_wrappers"
10 #include <log/log.h>
11 
12 //#define MONITOR_FILE_OP
13 
14 #ifdef __ANDROID_APEX__
15 
16 #ifdef MONITOR_FILE_OP
17 
18 using mkfifo_function_type = int (*)(const char*, mode_t);
19 using access_function_type = int (*)(const char*, int);
20 using mkdir_function_type = int (*)(const char*, mode_t);
21 using rmdir_function_type = int (*)(const char*);
22 using chdir_function_type = int (*)(const char*);
23 using link_function_type = int (*)(const char*, const char*);
24 using unlink_function_type = int (*)(const char*);
25 using rename_function_type = int (*)(const char*, const char*);
26 using stat_function_type = int (*)(const char*, struct stat*);
27 using chmod_function_type = int (*)(const char*, mode_t);
28 using chown_function_type = int (*)(const char*, uid_t, gid_t);
29 using utime_function_type = int (*)(const char*, struct utimbuf*);
30 using opendir_function_type = DIR* (*)(const char*);
31 using execl_function_type = int (*)(const char*, const char*, ...);
32 using execle_function_type = int (*)(const char*, const char*, ...);
33 using execlp_function_type = int (*)(const char*, const char*, ...);
34 using execv_function_type = int (*)(const char*, char* const[]);
35 using execvp_function_type = int (*)(const char*, char* const[]);
36 using openat_function_type = int (*)(int, const char*, int, ...);
37 
mkfifo(const char * pathname,mode_t mode)38 extern "C" int mkfifo(const char* pathname, mode_t mode) {
39   static auto real_function =
40       reinterpret_cast<mkfifo_function_type>(dlsym(RTLD_NEXT, "mkfifo"));
41   int ret = real_function(pathname, mode);
42   ALOGI("mkfifo (%s,%d) == %d", pathname, mode, ret);
43   return ret;
44 }
access(const char * pathname,int mode)45 extern "C" int access(const char* pathname, int mode) {
46   static auto real_function =
47       reinterpret_cast<access_function_type>(dlsym(RTLD_NEXT, "access"));
48   int ret = real_function(pathname, mode);
49   ALOGI("access (%s,%d) == %d", pathname, mode, ret);
50   return ret;
51 }
mkdir(const char * pathname,mode_t mode)52 extern "C" int mkdir(const char* pathname, mode_t mode) {
53   static auto real_function =
54       reinterpret_cast<mkdir_function_type>(dlsym(RTLD_NEXT, "mkdir"));
55   int ret = real_function(pathname, mode);
56   ALOGI("mkdir (%s,%d) == %d", pathname, mode, ret);
57   return ret;
58 }
rmdir(const char * pathname)59 extern "C" int rmdir(const char* pathname) {
60   static auto real_function =
61       reinterpret_cast<rmdir_function_type>(dlsym(RTLD_NEXT, "rmdir"));
62   int ret = real_function(pathname);
63   ALOGI("rmdir (%s) == %d", pathname, ret);
64   return ret;
65 }
chdir(const char * path)66 extern "C" int chdir(const char* path) {
67   static auto real_function =
68       reinterpret_cast<chdir_function_type>(dlsym(RTLD_NEXT, "chdir"));
69   int ret = real_function(path);
70   ALOGI("chdir (%s) == %d", path, ret);
71   return ret;
72 }
link(const char * oldpath,const char * newpath)73 extern "C" int link(const char* oldpath, const char* newpath) {
74   static auto real_function =
75       reinterpret_cast<link_function_type>(dlsym(RTLD_NEXT, "link"));
76   int ret = real_function(oldpath, newpath);
77   ALOGI("link (%s,%s) == %d", oldpath, newpath, ret);
78   return ret;
79 }
unlink(const char * pathname)80 extern "C" int unlink(const char* pathname) {
81   static auto real_function =
82       reinterpret_cast<unlink_function_type>(dlsym(RTLD_NEXT, "unlink"));
83   int ret = real_function(pathname);
84   ALOGI("unlink (%s) == %d", pathname, ret);
85   return ret;
86 }
rename(const char * oldpath,const char * newpath)87 extern "C" int rename(const char* oldpath, const char* newpath) {
88   static auto real_function =
89       reinterpret_cast<rename_function_type>(dlsym(RTLD_NEXT, "rename"));
90   int ret = real_function(oldpath, newpath);
91   ALOGI("rename (%s,%s) == %d", oldpath, newpath, ret);
92   return ret;
93 }
stat(const char * file_name,struct stat * buf)94 extern "C" int stat(const char* file_name, struct stat* buf) {
95   static auto real_function =
96       reinterpret_cast<stat_function_type>(dlsym(RTLD_NEXT, "stat"));
97   int ret = real_function(file_name, buf);
98   ALOGI("stat (%s, %p) == %d", file_name, buf, ret);
99   return ret;
100 }
chmod(const char * path,mode_t mode)101 extern "C" int chmod(const char* path, mode_t mode) {
102   static auto real_function =
103       reinterpret_cast<chmod_function_type>(dlsym(RTLD_NEXT, "chmod"));
104   int ret = real_function(path, mode);
105   ALOGI("chmod (%s) == %d", path, ret);
106   return ret;
107 }
chown(const char * path,uid_t owner,gid_t group)108 extern "C" int chown(const char* path, uid_t owner, gid_t group) {
109   static auto real_function =
110       reinterpret_cast<chown_function_type>(dlsym(RTLD_NEXT, "chown"));
111   int ret = real_function(path, owner, group);
112   ALOGI("chown (%s,%d,%d) == %d", path, owner, group, ret);
113   return ret;
114 }
utime(const char * filename,struct utimbuf * buf)115 extern "C" int utime(const char* filename, struct utimbuf* buf) {
116   static auto real_function =
117       reinterpret_cast<utime_function_type>(dlsym(RTLD_NEXT, "utime"));
118   int ret = real_function(filename, buf);
119   ALOGI("utime (%s, %p) == %d", filename, buf, ret);
120   return ret;
121 }
opendir(const char * name)122 extern "C" DIR* opendir(const char* name) {
123   static auto real_function =
124       reinterpret_cast<opendir_function_type>(dlsym(RTLD_NEXT, "opendir"));
125   DIR* ret = real_function(name);
126   ALOGI("opendir (%s) == %p", name, ret);
127   return ret;
128 }
execl(const char * path,const char * arg,...)129 extern "C" int execl(const char* path, const char* arg, ...) {
130   static auto real_function =
131       reinterpret_cast<execl_function_type>(dlsym(RTLD_NEXT, "execl"));
132   int ret = real_function(path, arg);
133   ALOGI("execl (%s, %s) == %d", path, arg, ret);
134   return ret;
135 }
execle(const char * path,const char * arg,...)136 extern "C" int execle(const char* path, const char* arg, ...) {
137   static auto real_function =
138       reinterpret_cast<execle_function_type>(dlsym(RTLD_NEXT, "execle"));
139   int ret = real_function(path, arg);
140   ALOGI("execle (%s, %s) == %d", path, arg, ret);
141   return ret;
142 }
execlp(const char * file,const char * arg,...)143 extern "C" int execlp(const char* file, const char* arg, ...) {
144   static auto real_function =
145       reinterpret_cast<execlp_function_type>(dlsym(RTLD_NEXT, "execlp"));
146   int ret = real_function(file, arg);
147   ALOGI("execlp %s, %s) == %d", file, arg, ret);
148   return ret;
149 }
execv(const char * path,char * const argv[])150 extern "C" int execv(const char* path, char* const argv[]) {
151   static auto real_function =
152       reinterpret_cast<execv_function_type>(dlsym(RTLD_NEXT, "execv"));
153   int ret = real_function(path, argv);
154   ALOGI("execv (%s, %s, ...) == %d", path, argv[0], ret);
155   return ret;
156 }
execvp(const char * file,char * const argv[])157 extern "C" int execvp(const char* file, char* const argv[]) {
158   static auto real_function =
159       reinterpret_cast<execvp_function_type>(dlsym(RTLD_NEXT, "execvp"));
160   int ret = real_function(file, argv);
161   ALOGI("execvp (%s, %s,...) == %d", file, argv[0], ret);
162   return ret;
163 }
164 
openat(int dirfd,const char * pathname,int flags,...)165 extern "C" int openat(int dirfd, const char* pathname, int flags, ...) {
166   static auto real_function =
167       reinterpret_cast<openat_function_type>(dlsym(RTLD_NEXT, "openat"));
168   int ret = real_function(dirfd, pathname, flags);
169   ALOGI("openat(%d, %s, 0x%x) == %d", dirfd, pathname, flags, ret);
170   return ret;
171 }
172 #endif
173 
174 using dlopen_function_type = void* (*)(const char*, int);
175 
176 // This is a temporary workaround for prebuilts calling dlopen with absolute
177 // paths.
dlopen(const char * filename,int flags)178 extern "C" void* dlopen(const char* filename, int flags) {
179   static auto real_dlopen_function =
180       reinterpret_cast<dlopen_function_type>(dlsym(RTLD_NEXT, "dlopen"));
181   if (!real_dlopen_function) {
182     ALOGE("Could not RTLD_NEXT dlopen, something very wrong.");
183     std::abort();
184   }
185   void* ret = real_dlopen_function(filename, flags);
186   if (!ret) {
187     ALOGI("dlopen(%s) failed, seeing if we can fix it", filename);
188     std::string original_filename(filename);
189 
190     if (original_filename.find("/vendor/") == 0) {
191       std::string new_filename = "/apex/com.google.pixel.camera.hal/" +
192                                  original_filename.substr(strlen("/vendor/"));
193       ALOGI("Trying %s instead of %s\n", new_filename.c_str(), filename);
194       ret = real_dlopen_function(new_filename.c_str(), flags);
195       if (ret) {
196         ALOGE(
197             "ERROR: Update your code to not use absolute paths. dlopen(%s) "
198             "failed but dlopen(%s) succeeded instead.",
199             filename, new_filename.c_str());
200       }
201     }
202   }
203   return ret;
204 }
205 #endif
206