diff mbox series

[pseudo,3/3] makewrappers: Enable a new efault option

Message ID 20260113231729.2698563-3-richard.purdie@linuxfoundation.org
State New
Headers show
Series [pseudo,1/3] test-syscall: Add a syscall test | expand

Commit Message

Richard Purdie Jan. 13, 2026, 11:17 p.m. UTC
From: "mark.hatle" <mark.hatle@kernel.crashing.org>

See Yocto Project Bugzilla 16075.

On Linux, some functions will return EFAULT if certain paths are NULL vs
empty.  RUST specifically uses this Linux specific behavior as an
optimization to detect if the statx function is available.

In my opinion, this is a horrible idea, even though the man page for
Linux/glibc says EFAULT is returned.  Looking through the call code
the EFAULT happens to occur when the kernel syscall attempts to copy
the path from userspace to kernel memory and then faults.  Relying on
this (posix) undefined behavior is really bad practice, but we have to
work with RUST and other tools.

Signed-off-by: mark.hatle <mark.hatle@kernel.crashing.org>
---
 makewrappers                   | 10 ++++++++++
 ports/linux/statx/wrapfuncs.in |  2 +-
 2 files changed, 11 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/makewrappers b/makewrappers
index 0d73cc1..154b489 100755
--- a/makewrappers
+++ b/makewrappers
@@ -245,6 +245,8 @@  class Function:
         self.async_skip = None
         # used for the copyright date when creating stub functions
         self.date = datetime.date.today().year
+        # Used to define pointers that should EFAULT if null
+        self.efault = None
     
         function, comments = line.split(';')
         comment = re.search(r'/\* *(.*) *\*/', comments)
@@ -392,6 +394,14 @@  class Function:
                     "asm(\"\" : \"+r\"(%s));"
                     "if (%s && !*%s && (flags & AT_EMPTY_PATH))\n"
                     "\t\t\tflags |= AT_SYMLINK_NOFOLLOW;" % (path, path, path))
+            if self.efault and path in self.efault.split('|'):
+                fix_paths.append(
+                    # Emulate EFAULT when path is null
+                    "if (%s == NULL) {\n"
+                    "\t\t\terrno = EFAULT;\n"
+                    "\t\t\trc = -1;\n"
+                    "\t\t\t%s\n"
+                    "\t\t}\n" % (path, self.rc_return()))
             fix_paths.append(
                 "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
                 (path, prefix, self.dirfd, path, self.flags))
diff --git a/ports/linux/statx/wrapfuncs.in b/ports/linux/statx/wrapfuncs.in
index 168234f..a81fb91 100644
--- a/ports/linux/statx/wrapfuncs.in
+++ b/ports/linux/statx/wrapfuncs.in
@@ -1 +1 @@ 
-int statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf);
+int statx(int dirfd, const char *path, int flags, unsigned int mask, struct statx *statxbuf); /* efault=path */