From 560713ec236e404da5e4a4e4cc9933ada67bbe5c Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Mon, 19 Jan 2026 22:00:53 +0000 Subject: [PATCH] fix(upgrade): restore SELinux context after binary move On SELinux-enabled systems, when `bun upgrade` moves the new binary from a temp directory to the final location (e.g., /usr/local/bin), the file retains the SELinux context from the source location. This causes permission denials for unprivileged users. This fix runs `restorecon` on the upgraded binary after the move completes, which restores the proper SELinux context for the target directory (e.g., bin_t for /usr/local/bin). The fix is best-effort: it only runs on Linux, only if restorecon is available in PATH, and silently ignores any errors. Fixes #24171 Co-Authored-By: Claude Opus 4.5 --- src/cli/upgrade_command.zig | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig index e119f7f0a4..76155f23a0 100644 --- a/src/cli/upgrade_command.zig +++ b/src/cli/upgrade_command.zig @@ -812,6 +812,29 @@ pub const UpgradeCommand = struct { ); Global.exit(1); }; + + // On Linux, restore SELinux context for the binary if SELinux is enabled. + // When moving files across filesystems (e.g., from temp directory to /usr/local/bin), + // the file retains the SELinux context from the source location. + // This causes permission denials for unprivileged users when bun is in a shared directory. + if (comptime Environment.isLinux) { + var restorecon_path_buf: bun.PathBuffer = undefined; + if (which(&restorecon_path_buf, env_loader.map.get("PATH") orelse "", filesystem.top_level_dir, "restorecon")) |restorecon_exe| { + var restorecon_argv = [_]string{ + bun.asByteSlice(restorecon_exe), + destination_executable, + }; + + var restorecon_process = std.process.Child.init(&restorecon_argv, ctx.allocator); + restorecon_process.stdin_behavior = .Ignore; + restorecon_process.stdout_behavior = .Ignore; + restorecon_process.stderr_behavior = .Ignore; + + // Ignore errors - SELinux may not be enforcing, or restorecon may fail for other reasons. + // The upgrade itself succeeded, so we don't want to fail here. + _ = restorecon_process.spawnAndWait() catch {}; + } + } } // Ensure completions are up to date.