Avoid SIGSTOP/SIGCONT race when ptrace is disabled.
This commit is contained in:
parent
f2f1ff333e
commit
98aacc7751
|
@ -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 );
|
||||
|
||||
|
|
Loading…
Reference in New Issue