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, ...@@ -462,8 +462,7 @@ static void read_process_memory( struct process *process, const int *addr,
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return; return;
} }
suspend_thread( thread, 0 ); if (suspend_for_ptrace( thread ))
if (thread->attached)
{ {
while (len > 0 && max) while (len > 0 && max)
{ {
...@@ -483,10 +482,9 @@ static void read_process_memory( struct process *process, const int *addr, ...@@ -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; 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 */ /* write data to a process memory space */
...@@ -508,8 +506,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len ...@@ -508,8 +506,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return; return;
} }
suspend_thread( thread, 0 ); if (suspend_for_ptrace( thread ))
if (thread->attached)
{ {
/* first word is special */ /* first word is special */
if (len > 1) if (len > 1)
...@@ -544,10 +541,9 @@ static void write_process_memory( struct process *process, int *addr, size_t len ...@@ -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; 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 */ /* take a snapshot of currently running processes */
......
...@@ -157,6 +157,25 @@ void continue_thread( struct thread *thread ) ...@@ -157,6 +157,25 @@ void continue_thread( struct thread *thread )
else ptrace( PTRACE_CONT, thread->unix_pid, 1, SIGSTOP ); 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 */ /* read an int from a thread address space */
int read_thread_int( struct thread *thread, const int *addr, int *data ) 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, ...@@ -541,8 +541,7 @@ static void get_selector_entry( struct thread *thread, int entry,
set_error( STATUS_INVALID_PARAMETER ); /* FIXME */ set_error( STATUS_INVALID_PARAMETER ); /* FIXME */
return; return;
} }
suspend_thread( thread, 0 ); if (suspend_for_ptrace( thread ))
if (thread->attached)
{ {
unsigned char flags_buf[4]; unsigned char flags_buf[4];
int *addr = (int *)thread->process->ldt_copy + 2 * entry; int *addr = (int *)thread->process->ldt_copy + 2 * entry;
...@@ -551,10 +550,9 @@ static void get_selector_entry( struct thread *thread, int entry, ...@@ -551,10 +550,9 @@ static void get_selector_entry( struct thread *thread, int entry,
addr = (int *)thread->process->ldt_flags + (entry >> 2); addr = (int *)thread->process->ldt_flags + (entry >> 2);
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done; if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
*flags = flags_buf[entry & 3]; *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 */ /* kill a thread on the spot */
......
...@@ -86,6 +86,7 @@ extern void wait4_thread( struct thread *thread, int signal ); ...@@ -86,6 +86,7 @@ extern void wait4_thread( struct thread *thread, int signal );
extern void stop_thread( struct thread *thread ); extern void stop_thread( struct thread *thread );
extern void continue_thread( struct thread *thread ); extern void continue_thread( struct thread *thread );
extern void detach_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 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 ); 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