Optimize process execution on Android
* exec/configure.ac (REENTRANT): Remove option for reentrancy. (PROGRAM_COUNTER, HAVE_SECCOMP): Define register providing the program counter and enable seccomp if its headers are available. * exec/exec.c (write_load_command): Avoid defining unused variable. (exec_0): Remove code specific to REENTRANT configurations. * exec/exec.h (struct exec_tracee) <exec_data, data_size>: New fields for loader instructions and their size. * exec/exec1.c (main): Call exec_init before forking. * exec/mipsel-user.h (ELF_NGREG): Delete definition. (struct mipsel_regs): Reduce number of gregs to 32, but introduce separate fields for special registers. * exec/trace.c (use_seccomp_p): New variable; defile to false if !HAVE_SECCOMP. (remove_tracee): Cease providing for non-reentrant configurations. Release executable data if present. (handle_clone_prepare): Likewise. Resume process with PTRACE_CONT if seccomp-based interception is enabled. (handle_clone, check_signal): Resume processes as above. (handle_exec): Divide into two functions, with only rewriting the system call and generating instructions for the loader remaining in the first, and copying such instructions into the loader's stack removed into a new function, `finish_exec'. (finish_exec): New function. (handle_readlinkat, handle_openat): Abolish non-REENTRANT configurations. (process_system_call): Divide exec system calls into two phases, disambiguated by the value of tracee->waiting_for_syscall. Typo fixes. Accommodate syscall-exit-stops where the signal was initially intercepted by `seccomp_system_call'. (interesting_syscalls): New array. (ARRAYELTS): New macro. (seccomp_system_call, establish_seccomp_filter): New function. (tracing_execve) [HAVE_SECCOMP]: Establish a seccomp filter if this is to be enabled. (after_fork): Provide PTRACE_O_TRACESECCOMP. Resume process with PTRACE_CONT if seccomp-based interception is enabled. (exec_waitpid): Resume process with PTRACE_CONT if seccomp-based interception is enabled. Dispatch stops identifying as PTRACE_EVENT_SECCOMP to `seccomp_system_call'. (exec_init): Establish whether it is possible to enable seccomp.
This commit is contained in:
parent
7c8d4e96ba
commit
ebf5bcb9f0
6 changed files with 666 additions and 219 deletions
|
@ -42,11 +42,6 @@ General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */])
|
||||
|
||||
AC_ARG_WITH([reentrancy],
|
||||
[AS_HELP_STRING([--with-reentrancy],
|
||||
[Generate library which can be used within a signal handler.])],
|
||||
[AC_DEFINE([REENTRANT], [1])])
|
||||
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
|
@ -74,9 +69,9 @@ AC_CHECK_FUNC([process_vm_readv],
|
|||
]])])])
|
||||
AC_CHECK_HEADERS([sys/param.h sys/uio.h])
|
||||
AC_CHECK_MEMBERS([siginfo_t.si_syscall], [], [],
|
||||
[[
|
||||
[[
|
||||
#include <signal.h>
|
||||
]])
|
||||
]])
|
||||
|
||||
AH_BOTTOM([
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
|
@ -120,6 +115,7 @@ AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls
|
|||
AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.])
|
||||
AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.])
|
||||
AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.])
|
||||
AH_TEMPLATE([PROGRAM_COUNTER], [Define to register holding the program counter.])
|
||||
AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.])
|
||||
AH_TEMPLATE([USER_WORD], [Define to word type used by tracees.])
|
||||
AH_TEMPLATE([USER_SWORD], [Define to signed word type used by tracees.])
|
||||
|
@ -134,7 +130,8 @@ AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.
|
|||
AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.])
|
||||
AH_TEMPLATE([OPEN_SYSCALL], [Define to number of the `open' system call.])
|
||||
AH_TEMPLATE([OPENAT_SYSCALL], [Define to number of the `openat' system call.])
|
||||
AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.])
|
||||
AH_TEMPLATE([HAVE_SECCOMP], [Define to 1 if secure computing filters are available
|
||||
to accelerate interception of system calls.])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
|
@ -250,6 +247,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [rdx])
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [r10])
|
||||
AC_DEFINE([STACK_POINTER], [rsp])
|
||||
AC_DEFINE([PROGRAM_COUNTER], [rip])
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -283,6 +281,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [edx])
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [esi])
|
||||
AC_DEFINE([STACK_POINTER], [esp])
|
||||
AC_DEFINE([PROGRAM_COUNTER], [eip])
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -314,6 +313,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [[regs[2]]])
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [[regs[3]]])
|
||||
AC_DEFINE([STACK_POINTER], [sp])
|
||||
AC_DEFINE([PROGRAM_COUNTER], [pc])
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -346,6 +346,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
|
||||
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
||||
AC_DEFINE([PROGRAM_COUNTER], [[uregs[15]]])
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -371,6 +372,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
|
||||
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
|
||||
AC_DEFINE([STACK_POINTER], [[uregs[15]]])
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -402,6 +404,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
|
||||
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
||||
AC_DEFINE([PROGRAM_COUNTER], [[cp0_epc]]) # pc
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -432,6 +435,7 @@ AS_CASE([$host], [x86_64-*linux*],
|
|||
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
|
||||
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
|
||||
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
|
||||
AC_DEFINE([PROGRAM_COUNTER], [[cp0_epc]]) # pc
|
||||
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
|
||||
AC_DEFINE([USER_WORD], [uintptr_t])
|
||||
AC_DEFINE([USER_SWORD], [intptr_t])
|
||||
|
@ -480,6 +484,12 @@ AC_ARG_VAR([LOADERFLAGS], [Flags used to link the loader.])
|
|||
AC_ARG_VAR([ARFLAGS], [Flags for the archiver.])
|
||||
AC_ARG_VAR([ASFLAGS], [Flags for the assembler.])
|
||||
|
||||
# Search for seccomp headers and declarations.
|
||||
AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h],
|
||||
[AC_CHECK_DECLS([SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_RET_TRACE],
|
||||
[AC_DEFINE([HAVE_SECCOMP], [1])], [],
|
||||
[[#include <linux/seccomp.h>]])])
|
||||
|
||||
# Make the assembler optimize for code size. Don't do this on MIPS,
|
||||
# as the assembler code manages branch delays manually.
|
||||
|
||||
|
|
17
exec/exec.c
17
exec/exec.c
|
@ -292,7 +292,9 @@ write_load_command (program_header *header, bool use_alternate,
|
|||
struct exec_map_command command1;
|
||||
USER_WORD start, end;
|
||||
bool need_command1;
|
||||
#ifndef PAGE_MASK
|
||||
static long pagesize;
|
||||
#endif /* !PAGE_MASK */
|
||||
|
||||
/* First, write the commands necessary to map the specified segment
|
||||
itself.
|
||||
|
@ -306,14 +308,14 @@ write_load_command (program_header *header, bool use_alternate,
|
|||
#ifdef HAVE_GETPAGESIZE
|
||||
if (!pagesize)
|
||||
pagesize = getpagesize ();
|
||||
#else /* HAVE_GETPAGESIZE */
|
||||
#else /* !HAVE_GETPAGESIZE */
|
||||
if (!pagesize)
|
||||
pagesize = sysconf (_SC_PAGESIZE);
|
||||
#endif /* HAVE_GETPAGESIZE */
|
||||
#endif /* !HAVE_GETPAGESIZE */
|
||||
|
||||
#define PAGE_MASK (~(pagesize - 1))
|
||||
#define PAGE_SIZE (pagesize)
|
||||
#endif /* PAGE_MASK */
|
||||
#endif /* !PAGE_MASK */
|
||||
|
||||
start = header->p_vaddr & PAGE_MASK;
|
||||
end = ((header->p_vaddr + header->p_filesz
|
||||
|
@ -895,10 +897,6 @@ format_pid (char *in, unsigned int pid)
|
|||
with #!; in that case, find the program to open and use that
|
||||
instead.
|
||||
|
||||
If REENTRANT is not defined, NAME is actually a buffer of size
|
||||
PATH_MAX + 80. In that case, copy over the file name actually
|
||||
opened.
|
||||
|
||||
Next, read the executable header, and add the necessary memory
|
||||
mappings for each file. Finally, return the action data and its
|
||||
size in *SIZE.
|
||||
|
@ -976,11 +974,6 @@ exec_0 (char *name, struct exec_tracee *tracee,
|
|||
rewrite = buffer1 + link_size;
|
||||
remaining = buffer1 + sizeof buffer1 - rewrite - 1;
|
||||
memcpy (rewrite, name, strnlen (name, remaining));
|
||||
|
||||
/* Replace name with buffer1. */
|
||||
#ifndef REENTRANT
|
||||
strcpy (name, buffer1);
|
||||
#endif /* REENTRANT */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
exec/exec.h
15
exec/exec.h
|
@ -152,6 +152,16 @@ struct exec_tracee
|
|||
completion. */
|
||||
USER_WORD sp;
|
||||
|
||||
/* Name of the executable being run. */
|
||||
char *exec_file;
|
||||
|
||||
/* Pointer to a storage area holding instructions for loading an
|
||||
executable if an `exec' system call is outstanding, or NULL. */
|
||||
char *exec_data;
|
||||
|
||||
/* Number of bytes in exec_data. */
|
||||
size_t data_size;
|
||||
|
||||
/* The thread ID of this process. */
|
||||
pid_t pid;
|
||||
|
||||
|
@ -162,11 +172,6 @@ struct exec_tracee
|
|||
/* Whether or not the tracee has been created but is not yet
|
||||
processed by `handle_clone'. */
|
||||
bool new_child : 1;
|
||||
|
||||
#ifndef REENTRANT
|
||||
/* Name of the executable being run. */
|
||||
char *exec_file;
|
||||
#endif /* !REENTRANT */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ main (int argc, char **argv)
|
|||
extern char **environ;
|
||||
int wstatus;
|
||||
|
||||
/* Provide the file name of the loader. */
|
||||
exec_init (argv[1]);
|
||||
|
||||
pid1 = getpid ();
|
||||
pid = fork ();
|
||||
|
||||
|
@ -58,9 +61,6 @@ main (int argc, char **argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Provide the file name of the loader. */
|
||||
exec_init (argv[1]);
|
||||
|
||||
if (after_fork (pid))
|
||||
exit (127);
|
||||
|
||||
|
|
|
@ -24,10 +24,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
|
||||
#include <sys/user.h>
|
||||
|
||||
#ifndef ELF_NGREG
|
||||
#define ELF_NGREG 45
|
||||
#endif /* ELF_NGREG */
|
||||
|
||||
|
||||
|
||||
/* This file defines a structure containing user mode general purpose
|
||||
|
@ -36,7 +32,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
struct mipsel_regs
|
||||
{
|
||||
/* General purpose registers. */
|
||||
uint64_t gregs[ELF_NGREG];
|
||||
uint64_t gregs[32];
|
||||
|
||||
/* Saved special registers. */
|
||||
uint64_t lo;
|
||||
uint64_t hi;
|
||||
uint64_t cp0_epc;
|
||||
uint64_t cp0_badvaddr;
|
||||
uint64_t cp0_status;
|
||||
uint64_t cp0_cause;
|
||||
};
|
||||
|
||||
#endif /* _MIPSEL_USER_H_ */
|
||||
|
|
807
exec/trace.c
807
exec/trace.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue