Fall back to signalfd+SIGCHLD when pidfd_open returns EPERM#160
Fall back to signalfd+SIGCHLD when pidfd_open returns EPERM#160paddor wants to merge 2 commits intosocketry:mainfrom
Conversation
Inside snap confinement (pre-snapd 2.75), the seccomp profile blocks pidfd_open with EPERM. When this happens, the epoll and uring selectors now fall back to a signalfd watching SIGCHLD: - Block SIGCHLD via pthread_sigmask - Create a signalfd (SFD_CLOEXEC | SFD_NONBLOCK) - Register it with epoll/uring for readability - Loop: yield → drain signalfd → waitpid(WNOHANG) for the target pid - Cleanup: close signalfd, restore signal mask via rb_ensure Since SIGCHLD fires for any child process, the fallback loops until the specific target pid has exited. Tests use seccomp-BPF (via Fiddle) in a forked child to block pidfd_open and exercise the fallback path.
|
For the reasons you stated, I'm slightly against merging this. But if we could make the burden a little lighter the calculus might change. Do you think we can extract the logic into a shared code file, so that we don't duplicate this between I know I deliberately avoided sharing a lot of code in the backends but it's mostly the mechanics of the scheduler, and I was aiming to have independent implementations where the logic was significantly tied to the OS interface. But for this, I think it's the same, right? So we could probably share the implementation and just have WDYT? |
Move the signalfd lifecycle (open/check/close) into a shared file that is #include'd by both epoll.c and uring.c, like pidfd.c. Each backend keeps only its selector-specific registration and yield loop.
|
Good idea — done in b2098b9. I extracted the signalfd lifecycle into
Each backend keeps only its selector-specific registration loop (epoll_ctl vs io_uring_prep_poll_add). The EPERM fallback in each |
Summary
pidfd_openfails withEPERM(e.g. inside snap confinement), the epoll and uring selectors now fall back to asignalfdwatchingSIGCHLDinstead of raisingSIGCHLDfires for any child, the fallback loops until the specific target pid exits#ifdef HAVE_SYS_SIGNALFD_H; on systems without signalfd, behavior is unchanged (raises onEPERMas before)Context
This is not urgent — snapd 2.75+ already allows
pidfd_openin its default seccomp profile, so the confinement issue is resolved for most users. However, older snapd versions (and potentially other seccomp-confined environments) still block the syscall. Feel free to close this if you'd rather not carry the extra code path.Test plan
Fiddle) in a forked child to blockpidfd_openwithEPERM, then exercise#process_waitthrough the signalfd path