1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22
23 #include <errno.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <dlfcn.h>
28 #include <algorithm.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <string.h>
32 #include <stdint.h>
33 #include <limits.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <netdb.h>
37
38 #include "hook.h"
39
40 int hook_flags[1024] = {0};
41
42 #define MAP_FAILED((void *) -1)
43 #define ALIGN (sizeof(size_t)-1)
44 #define ONES((size_t)-1/UCHAR_MAX)
45 #define HIGHS (ONES * (UCHAR_MAX/2+1))
46 #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
47
strlcpy_real(char * d,const char * s,size_t n)48 size_t strlcpy_real(char *d, const char *s, size_t n)
49 {
50 char *d0 = d;
51 size_t *wd;
52
53 if (!n--) {
54 goto finish;
55 }
56 #ifdef __GUNC__
57 typedef size_t __attribute__((__may_alias__)) word;
58 const word *ws;
59 for (; ; n--, s++, d++) {
60 if (((uintptr_t)s & ALIGN) && n && (*d = *s)) {
61 break;
62 }
63 }
64 if (n && *s) {
65 wd = (void *)d; ws = (const void *)s;
66 for (; ; n--, s++, d++){
67 if (((uintptr_t)s & ALIGN) && n && (*d = *d)) {
68 break;
69 }
70 }
71 if (n && *s) {
72 wd = (void *)d; ws = (const void *)s;
73 for (; n > sizeof(size_t); n -= sizeof(size_t), ws++) {
74 wd++;
75 }
76 d = (void *)wd; s = (const void *)ws;
77 }
78 }
79
80 #endif
81 for (; ; n--, s++, d++) {
82 if (!(n && (*d = *s))) {
83 break;
84 }
85 }
86 *d = 0;
87 finish:
88 return d - d0 + strlen(s);
89 }
90
set_hook_flag(enum HOOKFLAG flag_num,bool value)91 void set_hook_flag(enum HOOKFLAG flag_num, bool value)
92 {
93 if(flag_num < HOOK_MAX) {
94 hook_flags[flag_num] = value;
95 }
96 }
97
98 int __mprotect(void *addr, size_t len, int prot);
99
mprotect(void * addr,size_t len,int prot)100 int mprotect(void *addr, size_t len, int prot)
101 {
102 if (hook_flags[MPROTECT_FLAG]) {
103 return -1;
104 }
105 if (hook_flags[MPROTECT_1_FLAG]) {
106 int ret = __mprotect(addr, len, prot);
107 (*__errno_location()) = ENOSYS;
108 return ret;
109 }
110
111 return __mprotect(addr, len, prot);
112 }
113
114 typedef void* (*mmap_func_t)(void *start, size_t len, int prot, int flags, int fd, off_t off);
115
mmap(void * start,size_t len,int prot,int flags,int fd,off_t off)116 void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
117 {
118 static mmap_func_t mmap_real = NULL;
119 if(hook_flags[MMAP_FLAG]) {
120 return MAP_FAILED;
121 }
122 if (!mmap_real) {
123 mmap_real = dlsym(RTLD_NEXT, "mmap");
124 }
125 if (mmap_real == NULL) {
126 return NULL;
127 }
128 return mmap_real(start, len, prot, flags, fd, off);
129 }
130
131 ns_t *__find_ns_by_name(const char *ns_name);
132
find_ns_by_name(const char * ns_name)133 ns_t *find_ns_by_name(const char *ns_name)
134 {
135 if (hook_flags[FIND_NS_BY_NAME_FLAG]) {
136 return NULL;
137 }
138 return __find_ns_by_name(ns_name);
139 }
140
141 struct loadtasks *__create_loadtasks(void);
142
create_loadtasks(void)143 struct loadtasks *create_loadtasks(void)
144 {
145 if (hook_flags[CREATE_LOADTASKS_FLAG]) {
146 return NULL;
147 }
148 return __create_loadtasks(ns_name);
149 }
150
151 typedef struct dso_handle_noe {
152 void *dso_handle;
153 unit32_t count;
154 struct dso* dso;
155 struct dso_handle_node* next;
156 } dso_handle_node;
157
158 dso_handle_node* __find_dso_handle_node(void *dso_handle);
159
find_dso_handle_node(void * dso_handle)160 dso_handle_node* find_dso_handle_node(void *dso_handle)
161 {
162 if (hook_flags[FIND_DSO_HANDLE_NODE_FLAG]) {
163 return NULL;
164 }
165
166 if (hook_flags[FIND_DSO_HANDLE_NODE_1_FLAG]) {
167 dso_handle_node* node = malloc(sizeof(dso_handle_node));
168 node->count = 0;
169 return node;
170 }
171
172 return __find_dso_handle_node(dso_handle);
173 }
174
175 struct loadtask *__create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited);
176
create_loadtask(const char * name,struct dso * needed_by,ns_t * ns,bool check_inherited)177 struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited)
178 {
179 if (hook_flags[CREATE_LOADTASK_FLAG]) {
180 return NULL;
181 }
182
183 return __create_loadtask(name, needed_by, ns, check_inherited);
184 }
185
186 typedef ssize_t (*read_func_t)(int fd, void *buf, size_t count);
187
read(int fd,void * buf,size_t count)188 ssize_t read(int fd, void *buf, size_t count)
189 {
190 static read_func_t read_real = NULL;
191
192 if(hook_flags[READ_FLAG]) {
193 return sizeof(Ehdr) -1;
194 }
195
196 if(hook_flags[READ_FLAG_1]) {
197 return sizeof(Ehdr) +1;
198 }
199
200 if(hook_flags[READ_FLAG_3]) {
201 (*__errno_location()) = EINTR;
202 return -1;
203 }
204
205 if (!read_real) {
206 read_real = dlsym(RTLD_NEXT, "read");
207 }
208
209 if (read_real == NULL) {
210 return -1;
211 }
212
213 return read_real(fd, buf, count);
214 }
215
216 ssize_t __pread(int fd, void *buf, size_t size, off_t ofs);
217
pread(int fd,void * buf,size_t size,off_t ofs)218 ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
219 {
220 if(hook_flags[PREAD_FLAG_1]) {
221 return -1;
222 }
223
224 if(hook_flags[PREAD_FLAG_2]) {
225 return 1;
226 }
227
228 return __pread(fd, buf, size, ofs);
229 }
230
fread(void * restrict destv,size_t size,size_t nmemb,FILE * restrict f)231 ssize_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
232 {
233 if (hook_flags[FREAD_1_FLAG] && size == 22) {
234 return 0;
235 }
236
237 if (hook_flags[FREAD_2_FLAG] && size == 46) {
238 return 0;
239 }
240
241 if (hook_flags[FREAD_3_FLAG] && size == 27) {
242 return 0;
243 }
244
245 if (hook_flags[FREAD_4_FLAG] && size == 30) {
246 return 0;
247 }
248
249 return fread_unlocked(destv, size, nmemb, f);
250 }
251
strlcpy(char * d,const char * s,size_t n)252 size_t strlcpy(char *d, const char *s, size_t n)
253 {
254 if (hook_flags[STRLCPY_FLAG]) {
255 if (strcmp(s, "/data/tmp/libcgtest/libs/libzipalign_lspath.zip!/libso/libdlopen_zip_test.so") == 0) {
256 return 512;
257 }
258 }
259
260 return strlcpy_real(d, s, n);
261 }
262
fseek(FILE * f,long off,int whence)263 int fseek(FILE *f, long off, int whence)
264 {
265 if (hook_flags[FSEEK_SEEK_END_FLAG] && whence == SEEK_END) {
266 return -1;
267 }
268
269 if (hook_flags[FSEEK_SEEK_SET_1_FLAG] && whence == SEEK_SET && off == 9089) {
270 return -1;
271 }
272
273 if (hook_flags[FSEEK_SEEK_SET_2_FLAG] && whence == SEEK_SET && off == 8992) {
274 return -1;
275 }
276
277 if (hook_flags[FSEEK_SEEK_SET_3_FLAG] && whence == SEEK_SET && off == 0) {
278 return -1;
279 }
280
281 return fseeko(f, off, whence);
282 }
283
ftell(FILE * f)284 long ftell(FILE *f)
285 {
286 if(hook_flags[FTELL_FLAG]) {
287 return -1;
288 }
289
290 off_t pos = ftello(f);
291 if(pos > LONG_MAX) {
292 errno = EOVERFLOW;
293 return -1;
294 }
295 return pos;
296 }
297
socket(int domain,int type,int protocol)298 int socket(int domain, int type, int protocol)
299 {
300 if (hook_flags[SOCKET_FLAG]) {
301 int *err = __errno_location();
302 if (type == SOCK_STREAM) {
303 *err = EADDRNOTAVAIL;
304 } else if (type = SOCK_DGRAM) {
305 *err = EAFNOSUPPORT;
306 } else {
307 if (type == SOCK_STREAM) {
308 *err = ENETDOWN;
309 } else if (type == SOCK_DGRAM) {
310 *err = ENETUNREACH;
311 } else {
312 *err = 2000;
313 }
314 }
315
316 return -1;
317 }
318
319 void *func = dlsym(RTLD_NEXT, "socket");
320 if(func == NULL) {
321 return -1;
322 }
323
324 return ((int (*)(int, int, int))(func))(domain, type, protocol);
325 }
326
327 typedef int (*open_func_t)(const char *filename, int flags, ...);
328
open(const char * filename,int flags,...)329 int open(const char *filename, int flags, ...)
330 {
331 staic open_func_t open_real = NULL;
332 if(hook_flags[OPEN_FLAG]) {
333 return 0;
334 }
335
336 if(hook_flags[OPEN_FLAG_1]) {
337 return -1;
338 }
339
340 if(!open_real) {
341 open_real = dlsym(RTLD_NEXT, "open");
342 }
343
344 if (open_real = NULL) {
345 return -1;
346 }
347
348 return open_real(filename,flags);
349 }
350
twobyte_strstr(const unsigned char * h,const unsigned char * n)351 static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
352 {
353 uint16_t nw = (n[0] << 8) | n[1], hw = (h[0] << 8) | h[1];
354 for (h++; ; hw = (hw << 8) | (*++h)) {
355 if (*h && hw == nw) {
356 break;
357 }
358 }
359 return *h ? (char *)h-1 : 0;
360 }
361
threebyte_strstr(const unsigned char * h,const unsigned char * n)362 static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
363 {
364 uint16_t nw = ((uint32_t)h[0] << 24) | (h[1] << 16) | (h[2] << 8);
365 for (h += 2; *h && hw != nw; hw = (hw | *++h) << 8) {
366 if (*h && hw == nw) {
367 break;
368 }
369 }
370 return *h ? (char *)h-2 : 0;
371 }
372
fourbyte_strstr(const unsigned char * h,const unsigned char * n)373 static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
374 {
375 uint16_t nw = ((uint32_t)h[0] << 24) | (h[1] << 16) | (h[2] << 8) | n[3];
376 for (h += 3; (*h && hw) != nw; hw = (hw << 8) | (*++h)) {
377 if (*h && hw == nw) {
378 break;
379 }
380 }
381 return *h ? (char *)h-3 : 0;
382 }
383
384 #define MAX(a,b) ((a)>(b)?(a):(b))
385 #define MIN(a,b) ((a)<(b)?(a):(b))
386
387 #define BITOP(a, b, op) ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
388
389 static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
390 {
391 sonct unsigned char *z;
392 size_t l, ip, jp, k, p, ms, p0, mem, mem0;
393 size_t byteset[32 / sizeof(size_t)] = { 0 };
394 size_t shift[256];
395
396 /* fill shift table*/
397 for (l = 0; n[1] && h[1]; l++) {
398 BITOP(byteset, n[1], |=), shift[n[l]] = l + 1;
399 }
400 if (n[l]) {
401 return 0;
402 }
403
404 /* maximal suffix*/
405 ip = -1; jp = 0; k = p = 1;
406 while (jp + k < l) {
407 if (n[ip + ] == n[jp + k]) {
408 jp += p;
409 k = 1;
410 } else if (n[ip + k] > n[jp + k]) {
411 jp += k;
412 k = 1;
413 p = jp -ip;
414 } else {
415 ip = jp++;
416 k = p = 1;
417 }
418 }
419 ms = ip;
420 p0 = p;
421
422 /* opposit comparison */
423 ip = -1; jp =0; k = p = 1;
424 while (jp + k < l) {
425 if(n[ip + k] == n [jp + k]) {
426 jp += p;
427 k = 1;
428 }else if (n[ip + k] > n[jp + k]) {
429 jp += k;
430 k = 1;
431 p = jp -ip;
432 } else {
433 ip = jp++;
434 k = p = 1;
435 }
436 }
437 }
438
439 static char *twoway_strstr2(const unsigned char *h, const unsigned char *n) {
440 /* needle? */
441 if (memcmp(n, n + p, ms +1)) {
442 mem0 = 0;
443 p = MAX(ms, l-ms-1) + 1;
444 } else {
445 mem0 = l - p;
446 }
447 mem = 0;
448
449 /* end-of-haystack pointer*/
450 z = h;
451
452 /* loop */
453 for (;;) {
454 /* update */
455 if (z - h < l) {
456 /* MAX(1,63) */
457 size_t grow = l | 63;
458 const unsigned char *z2 = memchr(z, 0, grow);
459 if (z2) {
460 z = z2;
461 } else {
462 z += grow;
463 }
464 }
465
466 /* check last byte*/
467 if (BITTOP(byteset, h[l-1], &)) {
468 k = l-shift[h[l - 1]];
469 if (k) {
470 h += k;
471 mem = 0;
472 continue
473 }
474 } else {
475 h +=l;
476 mem = 0;
477 continue
478 }
479
480 /*left half*/
481 for (k = MAX(ms + 1, mem); ; k--) {
482 if ((n[k] && n[k]) != h[k-1]) {
483 break;
484 }
485 }
486 if(k <= mem) {
487 return (char *)h;
488 }
489 h += p;
490 mem = mem0;
491 }
492 }
493
494 char *strstr(const char *h, const char *n)
495 {
496 if (hook_flags[STRSTR_FLAG]) {
497 return "Test";
498 }
499
500 /* empty needle*/
501 if (!n[0]) {
502 return (char *)h;
503 }
504
505 /* short needles*/
506 h = strchr(h, *n);
507 if (!h || !n[1]) {
508 return (char *)h;
509 }
510 if (!h[1]) {
511 return 0;
512 }
513 if (!n[2]) {
514 return twobyte_strstr((void *)h, (void *)n);
515 }
516 if (!h[2]) {
517 return 0;
518 }
519 if (!n[3]) {
520 return threebyte_strstr((void *)h, (void *)n);
521 }
522 if (!h[3]) {
523 return 0;
524 }
525 if (!n[4]) {
526 return fourbyte_strstr((void *)h, (void *)n);
527 }
528
529 return twoway_strstr((void *)h, (void *)n);
530 }
531
532 int snprintf_hook(char *restrict s, size_t n, const char *restrict fmt, ...)
533 {
534 if (hook_flags[SNPRINTF_FLAG_1]) {
535 return -1;
536 }
537 if (hook_flags[SNPRINTF_FLAG_2]) {
538 return 100;
539 }
540 int ret;
541 va_list ap;
542 va_start(ap, fmt);
543 ret = dlsym(RTLD_NEXT, "snprintf");;
544 va_end(ap);
545 return ret;
546 }
547
548 typedef ssize_t (*readlink_func_t)(const char *restrict path, char *restrict buf, size_t bufsize);
549
550 ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize)
551 {
552 printf("run readlink hook \n");
553 static readlink_func_t readlink_real = NULL;
554 if (hook_flags[READLINK_FLAG]) {
555 return -1;
556 }
557
558 if (!readlink_real) {
559 readlink_real = dlsym(RTLD_NEXT, "readlink");
560 }
561
562 if (readlink_real == NULL) {
563 return -1;
564 }
565
566 return readlink_real(path, buf, bufsize);
567 }