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