Re: [PATCH v7 0/6] introduce PIDFD_SELF* sentinels

From: Lorenzo Stoakes
Date: Sat Feb 01 2025 - 11:39:33 EST


On Sat, Feb 01, 2025 at 12:12:46PM +0100, Christian Brauner wrote:
> > Intent is for Christian to take this in his tree (if he so wishes) to be
> > clear!
>
> If you send me an updated blurb I can fold it.

Thanks, I therefore propose replacing the cover letter blurb with the below:

----8<----
If you wish to utilise a pidfd interface to refer to the current process or
thread then there is a lot of ceremony involved, looking something like:

pid_t pid = getpid();
int pidfd = pidfd_open(pid, PIDFD_THREAD);

if (pidfd < 0) {
... error handling ...
}

if (process_madvise(pidfd, iovec, 8, MADV_GUARD_INSTALL, 0)) {
... cleanup pidfd ...
... error handling ...
}

...

... cleanup pidfd ...

This adds unnecessary overhead + system calls, complicated error handling
and in addition pidfd_open() is subject to RLIMIT_NOFILE (i.e. the limit of
per-process number of open file descriptors), so the call may fail
spuriously on this basis.

Rather than doing this we can make use of sentinels for this purpose which can
be passed as the pidfd instead. This looks like:

if (process_madvise(PIDFD_SELF, iovec, 8, MADV_GUARD_INSTALL, 0)) {
... error handling ...
}

And avoids all of the aforementioned issues. This series introduces such
sentinels.

It is useful to refer to both the current thread from the userland's
perspective for which we use PIDFD_SELF, and the current process from the
userland's perspective, for which we use PIDFD_SELF_PROCESS.

There is unfortunately some confusion between the kernel and userland as to
what constitutes a process - a thread from the userland perspective is a
process in userland, and a userland process is a thread group (more
specifically the thread group leader from the kernel perspective). We
therefore alias things thusly:

* PIDFD_SELF_THREAD aliased by PIDFD_SELF - use PIDTYPE_PID.
* PIDFD_SELF_THREAD_GROUP alised by PIDFD_SELF_PROCESS - use PIDTYPE_TGID.

In all of the kernel code we refer to PIDFD_SELF_THREAD and
PIDFD_SELF_THREAD_GROUP. However we expect users to use PIDFD_SELF and
PIDFD_SELF_PROCESS.

This matters for cases where, for instance, a user unshare()'s FDs or does
thread-specific signal handling and where the user would be hugely confused
if the FDs referenced or signal processed referred to the thread group
leader rather than the individual thread.

For now we only adjust pidfd_get_task() and the pidfd_send_signal() system
call with specific handling for this, implementing this functionality for
process_madvise(), process_mrelease() (albeit, using it here wouldn't
really make sense) and pidfd_send_signal().

We defer making further changes, as this would require a significant rework
of the pidfd mechanism.

The motivating case here is to support PIDFD_SELF in process_madvise(), so
this suffices for immediate uses. Moving forward, this can be further
expanded to other uses.