diff mbox series

[pseudo] makewrappers: Fix EFAULT implementation

Message ID 1768411296-19597-1-git-send-email-mark.hatle@kernel.crashing.org
State New
Headers show
Series [pseudo] makewrappers: Fix EFAULT implementation | expand

Commit Message

Mark Hatle Jan. 14, 2026, 5:21 p.m. UTC
From: "mark.hatle" <mark.hatle@kernel.crashing.org>

A bug was discovered in the makewrappers change in commit
9ce8c09980af23ebd4ebf072010469882d0459a6.

If EFAULT was returned, it would exist with signals blocked and the
function lock still held.  This would eventually deaadlock in certain
use-cases.

The change introduces a quick path exit to the makewrappers and
does a 'goto' to this quick exit in the case of the EFAULT.

A seperate issue was identified where the EFAULT code could try to
set a return code in a void function.  Fix this by using rc_decl.

Signed-off-by: mark.hatle <mark.hatle@kernel.crashing.org>
---
 makewrappers          |  6 +++---
 templates/wrapfuncs.c |  2 ++
 test/test-statx.c     | 19 ++++++++++++++++++-
 3 files changed, 23 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/makewrappers b/makewrappers
index 154b489..c9f6ad5 100755
--- a/makewrappers
+++ b/makewrappers
@@ -399,9 +399,9 @@  class Function:
                     # 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()))
+                    "\t\t\t%s -1;\n"
+                    "\t\t\tgoto quick_exit;\n"
+                    "\t\t}\n" % (path, self.rc_assign()))
             fix_paths.append(
                 "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
                 (path, prefix, self.dirfd, path, self.flags))
diff --git a/templates/wrapfuncs.c b/templates/wrapfuncs.c
index 93bb671..e925b6e 100644
--- a/templates/wrapfuncs.c
+++ b/templates/wrapfuncs.c
@@ -71,6 +71,8 @@  ${maybe_async_skip}
 		}
 	}
 	${variadic_end}
+quick_exit:
+	__attribute__((unused));
 	save_errno = errno;
 	pseudo_droplock();
 	sigprocmask(SIG_SETMASK, &saved, NULL);
diff --git a/test/test-statx.c b/test/test-statx.c
index 06d86af..3ea176b 100644
--- a/test/test-statx.c
+++ b/test/test-statx.c
@@ -8,13 +8,30 @@ 
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <errno.h>
 
 // Passing a null pointer is the test scenario
 #pragma GCC diagnostic ignored "-Wnonnull"
 
-int main(void) {
+int statx_test() {
     if (statx(0, NULL, 0, 0, NULL) != -1) {
         return 1;
     }
+    if (errno != EFAULT) {
+        return 2;
+    }
+    return 0;
+}
+
+/* We run this multiple times to ensure that pseudo does not deadlock */
+int main(void) {
+    int rc = 0;
+
+    for (int i = 0 ; i < 5 ; i++) {
+        rc = statx_test();
+        if (rc != 0)
+            return rc;
+    }
+
     return 0;
 }