HomeFreeBSD

killpg(): close a race with fork(), part 2

Description

killpg(): close a race with fork(), part 2

When we are sending terminating signal to the group, killpg() needs
to guarantee that all group members are to be terminated (it does not
need to ensure that they are terminated on return from killpg()). The
pg_killsx change eliminates the largest window there, but still, if
a multithreaded process is signalled, the following could happen:

  • thread 1 is selected for the signal delivery and gets descheduled
  • thread 2 waits for pg_killsx lock, obtains it and forks
  • thread 1 continue executing and terminates the process

This scenario allows the child to escape still.

Fix it by single-threading forking parent if a conflict with pg_killsx
is noted. We try to lock pg_killsx without sleeping, and failure to
acquire it means that a parallel killpg(2) is executed. Then, stop
other threads for running and in particular, receive signals, to avoid
the situation explained above.

Reviewed by: markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D41128

Details

Provenance
kibAuthored on Jul 20 2023, 9:19 PM
Reviewer
markj
Differential Revision
D41128: Different fix for the killpg race, part2
Parents
rGdfe172484d0e: sigtd(): prefer non-stopped thread as a target for signal queue
Branches
Unknown
Tags
Unknown