capsicum: allow subset of wait4(2) functionality

The usual way of handling process exit exit in capsicum(4) mode is
by using process descriptors (pdfork(2)) instead of the traditional
fork(2)/wait4(2) API. But most apps hadn't been converted this way,
and many cannot because the wait is hidden behind a library APIs that
revolve around PID numbers and not descriptors; GLib's
g_spawn_check_wait_status(3) is one example.

Thus, provide backwards compatibility by allowing the wait(2) family
of functions in Capsicum mode, except for child processes created by
pdfork(2).

Reviewed by:	brooks, oshogbo
Sponsored by:	Innovate UK
Differential Revision:	https://reviews.freebsd.org/D44372
This commit is contained in:
Edward Tomasz Napierala 2024-08-27 17:19:24 +02:00 committed by Mariusz Zaborski
parent 3b62f33500
commit d0675399d0
4 changed files with 20 additions and 5 deletions

View file

@ -594,7 +594,6 @@ FORK_TEST_F(WithFiles, AllowedMiscSyscalls) {
AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
errno = 0;
EXPECT_CAPMODE(ptrace_(PTRACE_PEEKDATA_, pid, &pid, NULL));
EXPECT_CAPMODE(waitpid(pid, NULL, WNOHANG));
SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
if (verbose) fprintf(stderr, " child finished\n");
}

View file

@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd June 24, 2022
.Dd August 27, 2024
.Dt WAIT 2
.Os
.Sh NAME
@ -605,9 +605,13 @@ must be checked against zero to determine if a process reported status.
.Pp
The
.Fn wait
family of functions will not return a child process created with
family of functions will only return a child process created with
.Xr pdfork 2
unless specifically directed to do so by specifying its process ID.
if the calling process is not in
.Xr capsicum 4
capability mode, and
.Nm
has been explicitly given the child's process ID.
.Sh ERRORS
The
.Fn wait

View file

@ -1330,6 +1330,18 @@ kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
return (0);
}
/*
* When running in capsicum(4) mode, make wait(2) ignore
* processes created with pdfork(2). This is because one can
* disown them - by passing their process descriptor to another
* process - which means it needs to be prevented from touching
* them afterwards.
*/
if (IN_CAPABILITY_MODE(td) && p->p_procdesc != NULL) {
PROC_UNLOCK(p);
continue;
}
nfound++;
PROC_LOCK_ASSERT(p, MA_OWNED);

View file

@ -157,7 +157,7 @@
int fd
);
}
7 AUE_WAIT4 STD {
7 AUE_WAIT4 STD|CAPENABLED {
int wait4(
int pid,
_Out_opt_ int *status,