Skip to content

nspawn: add "swapcontext()" to seccomp whitelist for user contexts on ppc32 #9485

@LionNatsu

Description

@LionNatsu

systemd version the issue has been seen with

From 96bedbe nspawn: replace syscall blacklist with a whitelist

... v239 v238 v237 v236 v235.

Unexpected behaviour you saw

Function swapcontext is out of system call filter whitelist of nspawn. Anyone of {get,set,make,swap}context is not available on PowerPC 32-bit (i.e. PPC32) container by default.

Use case: Fibers of Ruby is not available in PPC32 container.
https://bugs.ruby-lang.org/issues/14883

Steps to reproduce the problem

Part. 1

nspawn a PPC32 container, run Ruby code:

fib = Enumerator.new do |y|
  y << "FOO"
  y << "BAR"
end
puts fib.next

It should print "FOO", but it segmentation fault.

Part. 2

#include <ucontext.h>
#include <errno.h>
int main() {
    ucontext_t c;
    if (getcontext(&c) < 0)
        return errno;
    return 0;
}

It should return 0, but it returned 1 (EPERM).

Notes

A fiber uses getcontext() function to get the current context, to construct a new context, and uses makecontext() to switch context, so we have a nice lightweight userspace "thread" (or coroutine, fiber etc.).

The underlying call of getcontext() depends on architectures.

I checked source code from glibc (/sysdeps/unix/sysv/linux):

aarch64: rt_sigprocmask
sparc64: trap 0x6e
sparc32: rt_sigprocmask
sh3: sigprocmask
sh4: sigprocmask
i386: sigprocmask
arm: sigprocmask
powerpc64: sigprocmask
powerpc32: swapcontext
alpha: osf_sigprocmask
s390-32: rt_sigprocmask
s390-64: rt_sigprocmask
nios2: rt_sigprocmask
ia64: rt_sigprocmask
hppa: sigprocmask
x86_64: rt_sigprocmask
m680x0: sigprocmask

We already have {,rt_}sigprocmask in whitelist now (@signal), but there is no swapcontext.

[SYSCALL_FILTER_SET_SIGNAL] = {
.name = "@signal",
.help = "Process signal handling",
.value =
"rt_sigaction\0"
"rt_sigpending\0"
"rt_sigprocmask\0"
"rt_sigsuspend\0"
"rt_sigtimedwait\0"
"sigaction\0"
"sigaltstack\0"
"signal\0"
"signalfd\0"
"signalfd4\0"
"sigpending\0"
"sigprocmask\0"
"sigsuspend\0"
},

The syscall swapcontext() is a kind of mixture of {get,set,make,swap}context. Semantically it may be not suitable for @signal, we can put it in here:

/* Plus a good set of additional syscalls which are not part of any of the groups above */
{ 0, "brk" },
{ 0, "capget" },
{ 0, "capset" },

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions