Commit 98aacc77 authored by Alexandre Julliard's avatar Alexandre Julliard

Avoid SIGSTOP/SIGCONT race when ptrace is disabled.

parent f2f1ff33
......@@ -462,8 +462,7 @@ static void read_process_memory( struct process *process, const int *addr,
set_error( STATUS_ACCESS_DENIED );
return;
}
suspend_thread( thread, 0 );
if (thread->attached)
if (suspend_for_ptrace( thread ))
{
while (len > 0 && max)
{
......@@ -483,10 +482,9 @@ static void read_process_memory( struct process *process, const int *addr,
}
if (len && (read_thread_int( thread, addr + len - 1, &dummy ) == -1)) goto done;
}
done:
resume_thread( thread );
}
else set_error( STATUS_ACCESS_DENIED );
done:
resume_thread( thread );
}
/* write data to a process memory space */
......@@ -508,8 +506,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
set_error( STATUS_ACCESS_DENIED );
return;
}
suspend_thread( thread, 0 );
if (thread->attached)
if (suspend_for_ptrace( thread ))
{
/* first word is special */
if (len > 1)
......@@ -544,10 +541,9 @@ static void write_process_memory( struct process *process, int *addr, size_t len
}
if (len && (write_thread_int( thread, addr + len - 1, 0, 0 ) == -1)) goto done;
}
done:
resume_thread( thread );
}
else set_error( STATUS_ACCESS_DENIED );
done:
resume_thread( thread );
}
/* take a snapshot of currently running processes */
......
......@@ -157,6 +157,25 @@ void continue_thread( struct thread *thread )
else ptrace( PTRACE_CONT, thread->unix_pid, 1, SIGSTOP );
}
/* suspend a thread to allow using ptrace on it */
/* you must do a resume_thread when finished with the thread */
int suspend_for_ptrace( struct thread *thread )
{
if (thread->attached)
{
suspend_thread( thread, 0 );
return 1;
}
if (attach_thread( thread ))
{
/* the attach will have suspended it */
thread->suspend++;
return 1;
}
set_error( STATUS_ACCESS_DENIED );
return 0;
}
/* read an int from a thread address space */
int read_thread_int( struct thread *thread, const int *addr, int *data )
{
......
......@@ -541,8 +541,7 @@ static void get_selector_entry( struct thread *thread, int entry,
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
return;
}
suspend_thread( thread, 0 );
if (thread->attached)
if (suspend_for_ptrace( thread ))
{
unsigned char flags_buf[4];
int *addr = (int *)thread->process->ldt_copy + 2 * entry;
......@@ -551,10 +550,9 @@ static void get_selector_entry( struct thread *thread, int entry,
addr = (int *)thread->process->ldt_flags + (entry >> 2);
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
*flags = flags_buf[entry & 3];
done:
resume_thread( thread );
}
else set_error( STATUS_ACCESS_DENIED );
done:
resume_thread( thread );
}
/* kill a thread on the spot */
......
......@@ -86,6 +86,7 @@ extern void wait4_thread( struct thread *thread, int signal );
extern void stop_thread( struct thread *thread );
extern void continue_thread( struct thread *thread );
extern void detach_thread( struct thread *thread );
extern int suspend_for_ptrace( struct thread *thread );
extern int read_thread_int( struct thread *thread, const int *addr, int *data );
extern int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment