Page MenuHomeFreeBSD

exit1(9): do not deadlock if exit is called due to PT_SC_REMOTERQ
ClosedPublic

Authored by kib on Fri, Jun 5, 9:50 PM.
Tags
None
Referenced Files
F159641525: D57482.id179400.diff
Tue, Jun 16, 1:37 PM
F159631455: D57482.id179307.diff
Tue, Jun 16, 11:33 AM
Unknown Object (File)
Tue, Jun 16, 4:55 AM
Unknown Object (File)
Mon, Jun 15, 5:54 PM
Unknown Object (File)
Mon, Jun 15, 4:51 PM
Unknown Object (File)
Mon, Jun 15, 4:51 PM
Unknown Object (File)
Mon, Jun 15, 4:50 PM
Unknown Object (File)
Mon, Jun 15, 4:50 PM
Subscribers

Details

Summary

The remote syscall is executed in the context where debugger owns a
p_lock hold on the target. Due to this, exit1() waiting for p_lock
going to zero, never happen.

Postpone the exit1() call to ast then, saving the provided rval and
signo in the struct proc. Mark the async-exiting proc with the new
p_flag P_ASYNC_EXIT.

While p_xexit can be reused, p_xsig can be only set by actual exit1(),
otherwise it breaks the ptrace mechanism. Allocate a dedicated p_asig
for it.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

kib requested review of this revision.Fri, Jun 5, 9:50 PM

Commit everything before generating diff from git.

sys/kern/kern_ucoredump.c
201

What about the exit1() calls from do_execve() and fork_return()? Can't they be triggered via ptrace(PT_SC_REMOTE)?

kib marked an inline comment as done.Fri, Jun 5, 11:03 PM
kib added inline comments.
sys/kern/kern_ucoredump.c
201

From fork_return it cannot, I believe.
For execve yes, and I had it changed in the previous version of the patch: I had exit1 and exit2 swapped. Then I decided to keep exit1 synchronous and forgot to update execve.

kib marked an inline comment as done.

Plug exit call in execve

sys/kern/kern_exit.c
229

Is there any reason this shouldn't be spelled kern_exit(), and all external consumers updated to use it? e.g., shouldn't linux_exit() call this function as well? AFAIK it is possible to use ptrace(PT_SC_REMOTE) with foreign ABIs.

245

How can this case happen?

kib marked 2 inline comments as done.Sat, Jun 6, 12:16 AM
kib added inline comments.
sys/kern/kern_exit.c
229

I like the exit2() name, it has the same weirdness flavor as exit1(). If you insist, I will change it.

245

I believe e.g. ptrace(PT_CONTINUE, pid, 1, SIGKILL) could trigger it. Any killing signal processed by TDA_SIG before TDA_ASYNC_EXIT would get there through sigexit().

kib marked 2 inline comments as done.

Handle linux_exit()

sys/kern/kern_exit.c
229

I think it's not very nice to force others to figure out whether they should use exit1() or exit2(), when there is no comment explaining the difference, nor any clue in the names (shouldn't exit1() at least call exit2()?).

If we keep both names, then one of them should be local to kern_exit.c.

kib marked an inline comment as done.

Rename exit2() to kern_exit().
Add comment.

I'm not sure about the exit1() call in fork_return(). Isn't it possible for the debugger to attach to the nascent process (see the earlier ptracestop() calls there) and then trigger a system call immediately?

sys/kern/kern_exec.c
1045

This annotation isn't true anymore.

sys/kern/kern_exit.c
240
kib marked 2 inline comments as done.

kern_exit() in fork_return()
Remove unreached comment.
Fix function name in kassert.

I'm not sure about the exit1() call in fork_return(). Isn't it possible for the debugger to attach to the nascent process (see the earlier ptracestop() calls there) and then trigger a system call immediately?

I added a test for this scenario to D57485. PT_SC_REMOTE requires the target to be stopped at the user/kernel boundary so cannot be used while the new child is blocked in fork_return(). But I think using kern_exit() in fork_return() is okay anyway.

This revision is now accepted and ready to land.Mon, Jun 8, 7:50 PM