Page MenuHomeFreeBSD

pddupfd(2)
Needs ReviewPublic

Authored by kib on Fri, May 22, 4:07 AM.
Tags
None
Referenced Files
F157901070: D57163.diff
Tue, May 26, 7:56 AM
F157849138: D57163.diff
Mon, May 25, 8:06 PM
F157823334: D57163.diff
Mon, May 25, 2:34 PM
Unknown Object (File)
Mon, May 25, 7:41 AM
Unknown Object (File)
Mon, May 25, 4:41 AM
Unknown Object (File)
Mon, May 25, 2:05 AM
Unknown Object (File)
Sun, May 24, 10:39 PM

Details

Reviewers
markj
brooks
Summary

This is inspired by Linux' pidfd_getfd(), and should put our procdesc facility mostly on par with Linux.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

kib requested review of this revision.Fri, May 22, 4:07 AM
kib added a parent revision: D57124: sys: add pdopenpid(2).

The test program

/* $Id: pddupfd.c,v 1.2 2026/05/22 03:59:31 kostik Exp kostik $ */

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/procdesc.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MY_SYS_pdopenpid	603
#define MY_SYS_pddupfd		604

static int
my_pdopenpid(pid_t pid, int flags)
{
	return (syscall(MY_SYS_pdopenpid, pid, flags));
}

static int
my_pddupfd(pid_t pid, int remote_fd, int flags)
{
	return (syscall(MY_SYS_pddupfd, pid, remote_fd, flags));
}

static void
check(int fd, int child, int *comm)
{
	struct __wrusage wu;
	struct __siginfo si;
	int error, f, pp, status, workfd;
	char cmd[128];

	error = pdgetpid(fd, &pp);
	if (error == -1)
		err(1, "pgdetpid");
	printf("child pid %d %d\n", child, pp);

	while (*comm == -1)
		;
	workfd = my_pddupfd(fd, *comm, 0);
	if (workfd == -1)
		err(1, "pddupfd");

	f = fcntl(workfd, F_GETFD);
	if (f == -1)
		err(1, "F_GETFD %d", workfd);
	f &= ~FD_CLOEXEC;
	error = fcntl(workfd, F_SETFD, f);
	if (error == -1)
		err(1, "F_SETFD %d", workfd);

	snprintf(cmd, sizeof(cmd), "cat 0<&%d", workfd);
	system(cmd);
	close(workfd);

	*comm = 0;
	
	error = pdwait(fd, &status, WEXITED, &wu, &si);
	if (error == -1)
		err(1, "pdwait");
	printf("exited pid %d status %#x si.si_status %#x si.si_code %#x\n",
	    pp, status, si.si_status, si.si_code);
}

int
main(void)
{
	int *comm;
	pid_t child;
	int fd, workfd;

	comm = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED |
	    MAP_ANONYMOUS, -1, 0);
	if (comm == MAP_FAILED)
		err(1, "mmap");
	*comm = -1;

	child = fork();
	if (child == -1)
		err(1, "fork");
	if (child == 0) {
		workfd = open("/etc/passwd", O_RDONLY);
		if (workfd == -1)
			err(1, "open");
		*comm = workfd;
		while (*comm != 0)
			sleep(1);
		_exit(0x123);
	}

	fd = my_pdopenpid(child, 0);
	if (fd == -1)
		err(1, "pdopenpid");

	*comm = 1;
	check(fd, child, comm);
	close(fd);
}

Preseve capabilities and RESOLVE_BENEATH of the source fd.

I cannot apply the patch, it fails in pdfork.2. (I already applied the pdopenpid() patch.) Could you please rebase? Or, if your branch is already public, could you please include a pointer to it in the review description so that it's easier for me to fetch? That makes it easier for me to e.g., write syzkaller descriptions for new syscalls.

I cannot apply the patch, it fails in pdfork.2. (I already applied the pdopenpid() patch.) Could you please rebase? Or, if your branch is already public, could you please include a pointer to it in the review description so that it's easier for me to fetch? That makes it easier for me to e.g., write syzkaller descriptions for new syscalls.

I had to apply ACL to my gitweb server due to 'AI'. If you provide me with the list of IP addresses to enable, I will open for them.

I pushed the code to github.com/kostikbel/freebsd-src branch pdrfork.