arm64: ptrace: Fix overwriting 1st argument with return value
Since arm64 shares the return value with the area of the first argument, rewriting the return value before the system call execution completes destroys the first argument. Change-Id: I959944879254d8dd3a29489a65d8f274d45338e6 Fujitsu: POSTK_DEBUG_ARCH_DEP_110
This commit is contained in:
committed by
Masamichi Takagi
parent
ac18a24a27
commit
ea7f517e3d
@ -2735,4 +2735,12 @@ void calculate_time_from_tsc(struct timespec *ts)
|
||||
++ts->tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
extern void ptrace_syscall_event(struct thread *thread);
|
||||
long arch_ptrace_syscall_event(struct thread *thread,
|
||||
ihk_mc_user_context_t *ctx, long setret)
|
||||
{
|
||||
ptrace_syscall_event(thread);
|
||||
return setret;
|
||||
}
|
||||
/*** End of File ***/
|
||||
|
||||
@ -2858,4 +2858,13 @@ void calculate_time_from_tsc(struct timespec *ts)
|
||||
++ts->tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
extern void ptrace_syscall_event(struct thread *thread);
|
||||
long arch_ptrace_syscall_event(struct thread *thread,
|
||||
ihk_mc_user_context_t *ctx, long setret)
|
||||
{
|
||||
ihk_mc_syscall_ret(ctx) = setret;
|
||||
ptrace_syscall_event(thread);
|
||||
return ihk_mc_syscall_ret(ctx);
|
||||
}
|
||||
/*** End of File ***/
|
||||
|
||||
@ -586,6 +586,10 @@ typedef struct uti_attr {
|
||||
uint64_t flags; /* Representing location and behavior hints by bitmap */
|
||||
} uti_attr_t;
|
||||
|
||||
struct thread;
|
||||
long arch_ptrace_syscall_event(struct thread *thread,
|
||||
ihk_mc_user_context_t *ctx, long setret);
|
||||
|
||||
struct uti_ctx {
|
||||
union {
|
||||
char ctx[4096];
|
||||
|
||||
@ -2273,7 +2273,7 @@ static int ptrace_report_exec(struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ptrace_syscall_event(struct thread *thread)
|
||||
void ptrace_syscall_event(struct thread *thread)
|
||||
{
|
||||
int ptrace = thread->ptrace;
|
||||
|
||||
@ -2551,8 +2551,7 @@ SYSCALL_DECLARE(execve)
|
||||
}
|
||||
|
||||
if (thread->ptrace) {
|
||||
ihk_mc_syscall_ret(ctx) = 0;
|
||||
ptrace_syscall_event(thread);
|
||||
arch_ptrace_syscall_event(thread, ctx, 0);
|
||||
}
|
||||
|
||||
/* Unmap all memory areas of the process, userspace will be gone */
|
||||
@ -9619,6 +9618,9 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
|
||||
if(cpu_local_var(current)->proc->status == PS_EXITED &&
|
||||
(num != __NR_exit && num != __NR_exit_group)){
|
||||
/* x86_64: Setting -EINVAL to rax is done in the
|
||||
* following return.
|
||||
*/
|
||||
save_syscall_return_value(num, -EINVAL);
|
||||
check_signal(-EINVAL, NULL, -1);
|
||||
set_cputime(CPUTIME_MODE_K2U);
|
||||
@ -9628,8 +9630,8 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
cpu_enable_interrupt();
|
||||
|
||||
if (cpu_local_var(current)->ptrace) {
|
||||
ihk_mc_syscall_ret(ctx) = -ENOSYS;
|
||||
ptrace_syscall_event(cpu_local_var(current));
|
||||
arch_ptrace_syscall_event(cpu_local_var(current),
|
||||
ctx, -ENOSYS);
|
||||
num = ihk_mc_syscall_number(ctx);
|
||||
}
|
||||
|
||||
@ -9675,11 +9677,15 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
|
||||
}
|
||||
|
||||
if (cpu_local_var(current)->ptrace) {
|
||||
ihk_mc_syscall_ret(ctx) = l;
|
||||
ptrace_syscall_event(cpu_local_var(current));
|
||||
l = ihk_mc_syscall_ret(ctx);
|
||||
/* arm64: The return value modified by the tracer is
|
||||
* stored to x0 in the following check_signal().
|
||||
*/
|
||||
l = arch_ptrace_syscall_event(cpu_local_var(current), ctx, l);
|
||||
}
|
||||
|
||||
/* x86_64: Setting l to rax is done in the
|
||||
* following return.
|
||||
*/
|
||||
save_syscall_return_value(num, l);
|
||||
|
||||
#ifdef PROFILE_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user