#include <unistd.h> #include <fcntl.h> #include <stdarg.h> #include <sys/socket.h> #ifdef _MTK_ENG_ #include "../bionic/fdleak_debug_common.h" extern int __close(int); extern int __pipe(int*); extern int __pipe2(int *, int); extern int __socket(int, int, int); extern int __accept(int, struct sockaddr *, socklen_t *); extern int __dup(int); extern int __dup2(int, int); extern int __eventfd(unsigned int initval, int flags); FDLeak_Record_Backtrace fdleak_record_backtrace = NULL; FDLeak_Remove_Backtrace fdleak_remove_backtrace = NULL; int close(int fd) { if (fdleak_remove_backtrace){ fdleak_remove_backtrace(fd); } return __close(fd); } int pipe(int *pipefds) { int ret; ret = __pipe(pipefds); if (fdleak_record_backtrace && (ret == 0)){ fdleak_record_backtrace(pipefds[0]); fdleak_record_backtrace(pipefds[1]); } return ret; } #ifdef _GNU_SOURCE /* GLibc compatibility */ int pipe2(int *pipefds, int flag) { int ret; ret = __pipe2(pipefds, flag); if (fdleak_record_backtrace && (ret == 0)){ fdleak_record_backtrace(pipefds[0]); fdleak_record_backtrace(pipefds[1]); } return ret; }
#include <unistd.h> #include <fcntl.h> #include <stdarg.h> #include <sys/socket.h> #ifdef _MTK_ENG_ #include "../bionic/fdleak_debug_common.h" extern int __close(int); extern int __pipe(int*); extern int __pipe2(int *, int); extern int __socket(int, int, int); extern int __accept(int, struct sockaddr *, socklen_t *); extern int __dup(int); extern int __dup2(int, int); extern int __eventfd(unsigned int initval, int flags); FDLeak_Record_Backtrace fdleak_record_backtrace = NULL; FDLeak_Remove_Backtrace fdleak_remove_backtrace = NULL; int close(int fd) { if (fdleak_remove_backtrace){ fdleak_remove_backtrace(fd); } return __close(fd); } int pipe(int *pipefds) { int ret; ret = __pipe(pipefds); if (fdleak_record_backtrace && (ret == 0)){ fdleak_record_backtrace(pipefds[0]); fdleak_record_backtrace(pipefds[1]); } return ret; } #ifdef _GNU_SOURCE /* GLibc compatibility */ int pipe2(int *pipefds, int flag) { int ret; ret = __pipe2(pipefds, flag); if (fdleak_record_backtrace && (ret == 0)){ fdleak_record_backtrace(pipefds[0]); fdleak_record_backtrace(pipefds[1]); } return ret; } #endif int socket(int domain, int type, int protocol) { int fd; fd = __socket(domain, type, protocol); if (fdleak_record_backtrace) { fdleak_record_backtrace(fd); } return fd; } int accept(int serverfd, struct sockaddr *addr, socklen_t *addrlen) { int fd; fd = __accept(serverfd, addr, addrlen); if (fdleak_record_backtrace) { fdleak_record_backtrace(fd); } return fd; } int dup(int oldfd) { int newfd = 0; newfd = __dup(oldfd); if (fdleak_record_backtrace) { fdleak_record_backtrace(newfd); } return newfd; } int dup2(int oldfd, int targetfd) { int newfd = 0; //LCH need care targetfd, due to dup2 sys call will check targetfd open or not, if open will close it first. //mask here for fdleak_remove_backtrace overwriten //if (fdleak_remove_backtrace) { // fdleak_remove_backtrace(targetfd); //} newfd = __dup2(oldfd, targetfd); if (fdleak_record_backtrace) { fdleak_record_backtrace(newfd); } return newfd; } int eventfd(unsigned int initval, int flags) { int fd = __eventfd(initval, flags); if (fdleak_record_backtrace) { fdleak_record_backtrace(fd); } return fd; } #else //user load user original path through modify libc/Android.mk int close(int fd) { return __close(fd); } int pipe(int *pipefds) { return __pipe(pipefds); } #ifdef _GNU_SOURCE /* GLibc compatibility */ int pipe2(int *pipefds, int flag) { return __pipe2(pipefds, flag); }
/* Spawn a new process executing PATH with the attributes describes in *ATTRP. Before running the process perform the actions described in FILE-ACTIONS. */ static int __spawnix (pid_t * pid, const char *file, const posix_spawn_file_actions_t * file_actions, const posix_spawnattr_t * attrp, char *const argv[], char *const envp[], int xflags, int (*exec) (const char *, char *const *, char *const *)) { pid_t new_pid; struct posix_spawn_args args; int ec; if (__pipe2 (args.pipe, O_CLOEXEC)) return errno; /* To avoid imposing hard limits on posix_spawn{p} the total number of arguments is first calculated to allocate a mmap to hold all possible values. */ ptrdiff_t argc = 0; /* Linux allows at most max (0x7FFFFFFF, 1/4 stack size) arguments to be used in a execve call. We limit to INT_MAX minus one due the compatiblity code that may execute a shell script (maybe_script_execute) where it will construct another argument list with an additional argument. */ ptrdiff_t limit = INT_MAX - 1; while (argv[argc++] != NULL) if (argc == limit) { errno = E2BIG; return errno; } int prot = (PROT_READ | PROT_WRITE | ((GL (dl_stack_flags) & PF_X) ? PROT_EXEC : 0)); /* Add a slack area for child's stack. */ size_t argv_size = (argc * sizeof (void *)) + 512; size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize)); void *stack = __mmap (NULL, stack_size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); if (__glibc_unlikely (stack == MAP_FAILED)) { close_not_cancel (args.pipe[0]); close_not_cancel (args.pipe[1]); return errno; } /* Disable asynchronous cancellation. */ int cs = LIBC_CANCEL_ASYNC (); args.file = file; args.exec = exec; args.fa = file_actions; args.attr = attrp ? attrp : &(const posix_spawnattr_t) { 0 }; args.argv = argv; args.argc = argc; args.envp = envp; args.xflags = xflags; __sigprocmask (SIG_BLOCK, &SIGALL_SET, &args.oldmask); /* The clone flags used will create a new child that will run in the same memory space (CLONE_VM) and the execution of calling thread will be suspend until the child calls execve or _exit. These condition as signal below either by pipe write (_exit with SPAWN_ERROR) or a successful execve. Also since the calling thread execution will be suspend, there is not need for CLONE_SETTLS. Although parent and child share the same TLS namespace, there will be no concurrent access for TLS variables (errno for instance). */ new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size, CLONE_VM | CLONE_VFORK | SIGCHLD, &args); close_not_cancel (args.pipe[1]); if (new_pid > 0) { if (__read (args.pipe[0], &ec, sizeof ec) != sizeof ec) ec = 0; else __waitpid (new_pid, NULL, 0); } else ec = -new_pid; __munmap (stack, stack_size); close_not_cancel (args.pipe[0]); if (!ec && new_pid) *pid = new_pid; __sigprocmask (SIG_SETMASK, &args.oldmask, 0); LIBC_CANCEL_RESET (cs); return ec; } /* Spawn a new process executing PATH with the attributes describes in *ATTRP. Before running the process perform the actions described in FILE-ACTIONS. */ int __spawni (pid_t * pid, const char *file, const posix_spawn_file_actions_t * acts, const posix_spawnattr_t * attrp, char *const argv[], char *const envp[], int xflags) { return __spawnix (pid, file, acts, attrp, argv, envp, xflags, xflags & SPAWN_XFLAGS_USE_PATH ? __execvpe : __execve); }