mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-26 07:33:47 +00:00
Fix cwd relative process execution on Android
* exec/exec.c (format_pid): New function. (exec_0): Make cwd relative file names relative to /proc/pid/cwd. * exec/trace.c (handle_exec): Handle EINTR. (process_system_call): Report failure without clobbering x0.
This commit is contained in:
parent
da6f0d9c6f
commit
b9de6e35b7
53
exec/exec.c
53
exec/exec.c
@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
@ -808,6 +809,35 @@ insert_args (struct exec_tracee *tracee, USER_REGS_STRUCT *regs,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Format PID, an unsigned process identifier, in base 10. Place the
|
||||||
|
result in *IN, and return a pointer to the byte after the
|
||||||
|
result. REM should be NULL. */
|
||||||
|
|
||||||
|
static char *
|
||||||
|
format_pid (char *in, unsigned int pid)
|
||||||
|
{
|
||||||
|
unsigned int digits[32], *fill;
|
||||||
|
|
||||||
|
fill = digits;
|
||||||
|
|
||||||
|
for (; pid != 0; pid = pid / 10)
|
||||||
|
*fill++ = pid % 10;
|
||||||
|
|
||||||
|
/* Insert 0 if the number would otherwise be empty. */
|
||||||
|
|
||||||
|
if (fill == digits)
|
||||||
|
*fill++ = 0;
|
||||||
|
|
||||||
|
while (fill != digits)
|
||||||
|
{
|
||||||
|
--fill;
|
||||||
|
*in++ = '0' + *fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
*in = '\0';
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return a sequence of actions required to load the executable under
|
/* Return a sequence of actions required to load the executable under
|
||||||
the file NAME for the given TRACEE. First, see if the file starts
|
the file NAME for the given TRACEE. First, see if the file starts
|
||||||
with #!; in that case, find the program to open and use that
|
with #!; in that case, find the program to open and use that
|
||||||
@ -836,6 +866,29 @@ exec_0 (const char *name, struct exec_tracee *tracee,
|
|||||||
#if defined __mips__ && !defined MIPS_NABI
|
#if defined __mips__ && !defined MIPS_NABI
|
||||||
int fpu_mode;
|
int fpu_mode;
|
||||||
#endif /* defined __mips__ && !defined MIPS_NABI */
|
#endif /* defined __mips__ && !defined MIPS_NABI */
|
||||||
|
char buffer[PATH_MAX + 80], *rewrite;
|
||||||
|
size_t remaining;
|
||||||
|
|
||||||
|
/* If name is not absolute, then make it relative to TRACEE's
|
||||||
|
cwd. Use stpcpy, as sprintf is not reentrant. */
|
||||||
|
|
||||||
|
if (name[0] && name[0] != '/')
|
||||||
|
{
|
||||||
|
/* Clear `buffer'. */
|
||||||
|
memset (buffer, 0, sizeof buffer);
|
||||||
|
|
||||||
|
/* Copy over /proc, the PID, and /cwd/. */
|
||||||
|
rewrite = stpcpy (buffer, "/proc/");
|
||||||
|
rewrite = format_pid (rewrite, tracee->pid);
|
||||||
|
rewrite = stpcpy (rewrite, "/cwd/");
|
||||||
|
|
||||||
|
/* Make sure there is enough free space. */
|
||||||
|
remaining = buffer + sizeof buffer - rewrite - 1;
|
||||||
|
rewrite = stpncpy (rewrite, name, remaining);
|
||||||
|
|
||||||
|
/* Replace name with buffer. */
|
||||||
|
name = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
fd = open (name, O_RDONLY);
|
fd = open (name, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
39
exec/trace.c
39
exec/trace.c
@ -457,10 +457,17 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
|||||||
memcpy (&original, regs, sizeof *regs);
|
memcpy (&original, regs, sizeof *regs);
|
||||||
|
|
||||||
/* Figure out what the loader needs to do. */
|
/* Figure out what the loader needs to do. */
|
||||||
|
again1:
|
||||||
area = exec_0 (buffer, tracee, &size, regs);
|
area = exec_0 (buffer, tracee, &size, regs);
|
||||||
|
|
||||||
if (!area)
|
if (!area)
|
||||||
return 1;
|
{
|
||||||
|
/* Handle SIGINTR errors caused by IO. */
|
||||||
|
if (errno == EINTR)
|
||||||
|
goto again1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Rewrite the first argument to point to the loader. */
|
/* Rewrite the first argument to point to the loader. */
|
||||||
|
|
||||||
@ -516,10 +523,7 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
|||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
return 1;
|
||||||
errno = EIO;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WIFSTOPPED (wstatus))
|
if (!WIFSTOPPED (wstatus))
|
||||||
/* The process has been killed in response to a signal.
|
/* The process has been killed in response to a signal.
|
||||||
@ -608,13 +612,14 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs)
|
|||||||
|
|
||||||
#endif /* STACK_GROWS_DOWNWARDS */
|
#endif /* STACK_GROWS_DOWNWARDS */
|
||||||
|
|
||||||
exec_failure:
|
|
||||||
|
|
||||||
/* Continue. */
|
/* Continue. */
|
||||||
if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0))
|
if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0))
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
exec_failure:
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process the system call at which TRACEE is stopped. If the system
|
/* Process the system call at which TRACEE is stopped. If the system
|
||||||
@ -625,10 +630,10 @@ static void
|
|||||||
process_system_call (struct exec_tracee *tracee)
|
process_system_call (struct exec_tracee *tracee)
|
||||||
{
|
{
|
||||||
USER_REGS_STRUCT regs;
|
USER_REGS_STRUCT regs;
|
||||||
int rc, wstatus;
|
int rc, wstatus, save_errno;
|
||||||
USER_WORD callno, sp;
|
USER_WORD callno, sp;
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
USER_WORD old_w0, old_w1, old_w2;
|
USER_WORD old_w1, old_w2;
|
||||||
#endif /* __aarch64__ */
|
#endif /* __aarch64__ */
|
||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
@ -695,6 +700,9 @@ process_system_call (struct exec_tracee *tracee)
|
|||||||
Make sure that the stack pointer is restored to its original
|
Make sure that the stack pointer is restored to its original
|
||||||
position upon exit, or bad things can happen. */
|
position upon exit, or bad things can happen. */
|
||||||
|
|
||||||
|
/* First, save errno; system calls below will clobber it. */
|
||||||
|
save_errno = errno;
|
||||||
|
|
||||||
#ifndef __aarch64__
|
#ifndef __aarch64__
|
||||||
regs.SYSCALL_NUM_REG = -1;
|
regs.SYSCALL_NUM_REG = -1;
|
||||||
#else /* __aarch64__ */
|
#else /* __aarch64__ */
|
||||||
@ -702,7 +710,6 @@ process_system_call (struct exec_tracee *tracee)
|
|||||||
can't find any unused system call, so use fcntl instead, with
|
can't find any unused system call, so use fcntl instead, with
|
||||||
invalid arguments. */
|
invalid arguments. */
|
||||||
regs.SYSCALL_NUM_REG = 72;
|
regs.SYSCALL_NUM_REG = 72;
|
||||||
old_w0 = regs.regs[0];
|
|
||||||
old_w1 = regs.regs[1];
|
old_w1 = regs.regs[1];
|
||||||
old_w2 = regs.regs[2];
|
old_w2 = regs.regs[2];
|
||||||
regs.regs[0] = -1;
|
regs.regs[0] = -1;
|
||||||
@ -739,6 +746,11 @@ process_system_call (struct exec_tracee *tracee)
|
|||||||
if (rc == -1 && errno == EINTR)
|
if (rc == -1 && errno == EINTR)
|
||||||
goto again1;
|
goto again1;
|
||||||
|
|
||||||
|
/* Return if waitpid fails. */
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!WIFSTOPPED (wstatus))
|
if (!WIFSTOPPED (wstatus))
|
||||||
/* The process has been killed in response to a signal. In this
|
/* The process has been killed in response to a signal. In this
|
||||||
case, simply unlink the tracee and return. */
|
case, simply unlink the tracee and return. */
|
||||||
@ -747,16 +759,15 @@ process_system_call (struct exec_tracee *tracee)
|
|||||||
{
|
{
|
||||||
#ifdef __mips__
|
#ifdef __mips__
|
||||||
/* MIPS systems place errno in v0 and set a3 to 1. */
|
/* MIPS systems place errno in v0 and set a3 to 1. */
|
||||||
regs.gregs[2] = errno;
|
regs.gregs[2] = save_errno;
|
||||||
regs.gregs[7] = 1;
|
regs.gregs[7] = 1;
|
||||||
#else /* !__mips__ */
|
#else /* !__mips__ */
|
||||||
regs.SYSCALL_RET_REG = -errno;
|
regs.SYSCALL_RET_REG = -save_errno;
|
||||||
#endif /* __mips__ */
|
#endif /* __mips__ */
|
||||||
|
|
||||||
/* Report errno. */
|
/* Report errno. */
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
/* Restore x0, x1 and x2. */
|
/* Restore x1 and x2. x0 is clobbered by errno. */
|
||||||
regs.regs[0] = old_w0;
|
|
||||||
regs.regs[1] = old_w1;
|
regs.regs[1] = old_w1;
|
||||||
regs.regs[2] = old_w2;
|
regs.regs[2] = old_w2;
|
||||||
aarch64_set_regs (tracee->pid, ®s, false);
|
aarch64_set_regs (tracee->pid, ®s, false);
|
||||||
|
Loading…
Reference in New Issue
Block a user