Fix use-after-free in gdbserver
-fsanitize=address pointed out a use-after-free in gdbserver. In particular, handle_detach could reference "process" after it was deleted by detach_inferior. Avoiding this also necessitated changing target_ops::join to take a pid rather than a process_info*. Tested by the buildbot using a few of the gdbserver builders. gdb/gdbserver/ChangeLog 2018-11-29 Tom Tromey <tom@tromey.com> * win32-low.c (win32_join): Take pid, not process. * target.h (struct target_ops) <join>: Change argument type. (join_inferior): Change argument name. * spu-low.c (spu_join): Take pid, not process. * server.c (handle_detach): Preserve pid before destroying process. * lynx-low.c (lynx_join): Take pid, not process. * linux-low.c (linux_join): Take pid, not process.
This commit is contained in:
parent
e368bf56d3
commit
d105de22fc
@ -1,3 +1,14 @@
|
||||
2018-11-29 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* win32-low.c (win32_join): Take pid, not process.
|
||||
* target.h (struct target_ops) <join>: Change argument type.
|
||||
(join_inferior): Change argument name.
|
||||
* spu-low.c (spu_join): Take pid, not process.
|
||||
* server.c (handle_detach): Preserve pid before destroying
|
||||
process.
|
||||
* lynx-low.c (lynx_join): Take pid, not process.
|
||||
* linux-low.c (linux_join): Take pid, not process.
|
||||
|
||||
2018-11-23 Alan Hayward <alan.hayward@arm.com>
|
||||
|
||||
* linux-aarch64-low.c (aarch64_cannot_store_register): Remove.
|
||||
|
@ -1670,12 +1670,12 @@ linux_mourn (struct process_info *process)
|
||||
}
|
||||
|
||||
static void
|
||||
linux_join (process_info *proc)
|
||||
linux_join (int pid)
|
||||
{
|
||||
int status, ret;
|
||||
|
||||
do {
|
||||
ret = my_waitpid (proc->pid, &status, 0);
|
||||
ret = my_waitpid (pid, &status, 0);
|
||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||
break;
|
||||
} while (ret != -1 || errno != ECHILD);
|
||||
|
@ -562,7 +562,7 @@ lynx_mourn (struct process_info *proc)
|
||||
/* Implement the join target_ops method. */
|
||||
|
||||
static void
|
||||
lynx_join (process_info *proc)
|
||||
lynx_join (int pid)
|
||||
{
|
||||
/* The PTRACE_DETACH is sufficient to detach from the process.
|
||||
So no need to do anything extra. */
|
||||
|
@ -1255,11 +1255,15 @@ handle_detach (char *own_buf)
|
||||
|
||||
fprintf (stderr, "Detaching from process %d\n", process->pid);
|
||||
stop_tracing ();
|
||||
|
||||
/* We'll need this after PROCESS has been destroyed. */
|
||||
int pid = process->pid;
|
||||
|
||||
if (detach_inferior (process) != 0)
|
||||
write_enn (own_buf);
|
||||
else
|
||||
{
|
||||
discard_queued_stop_replies (ptid_t (process->pid));
|
||||
discard_queued_stop_replies (ptid_t (pid));
|
||||
write_ok (own_buf);
|
||||
|
||||
if (extended_protocol || target_running ())
|
||||
@ -1269,7 +1273,7 @@ handle_detach (char *own_buf)
|
||||
and instead treat this like a normal program exit. */
|
||||
cs.last_status.kind = TARGET_WAITKIND_EXITED;
|
||||
cs.last_status.value.integer = 0;
|
||||
cs.last_ptid = ptid_t (process->pid);
|
||||
cs.last_ptid = ptid_t (pid);
|
||||
|
||||
current_thread = NULL;
|
||||
}
|
||||
@ -1281,7 +1285,7 @@ handle_detach (char *own_buf)
|
||||
/* If we are attached, then we can exit. Otherwise, we
|
||||
need to hang around doing nothing, until the child is
|
||||
gone. */
|
||||
join_inferior (process);
|
||||
join_inferior (pid);
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
|
@ -362,12 +362,12 @@ spu_mourn (struct process_info *process)
|
||||
}
|
||||
|
||||
static void
|
||||
spu_join (process_info *proc)
|
||||
spu_join (int pid)
|
||||
{
|
||||
int status, ret;
|
||||
|
||||
do {
|
||||
ret = waitpid (proc->pid, &status, 0);
|
||||
ret = waitpid (pid, &status, 0);
|
||||
if (WIFEXITED (status) || WIFSIGNALED (status))
|
||||
break;
|
||||
} while (ret != -1 || errno != ECHILD);
|
||||
|
@ -103,9 +103,9 @@ struct target_ops
|
||||
|
||||
void (*mourn) (struct process_info *proc);
|
||||
|
||||
/* Wait for process PROC to exit. */
|
||||
/* Wait for process PID to exit. */
|
||||
|
||||
void (*join) (process_info *proc);
|
||||
void (*join) (int pid);
|
||||
|
||||
/* Return 1 iff the thread with process ID PID is alive. */
|
||||
|
||||
@ -530,8 +530,8 @@ int kill_inferior (process_info *proc);
|
||||
#define store_inferior_registers(regcache, regno) \
|
||||
(*the_target->store_registers) (regcache, regno)
|
||||
|
||||
#define join_inferior(proc) \
|
||||
(*the_target->join) (proc)
|
||||
#define join_inferior(pid) \
|
||||
(*the_target->join) (pid)
|
||||
|
||||
#define target_supports_non_stop() \
|
||||
(the_target->supports_non_stop ? (*the_target->supports_non_stop ) () : 0)
|
||||
|
@ -873,9 +873,9 @@ win32_mourn (struct process_info *process)
|
||||
/* Implementation of target_ops::join. */
|
||||
|
||||
static void
|
||||
win32_join (process_info *proc)
|
||||
win32_join (int pid)
|
||||
{
|
||||
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, proc->pid);
|
||||
HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (h != NULL)
|
||||
{
|
||||
WaitForSingleObject (h, INFINITE);
|
||||
|
Loading…
Reference in New Issue
Block a user