[RFC 1/2] tools/nolibc: add sigaction()

Thomas Weißschuh thomas.weissschuh at linutronix.de
Fri Jun 27 00:45:19 PDT 2025


On Fri, Jun 27, 2025 at 06:46:56AM +0000, Berg, Benjamin wrote:
> On Fri, 2025-06-27 at 06:48 +0200, Thomas Weißschuh wrote:
> > On Thu, Jun 26, 2025 at 09:57:13PM +0200, Benjamin Berg wrote:
> > > From: Benjamin Berg <benjamin.berg at intel.com>
> > > 
> > > In preparation to add tests that use it.
> > 
> > I tried to implement signal support in nolibc before but ran into some issues.
> > Unfortunately I don't remember the details.
> > But I guess you know more about signals than me, so let's try it again.
> > In any case this should add some tests to
> > tools/testing/selftests/nolibc/nolibc-test.c.
> > 
> > If you test it with qemu-user please be aware that there were issues around
> > SA_RESTORER up until recently [0] [1].
> 
> Oh, is there a convenient way to cross-compile for various
> architectures and run them using qemu?
> 
> So far I only tried x86/x86_64.

We have a script for that in the nolibc testsuite:

$ cd tools/testing/selftests/nolibc/
$ ./run-tests.sh -p -m user
i386:          225 test(s): 222 passed,   3 skipped,   0 failed => status: warning
x86_64:        225 test(s): 222 passed,   3 skipped,   0 failed => status: warning
arm64:         225 test(s): 222 passed,   3 skipped,   0 failed => status: warning
...

"-p" downloads a bunch of toolchains from kernel.org
"-m user" uses qemu-user. "-m system", or no "-m" at all would build a kernel and use qemu-system.
"-l" will use llvm/clang instead of gcc (only use with "-m user").

Actual tests are in nolibc-test.c.

> > 
> > [1] https://lore.kernel.org/qemu-devel/20250202-riscv-sa-restorer-v1-1-6f4bf814a1dd@t-8ch.de/
> > [0] https://lore.kernel.org/qemu-devel/mvmed060xc9.fsf@suse.de/
> > 
> > > 
> > > Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
> > > ---
> > >  tools/include/nolibc/nolibc.h |  3 +++
> > >  tools/include/nolibc/signal.h | 34 ++++++++++++++++++++++++++++++++++
> > >  2 files changed, 37 insertions(+)
> > > 
> > > diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h
> > > index c199ade200c2..29e37a755aba 100644
> > > --- a/tools/include/nolibc/nolibc.h
> > > +++ b/tools/include/nolibc/nolibc.h
> > > @@ -92,6 +92,9 @@
> > >  #ifndef _NOLIBC_H
> > >  #define _NOLIBC_H
> > >  
> > > +/* So that we do not get compatibility types/defines */
> > > +#define __KERNEL__
> > 
> > Could you explain this more?
> > 
> > The user may have included kernel UAPI headers already before including nolibc,
> > so it doesn't really work.
> 
> Maybe we should just set it in the CFLAGS directly then?

We also don't control the CFLAGS the user is using.

> Honestly, I am not entirely sure how you are supposed to do it
> correctly. The thing is, if I do not set __KERNEL__, then I get the old
> compatibility defines and types from asm/signal.h.
> 
> And, I do not see an alternative way. It would not be safe to avoid the
> include entirely and if you try that you are also missing the
> SA_RESTORER define for the proper "struct sigaction" definition to be
> correct.
> 
> The best alternative I see would be copying the proper definitions into
> the architecture specific header. That would also be ugly, as one would
> need to do a "struct sigaction" -> "struct nolibc_rt_sigaction"
> conversion internally. But, that would have the advantage that nolibc
> works outside of the kernel tree.

I think we need to do something like this.
Luckily the real mess seems to be only on x86.

> Even if all this is ugly, I would prefer that over using the
> compatibility sigaction syscall instead of rt_sigaction.

As an alternative, you are not forced to use nolibc for the KUnit UAPI
framework. You can depend on CONFIG_CC_CAN_LINK_STATIC=y and use "-static" for
the toolchains "real" libc.
Not that I want to discourage you from contributing to nolibc, though.

> > > +
> > >  #include "std.h"
> > >  #include "arch.h"
> > >  #include "types.h"
> > > diff --git a/tools/include/nolibc/signal.h b/tools/include/nolibc/signal.h
> > > index ac13e53ac31d..fa52119e577f 100644
> > > --- a/tools/include/nolibc/signal.h
> > > +++ b/tools/include/nolibc/signal.h
> > > @@ -14,6 +14,7 @@
> > >  #include "arch.h"
> > >  #include "types.h"
> > >  #include "sys.h"
> > > +#include <linux/signal.h>
> > >  
> > >  /* This one is not marked static as it's needed by libgcc for divide by zero */
> > >  int raise(int signal);
> > > @@ -23,4 +24,37 @@ int raise(int signal)
> > >  	return sys_kill(sys_getpid(), signal);
> > >  }
> > >  
> > > +/*
> > > + * sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
> > > + */
> > > +
> > > +#ifdef SA_RESTORER
> > > +__attribute__((naked))
> > 
> > __attribute__((naked)) is not supported everywhere.
> 
> One can just drop it. It just felt it was cleaner as we really just
> want to set the register and do the syscall without modifying the
> stack.

If it works without, also good.
If you want you can also use __nolibc_has_attribute(naked) from compiler.h.

<snip>



More information about the linux-um mailing list