Bug 420906 - missing syscall wrapper for clone3 (435)
Summary: missing syscall wrapper for clone3 (435)
Status: ASSIGNED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: unspecified
Platform: Debian unstable Linux
: NOR normal
Target Milestone: ---
Assignee: Mark Wielaard
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-05-02 16:05 UTC by Nick Black
Modified: 2023-10-12 15:52 UTC (History)
5 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Make clone3 on linux ENOSYS (5.99 KB, text/plain)
2021-07-21 11:55 UTC, Mark Wielaard
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Nick Black 2020-05-02 16:05:13 UTC
There's not yet a syscall handler for amd64 435 "clone3()", introduced in Linux 5.3.

STEPS TO REPRODUCE
1. Run a program making use of the clone3() system call.

OBSERVED RESULT
--4132784-- WARNING: unhandled amd64-linux syscall: 435
--4132784-- You may be able to write your own handler.
--4132784-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
--4132784-- Nevertheless we consider this a bug.  Please report
--4132784-- it at http://valgrind.org/support/bug_reports.html.

EXPECTED RESULT
No such output

SOFTWARE/OS VERSIONS
Linux, 5.6.8, Debian Unstable GLIBC 2.30-4

ADDITIONAL INFORMATION

I can probably beat out a handler for this without much trouble (I've got a few others in Valgrind), but wanted to get the bug reported.
Comment 1 Tom Hughes 2020-05-02 16:34:25 UTC
Actually clone is very special and much more complicated than other system calls.

I did look at this because I was expecting somebody to ask for it and it's going to need a bit of work to refactor things to avoid duplicating all the code - the existing helper functions used by clone/clone2 likely need to be reworked to use the new args structure and then have clone/clone pass it a faked up structure or something.
Comment 2 Nick Black 2020-05-04 12:00:46 UTC
I'll leave it to you, then!
Comment 3 Florian Weimer 2021-07-20 15:02:47 UTC
glibc 2.34 will issue clone3 system calls and fall back to clone if clone3 fails.
Comment 4 Florian Weimer 2021-07-20 15:13:06 UTC
To reproduce, you can use Fedora rawhide (or 34) and install a glibc build on top of it. https://koji.fedoraproject.org/koji/buildinfo?buildID=1782185 or any build later than glibc-2.33.9000-44.fc35 will do. Building glibc from upstream sources will of course work as well.

It is simple to enough to reproduce using Python:

>>> import threading
>>> threading.Thread(None, lambda: print("Thread is running")).start()
--3019-- WARNING: unhandled amd64-linux syscall: 435
--3019-- You may be able to write your own handler.
--3019-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
--3019-- Nevertheless we consider this a bug.  Please report
--3019-- it at http://valgrind.org/support/bug_reports.html.
Thread is running

So things just work (as expected), except for the annoying warning.

If you build glibc from upstream sources, you can get to a Python prompt with the just-built glibc like this (without installing):

git clone --depth 1 https://sourceware.org/git/glibc.git
cd glibc
mkdir build
cd build
../configure --prefix=/usr
make -j`nproc`
bash testrun.sh --tool=valgrind /usr/bin/python3

A valgrind binary needs to be on PATH for this.
Comment 5 Mark Wielaard 2021-07-21 09:59:37 UTC
(In reply to Florian Weimer from comment #4)
> To reproduce, you can use Fedora rawhide (or 34) and install a glibc build
> on top of it. https://koji.fedoraproject.org/koji/buildinfo?buildID=1782185
> or any build later than glibc-2.33.9000-44.fc35 will do. Building glibc from
> upstream sources will of course work as well.
> 
> It is simple to enough to reproduce using Python:
> 
> >>> import threading
> >>> threading.Thread(None, lambda: print("Thread is running")).start()
> --3019-- WARNING: unhandled amd64-linux syscall: 435
> --3019-- You may be able to write your own handler.
> --3019-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
> --3019-- Nevertheless we consider this a bug.  Please report
> --3019-- it at http://valgrind.org/support/bug_reports.html.
> Thread is running
> 
> So things just work (as expected), except for the annoying warning.

valgrind is loosing control over the cloned thread, so it is not just an annoying warning.

The quickest solution/workaround would be to explicitly ENOSYS clone3 (without warning) so that glibc falls back to clone.
Comment 6 Mark Wielaard 2021-07-21 11:55:14 UTC
Created attachment 140238 [details]
Make clone3 on linux ENOSYS

It is also breaking a ton of regtest tests. Currently testing a patch that makes clone3 simply produce ENOSYS through sys_ni_syscall.
Comment 7 Mark Wielaard 2021-09-27 09:01:45 UTC
(In reply to Mark Wielaard from comment #6)
> Created attachment 140238 [details]
> Make clone3 on linux ENOSYS
> 
> It is also breaking a ton of regtest tests. Currently testing a patch that
> makes clone3 simply produce ENOSYS through sys_ni_syscall.

This was pushed as:

commit 52ed51fc35f8a6148c2940eb46932b02dd3b9b23
Author: Mark Wielaard <mark@klomp.org>
Date:   Wed Jul 21 19:53:13 2021 +0200

    Generate a ENOSYS (sys_ni_syscall) for clone3 on all linux arches
    
    glibc 2.34 will try to use clone3 first before falling back to
    the clone syscall. So implement clone3 as sys_ni_syscall which
    simply return ENOSYS without producing a warning.
    
    https://bugs.kde.org/show_bug.cgi?id=439590

And makes at least glibc fall back to clone.
Comment 8 Martin Koller 2021-10-08 15:47:42 UTC
tried this with my application. The previous error is no longer reported, however valgrind still stops with:

vex amd64->IR: unhandled instruction bytes: 0x37 0x48 0x83 0xF8 0x2E 0xF 0x84 0x17 0xFF 0xFF
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==19360== valgrind: Unrecognised instruction at address 0x2bf6ede1.
==19360==    at 0x2BF6EDE1: ??? (in /memfd:sljit (deleted))
==19360==    by 0x3766F437: ???
....
==19360== Either way, Valgrind will now raise a SIGILL signal which will
==19360== probably kill your program.
==19360== 
==19360== Process terminating with default action of signal 4 (SIGILL): dumping core
==19360==  Illegal opcode at address 0x2BF6EDE1
==19360==    at 0x2BF6EDE1: ??? (in /memfd:sljit (deleted))
==19360==    by 0x3766F437: ???