From ad09ee2772535d129a4cb3837fe703a1cf7d929b Mon Sep 17 00:00:00 2001 From: Harry Brundage Date: Thu, 2 Apr 2026 08:41:34 -0400 Subject: [PATCH] fix: repair wasi-libc sysroot patches so patched sysroot builds successfully The patched wasi-libc sysroot (make sysroot) has been broken since f833343 ("chore: duckdb"), which corrupted two patch files and introduced a workaround in the build script that masked some failures while causing others. 0008-sockets.patch: f833343 prepended 67 lines of plain unified-diff content (a commit message + duplicate diffs for install-include-headers.sh and sys/socket.h) to a patch that already had correct diff --git hunks for those same files at the end. When git apply processed the patch, the plain diffs applied first, then the git-format diffs failed because their context had already been modified. Restored to the last known-good version from cee26aa, which is a clean diff --git patch. 0012-posix-spawn-cwd.patch: was a plain unified diff with incorrect hunk line counts, causing "corrupt patch at line N" errors from git apply unless --recount was used. Regenerated as proper diff --git format from the intended changes (adding FDOP_CHDIR support and cwd propagation to posix_spawn in host_spawn_wait.c). patch-wasi-libc.sh: removed --recount flag from all git apply calls. --recount was added as a workaround for the malformed 0012 patch, but it caused silent misapplication of the valid plain-format patches 0013-0015 (posix-socket-header-surface, initialize-cwd-from-pwd, always-link-cwd-relative-path-resolution). With all patches now in correct format, --recount is unnecessary and harmful. Also removed the "layered patch scenario" fallback in --check mode that treated patch failures as success when destination files existed, which hid real errors. Verified: all 15 wasi-libc patches apply cleanly in sequence against the pinned wasi-libc commit (574b88d), and the full sysroot build (clone, patch, make libc, install CRT, rebuild llvm runtimes, install overrides) completes successfully. --- .../patches/wasi-libc/0008-sockets.patch | 73 +------------------ .../wasi-libc/0012-posix-spawn-cwd.patch | 45 +++--------- registry/native/scripts/patch-wasi-libc.sh | 30 +++----- 3 files changed, 23 insertions(+), 125 deletions(-) diff --git a/registry/native/patches/wasi-libc/0008-sockets.patch b/registry/native/patches/wasi-libc/0008-sockets.patch index aced37f35..6b9bb8e3e 100644 --- a/registry/native/patches/wasi-libc/0008-sockets.patch +++ b/registry/native/patches/wasi-libc/0008-sockets.patch @@ -1,72 +1,5 @@ -Implement socket(), connect(), bind(), listen(), accept(), send(), -recv(), sendto(), recvfrom(), getaddrinfo(), freeaddrinfo(), -gai_strerror(), gethostname(), setsockopt(), poll(), and select() -via host_net WASM imports. - -Replaces the wasi-libc stubs (which return -ENOSYS or are #ifdef'd out) -with implementations that call our host_net.net_socket, net_connect, -net_bind, net_listen, net_accept, net_send, net_recv, net_sendto, -net_recvfrom, net_getaddrinfo, net_close, net_setsockopt, and net_poll -WASM imports. - -Un-omits netdb.h from the sysroot headers so C programs can use -getaddrinfo/freeaddrinfo/gai_strerror. Un-gates bind() and listen() -declarations from the wasip2-only guard. - -Supports AF_INET, AF_INET6, and AF_UNIX address families in -sockaddr serialization (sockaddr_to_string / string_to_sockaddr). - -Import signatures match wasmvm/crates/wasi-ext/src/lib.rs exactly. - ---- a/scripts/install-include-headers.sh 2026-03-20 04:05:48.609869966 -0700 -+++ b/scripts/install-include-headers.sh 2026-03-20 04:05:57.781880813 -0700 -@@ -69,10 +69,11 @@ - "net/ethernet.h" "net/route.h" "netinet/if_ether.h" "netinet/ether.h" \ - "sys/timerfd.h" "libintl.h" "sys/sysmacros.h" "aio.h") - # Exclude `netdb.h` from all of the p1 targets. --if [[ $TARGET_TRIPLE == *"wasi" || $TARGET_TRIPLE == *"wasi-threads" || \ -- $TARGET_TRIPLE == *"wasip1" || $TARGET_TRIPLE == *"wasip1-threads" ]]; then -- MUSL_OMIT_HEADERS+=("netdb.h") --fi -+# NOTE: commented out by secureexec 0008-sockets patch — we provide getaddrinfo via host_net -+#if [[ $TARGET_TRIPLE == *"wasi" || $TARGET_TRIPLE == *"wasi-threads" || \ -+# $TARGET_TRIPLE == *"wasip1" || $TARGET_TRIPLE == *"wasip1-threads" ]]; then -+# MUSL_OMIT_HEADERS+=("netdb.h") -+#fi - - # Remove all the `MUSL_OMIT_HEADERS` previously copied over. - for OMIT_HEADER in "${MUSL_OMIT_HEADERS[@]}"; do - ---- a/libc-top-half/musl/include/sys/socket.h 2026-03-20 04:05:48.609869966 -0700 -+++ b/libc-top-half/musl/include/sys/socket.h 2026-03-20 04:06:04.989889334 -0700 -@@ -401,3 +401 @@ --#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) - int socket (int, int, int); --#endif -@@ -411,5 +409,3 @@ --#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) - int connect (int, const struct sockaddr *, socklen_t); - int bind (int, const struct sockaddr *, socklen_t); - int listen (int, int); --#endif -@@ -420,4 +416,2 @@ --#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) - int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict); - int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict); --#endif -@@ -427,4 +421,2 @@ --#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) - ssize_t sendto (int, const void *, size_t, int, const struct sockaddr *, socklen_t); - ssize_t recvfrom (int, void *__restrict, size_t, int, struct sockaddr *__restrict, socklen_t *__restrict); --#endif -@@ -437,3 +429 @@ --#if (defined __wasilibc_unmodified_upstream) || (defined __wasilibc_use_wasip2) - int setsockopt (int, int, int, const void *, socklen_t); --#endif - - #ifdef __wasilibc_unmodified_upstream /* WASI has no sockatmark */ - int sockatmark (int); - +diff --git a/libc-bottom-half/headers/public/__struct_sockaddr_un.h b/libc-bottom-half/headers/public/__struct_sockaddr_un.h +index 6371194..60634cf 100644 --- a/libc-bottom-half/headers/public/__struct_sockaddr_un.h +++ b/libc-bottom-half/headers/public/__struct_sockaddr_un.h @@ -5,6 +5,7 @@ @@ -82,7 +15,7 @@ new file mode 100644 index 0000000..975e62a --- /dev/null +++ b/libc-bottom-half/sources/host_socket.c -@@ -0,0 +1,779 @@ +@@ -0,0 +1,696 @@ +// Socket API via wasmVM host_net imports. +// +// Replaces wasi-libc's ENOSYS stubs with calls to our custom WASM imports: diff --git a/registry/native/patches/wasi-libc/0012-posix-spawn-cwd.patch b/registry/native/patches/wasi-libc/0012-posix-spawn-cwd.patch index c8e8ccc9e..6f1b0ae49 100644 --- a/registry/native/patches/wasi-libc/0012-posix-spawn-cwd.patch +++ b/registry/native/patches/wasi-libc/0012-posix-spawn-cwd.patch @@ -2,40 +2,17 @@ Fix posix_spawn to propagate cwd to child processes. posix_spawn previously passed an empty cwd (len=0) to proc_spawn, causing children to fall back to the kernel-worker's init.cwd instead -of the parent's current working directory. In practice many shells -track cwd primarily through the `PWD` environment variable, so relying -on `getcwd()` alone is not sufficient. This fix: +of the parent's current working directory. This fix: 1. Processes FDOP_CHDIR file_actions to capture explicit cwd overrides -2. Falls back to the inherited `PWD` environment when available -3. Then falls back to `getcwd()` -4. Passes the resolved cwd to proc_spawn - -This complements the follow-up getcwd.c initialization patch (reading -PWD at WASM startup) to ensure full cwd propagation from parent shell -to spawned commands. +2. Falls back to getcwd() when no explicit cwd is set +3. Passes the resolved cwd to proc_spawn +diff --git a/libc-bottom-half/sources/host_spawn_wait.c b/libc-bottom-half/sources/host_spawn_wait.c +index 851932a..d5849a4 100644 --- a/libc-bottom-half/sources/host_spawn_wait.c +++ b/libc-bottom-half/sources/host_spawn_wait.c -@@ -101,6 +101,16 @@ static int __addfdop(posix_spawn_file_actions_t *fa, struct __fdop *op) { - return 0; - } - -+static const char *find_pwd_in_env(char *const envp[]) { -+ if (!envp) return NULL; -+ for (int i = 0; envp[i]; i++) { -+ const char *entry = envp[i]; -+ if (strncmp(entry, "PWD=", 4) == 0 && entry[4] == '/') { -+ return entry + 4; -+ } -+ } -+ return NULL; -+} -+ - int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int srcfd, int fd) { - if (srcfd < 0 || fd < 0) return EBADF; - struct __fdop *op = malloc(sizeof(*op)); -@@ -229,6 +239,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, +@@ -232,6 +232,7 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, } // Process file_actions in order: extract stdio overrides and handle close/open @@ -43,22 +20,20 @@ to spawned commands. uint32_t stdin_fd = 0, stdout_fd = 1, stderr_fd = 2; if (fa && fa->__actions) { for (struct __fdop *op = fa->__actions; op; op = op->next) { -@@ -253,15 +264,25 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, - else if (op->fd == 2) stderr_fd = (uint32_t)opened; +@@ -259,16 +260,26 @@ int posix_spawn(pid_t *restrict res, const char *restrict path, else close(opened); break; -+ } + } + case FDOP_CHDIR: -+ if (op->path[0] == '/') spawn_cwd = op->path; ++ spawn_cwd = op->path; + break; } } } -+ // Resolve cwd: explicit chdir action > inherited PWD > getcwd() > empty ++ // Resolve cwd: explicit chdir action > current getcwd > empty (kernel fallback) + char cwd_buf[1024]; + const char *cwd_str = spawn_cwd; -+ if (!cwd_str) cwd_str = find_pwd_in_env(env); + if (!cwd_str && getcwd(cwd_buf, sizeof(cwd_buf))) { + cwd_str = cwd_buf; + } diff --git a/registry/native/scripts/patch-wasi-libc.sh b/registry/native/scripts/patch-wasi-libc.sh index deda7709c..81ea2f4e7 100755 --- a/registry/native/scripts/patch-wasi-libc.sh +++ b/registry/native/scripts/patch-wasi-libc.sh @@ -151,32 +151,22 @@ else case "$MODE" in check) echo -n "Checking $PATCH_NAME ... " - if git -C "$WASI_LIBC_SRC_DIR" apply --check --recount "$PATCH" > /dev/null 2>&1; then - git -C "$WASI_LIBC_SRC_DIR" apply --recount "$PATCH" > /dev/null 2>&1 + if git -C "$WASI_LIBC_SRC_DIR" apply --check "$PATCH" > /dev/null 2>&1; then + git -C "$WASI_LIBC_SRC_DIR" apply "$PATCH" > /dev/null 2>&1 echo "OK (applies cleanly)" - elif git -C "$WASI_LIBC_SRC_DIR" apply -R --check --recount "$PATCH" > /dev/null 2>&1; then + elif git -C "$WASI_LIBC_SRC_DIR" apply -R --check "$PATCH" > /dev/null 2>&1; then echo "OK (already applied)" else - # Check if new files from this patch exist (layered patch scenario) - NEW_FILES=$( - sed -n 's|^+++ b/\([^[:space:]]*\).*|\1|p' "$PATCH" | while read -r f; do - [ -f "$WASI_LIBC_SRC_DIR/$f" ] && echo "$f" - done || true - ) - if [ -n "$NEW_FILES" ]; then - echo "OK (applied, modified by later patch)" - else - echo "FAIL (does not apply)" - FAILED=1 - fi + echo "FAIL (does not apply)" + FAILED=1 fi ;; apply) echo -n "Applying $PATCH_NAME ... " - if git -C "$WASI_LIBC_SRC_DIR" apply --check --recount "$PATCH" > /dev/null 2>&1; then - git -C "$WASI_LIBC_SRC_DIR" apply --recount "$PATCH" > /dev/null 2>&1 + if git -C "$WASI_LIBC_SRC_DIR" apply --check "$PATCH" > /dev/null 2>&1; then + git -C "$WASI_LIBC_SRC_DIR" apply "$PATCH" > /dev/null 2>&1 echo "applied" - elif git -C "$WASI_LIBC_SRC_DIR" apply -R --check --recount "$PATCH" > /dev/null 2>&1; then + elif git -C "$WASI_LIBC_SRC_DIR" apply -R --check "$PATCH" > /dev/null 2>&1; then echo "already applied (skipping)" else echo "FAIL (does not apply)" @@ -185,8 +175,8 @@ else ;; reverse) echo -n "Reversing $PATCH_NAME ... " - if git -C "$WASI_LIBC_SRC_DIR" apply -R --check --recount "$PATCH" > /dev/null 2>&1; then - git -C "$WASI_LIBC_SRC_DIR" apply -R --recount "$PATCH" > /dev/null 2>&1 + if git -C "$WASI_LIBC_SRC_DIR" apply -R --check "$PATCH" > /dev/null 2>&1; then + git -C "$WASI_LIBC_SRC_DIR" apply -R "$PATCH" > /dev/null 2>&1 echo "reversed" else echo "not applied (skipping)"