Skip to content

fix: ensure exec staging dir, preferring user dirs over tmp#336

Open
jonaslb wants to merge 1 commit intoaxodotdev:mainfrom
jonaslb:executable-staging-dir
Open

fix: ensure exec staging dir, preferring user dirs over tmp#336
jonaslb wants to merge 1 commit intoaxodotdev:mainfrom
jonaslb:executable-staging-dir

Conversation

@jonaslb
Copy link

@jonaslb jonaslb commented Feb 14, 2026

Fixes #324 . Related to astral-sh/uv#17191.

As a bit extra context for the issue, /tmp is sometimes mounted noexec, as it is I believe considered "security best practice" according to CIS. So probably, most users hit by this are enterprisy. But I suppose there might be some distros out there as well.

This PR handles the issue by:

  1. Walking through a list of priorities, starting with runtime dir, cache dir and data-local dir (using directories crate that I added as dependency), and then finally TMPDIR at last as before.
  2. For each one, if it exists and we can create a subfolder, it tests if it is possible to execute from there (assuming true on non-unix). This happens by writing a small no-op script.
    • In practice we're going to mostly resolve /run/user/<uid> on Linux, $HOME/Library/Caches on MacOS, and {FOLDERID_LocalAppData} on Windows (as documented by the directories crate).
  3. Still uses the tempfile library as before for cleanup on drop

I've tested this with a script that sets up a "fake root":

#!/bin/bash -eux

ROOT=/tmp/axo-staging-check
TMPDIR=$ROOT/tmp
XDG_RUNTIME_DIR=$ROOT/runtime
XDG_CACHE_HOME=$ROOT/cache
XDG_DATA_HOME=$ROOT/data

domount() {
	sudo mkdir -p $1
	sudo mount -t tmpfs -o rw,nosuid,nodev,size=512m,$2 tmpfs $1
}
domount $TMPDIR noexec,mode=777
domount $XDG_RUNTIME_DIR exec,mode=700,uid=$(id -u),gid=$(id -g)
domount $XDG_CACHE_HOME exec,mode=775,uid=$(id -u),gid=$(id -g)
domount $XDG_DATA_HOME exec,mode=775,uid=$(id -u),gid=$(id -g)

# Cargo will use our fake TMPDIR otherwise, filling it
cargo test --no-run
# Now run test
set +e
RUST_BACKTRACE=1 \
TMPDIR=$TMPDIR \
XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \
XDG_CACHE_HOME=$XDG_CACHE_HOME \
XDG_DATA_HOME=$XDG_DATA_HOME \
cargo test -p axoupdater-cli --test integration test_upgrade -- --nocapture

# Do cleanup
# ls -la $TMPDIR $XDG_RUNTIME_DIR $XDG_CACHE_HOME $XDG_DATA_HOME
sudo umount $TMPDIR $XDG_RUNTIME_DIR $XDG_CACHE_HOME $XDG_DATA_HOME

Although it's not easy to run the tests due to rate limiting from Github. I also had to adapt the cli tests to have a fallback to the runtime dir themselves, as they each individually do the whole "download and execute" dance, which won't work with a noexec tmp either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

update fails when /tmp is mounted noexec

1 participant