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 <noreply@anthropic.com>
This commit is contained in:
Claude Bot
2026-01-19 22:00:53 +00:00
parent 716801e92d
commit 560713ec23

View File

@@ -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.