fix(host): longshot_env.txt can't set HOS_CONTROL_PEER_SID #911

Open
dyst wants to merge 1 commit from dyst/Longshot:fix/env-file-peer-sid into main
Member

Type: fix · Risk: low · Tested on: Windows 11, game-free checks; the host file built for Windows (llvm-mingw) and Linux (gcc) · Needs: none

Why

Another Windows user on the same PC could be let into the game's control pipe through a shared longshot_env.txt. HOS_CONTROL_PEER_SID (#544) gives one more account read and write on the control bridge's pipe, enough to steer the game and, with HOS_CONTROL_MEM, read and write its memory. longshot_env.txt is the file players pass around, and it could set that switch, so a file from someone else could name their account. This keeps the switch to the environment the game is started with, where the Test Farm's agent sets it.

How to reproduce

Seen on: Windows 11, any GPU (found reading the code; no report)
Settings and switches: HOS_CONTROL set (the control bridge on); HOS_CONTROL_PEER_SID not set in the environment
Steps: put HOS_CONTROL_PEER_SID=<another local user's SID> in longshot_env.txt beside the game and start it
Expected: the line left out, as longshot_env.txt leaves out HOS_ENV_FILE and the switches that write files; the pipe the game user's alone
Actual: on main the line is taken, and the bridge logs "control: the pipe lets in HOS_CONTROL_PEER_SID's account too"

What changed

longshot_env.txt no longer sets HOS_CONTROL_PEER_SID: the line is left out and logged like the other refused ones. The switch still works from the environment the game starts with, and from a file HOS_ENV_FILE names (a test run's own file, which sets anything).

  • host: env_line_allowed in host/hos_main.c refuses HOS_CONTROL_PEER_SID, next to HOS_ENV_FILE and SDL_DYNAMIC_API; the comment above load_longshot_env's rules names it.
  • tests: tests/test_env_file.py: the player's file sets HOS_CONTROL_PEER_SID=... and the check wants it unset; then with the switch in the environment the game started with, load_longshot_env keeps the environment's value.
  • docs: docs/control.md (Security, HOS_CONTROL_PEER_SID) and docs/development.md (the bridge's paragraph): set it in the environment, longshot_env.txt leaves it out.

Measurements

Verdict: passes: the player's file no longer sets HOS_CONTROL_PEER_SID and the environment's value is kept; the same check fails on main, where the file's line is taken. Nothing to time (a check of which lines the file sets).

Hardware: Ryzen 9 3900X, 64 GB, Windows 11 (no game run: a game-free check)
Scene: none: game-free. env_line_allowed and load_longshot_env cut out of host/hos_main.c and run with the check's files
Method: tests/test_env_file.py (Builder's llvm-mingw clang) on this branch, and the same check against main's host/hos_main.c (main's file in a scratch tree with this branch's test)
How to reproduce: python -I -B tests/test_env_file.py --cc clang; for main, the same with main's host/hos_main.c

Before: main @ f637b42d After: this PR @ 0b156278
HOS_CONTROL_PEER_SID from the player's longshot_env.txt taken left out
HOS_CONTROL_PEER_SID from the environment kept kept
tests/test_env_file.py fails passes
main @ f637b42d: FAIL:117 is("HOS_CONTROL_PEER_SID", NULL)
this PR: env: longshot_env.txt: HOS_CONTROL_PEER_SID left out (only the game's switches, and no paths, are taken from it)
this PR: PASS: HOS_ENV_FILE replaces longshot_env.txt; unset or empty reads it as before; the player's file sets only the game's switches, never HOS_CONTROL_PEER_SID; the environment goes over the file

Flags and settings

One switch changes where it may be set: HOS_CONTROL_PEER_SID is no longer taken from longshot_env.txt.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
HOS_CONTROL_PEER_SID One more local user account let into the control bridge's pipe (Windows) taken from the environment, HOS_ENV_FILE's file or longshot_env.txt taken from the environment or HOS_ENV_FILE's file only a longshot_env.txt line for it is left out and logged Helps: a shared file can't open the pipe to another account. Doesn't change: the Test Farm's agent, which sets it in the environment Set it in the environment, unset by default (documented in docs/control.md and docs/development.md)

Testing

Tested: on this branch (0b156278, on main @ f637b42d), Windows with the Builder's llvm-mingw clang (6 at once): the 45 checks that read this diff (the tests that name a changed file, test_env_file among them), not the whole suite: 36 passed, 9 failed, each also failing on main: test_crash_dialog, test_oot_state_tap, test_vk_pgo, test_walk_key in the full run on main @ 1310ecc6; test_driver_cache_folder, test_pipeline_tour, test_udmabuf_warning, test_vk_occlusion_queries on main @ 7bacf846; test_log_open_failure on main @ f637b42d (run there alone: its fixture's fcntl is undeclared with this compiler). tests/test_env_file.py fails on main's host/hos_main.c and passes here (Measurements). host/hos_main.c compiled to an object for Windows (llvm-mingw clang, x86_64-w64-mingw32) and for Linux (gcc, Docker python:3.12, with host/posix), with the runtime headers a lift makes (a64.h, a64_suyu.h, a64_fpx.h) copied from a local work folder: both clean.

Not tested: in the game (the change is one refused name in the file's allow-list, which the check runs as it is); the whole game build on Linux.

Must be tested: None

Risks

What could break: someone who set HOS_CONTROL_PEER_SID in longshot_env.txt (none known: the Test Farm's agent sets it in the environment) now has the pipe the game user's alone, with the line logged as left out; setting it in the environment restores it. With #62 (one list of the switches, host/switches.def): no textual conflict (the two merge cleanly: this change sits apart from the table #62 replaces), but #62 lists HOS_CONTROL_PEER_SID as GAME; whichever merges second should mark it LOCAL there, one line, so the list says what the allow-list does.

Turning it off: set the switch in the environment instead; reverting the commit brings the old behaviour back.

Compatibility: Nothing changes for a player: saves, longshot_options.ini, the caches and the vk ABI (MKWVK_API_VERSION) are untouched; only a longshot_env.txt line for this switch is now left out.

Issues

See #544 (the switch).

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.
  • Docs updated.

🤖 Generated with Claude Code

**Type:** fix · **Risk:** low · **Tested on:** Windows 11, game-free checks; the host file built for Windows (llvm-mingw) and Linux (gcc) · **Needs:** none ## Why Another Windows user on the same PC could be let into the game's control pipe through a shared `longshot_env.txt`. `HOS_CONTROL_PEER_SID` (#544) gives one more account read and write on the control bridge's pipe, enough to steer the game and, with `HOS_CONTROL_MEM`, read and write its memory. `longshot_env.txt` is the file players pass around, and it could set that switch, so a file from someone else could name their account. This keeps the switch to the environment the game is started with, where the Test Farm's agent sets it. ## How to reproduce **Seen on:** Windows 11, any GPU (found reading the code; no report) **Settings and switches:** `HOS_CONTROL` set (the control bridge on); `HOS_CONTROL_PEER_SID` not set in the environment **Steps:** put `HOS_CONTROL_PEER_SID=<another local user's SID>` in `longshot_env.txt` beside the game and start it **Expected:** the line left out, as `longshot_env.txt` leaves out `HOS_ENV_FILE` and the switches that write files; the pipe the game user's alone **Actual:** on main the line is taken, and the bridge logs "control: the pipe lets in HOS_CONTROL_PEER_SID's account too" ## What changed `longshot_env.txt` no longer sets `HOS_CONTROL_PEER_SID`: the line is left out and logged like the other refused ones. The switch still works from the environment the game starts with, and from a file `HOS_ENV_FILE` names (a test run's own file, which sets anything). - host: `env_line_allowed` in `host/hos_main.c` refuses `HOS_CONTROL_PEER_SID`, next to `HOS_ENV_FILE` and `SDL_DYNAMIC_API`; the comment above `load_longshot_env`'s rules names it. - tests: `tests/test_env_file.py`: the player's file sets `HOS_CONTROL_PEER_SID=...` and the check wants it unset; then with the switch in the environment the game started with, `load_longshot_env` keeps the environment's value. - docs: `docs/control.md` (*Security*, `HOS_CONTROL_PEER_SID`) and `docs/development.md` (the bridge's paragraph): set it in the environment, `longshot_env.txt` leaves it out. ## Measurements **Verdict:** passes: the player's file no longer sets `HOS_CONTROL_PEER_SID` and the environment's value is kept; the same check fails on main, where the file's line is taken. Nothing to time (a check of which lines the file sets). Hardware: Ryzen 9 3900X, 64 GB, Windows 11 (no game run: a game-free check) Scene: none: game-free. `env_line_allowed` and `load_longshot_env` cut out of `host/hos_main.c` and run with the check's files Method: `tests/test_env_file.py` (Builder's llvm-mingw clang) on this branch, and the same check against main's `host/hos_main.c` (main's file in a scratch tree with this branch's test) How to reproduce: `python -I -B tests/test_env_file.py --cc clang`; for main, the same with main's `host/hos_main.c` | | Before: main @ f637b42d | After: this PR @ 0b156278 | |---|---|---| | `HOS_CONTROL_PEER_SID` from the player's `longshot_env.txt` | taken | left out | | `HOS_CONTROL_PEER_SID` from the environment | kept | kept | | `tests/test_env_file.py` | fails | passes | ``` main @ f637b42d: FAIL:117 is("HOS_CONTROL_PEER_SID", NULL) this PR: env: longshot_env.txt: HOS_CONTROL_PEER_SID left out (only the game's switches, and no paths, are taken from it) this PR: PASS: HOS_ENV_FILE replaces longshot_env.txt; unset or empty reads it as before; the player's file sets only the game's switches, never HOS_CONTROL_PEER_SID; the environment goes over the file ``` ### Flags and settings One switch changes where it may be set: `HOS_CONTROL_PEER_SID` is no longer taken from `longshot_env.txt`. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `HOS_CONTROL_PEER_SID` | One more local user account let into the control bridge's pipe (Windows) | taken from the environment, `HOS_ENV_FILE`'s file or `longshot_env.txt` | taken from the environment or `HOS_ENV_FILE`'s file only | a `longshot_env.txt` line for it is left out and logged | Helps: a shared file can't open the pipe to another account. Doesn't change: the Test Farm's agent, which sets it in the environment | Set it in the environment, unset by default (documented in docs/control.md and docs/development.md) | ## Testing **Tested:** on this branch (0b156278, on main @ f637b42d), Windows with the Builder's llvm-mingw clang (6 at once): the 45 checks that read this diff (the tests that name a changed file, `test_env_file` among them), not the whole suite: 36 passed, 9 failed, each also failing on main: `test_crash_dialog`, `test_oot_state_tap`, `test_vk_pgo`, `test_walk_key` in the full run on main @ 1310ecc6; `test_driver_cache_folder`, `test_pipeline_tour`, `test_udmabuf_warning`, `test_vk_occlusion_queries` on main @ 7bacf846; `test_log_open_failure` on main @ f637b42d (run there alone: its fixture's `fcntl` is undeclared with this compiler). `tests/test_env_file.py` fails on main's `host/hos_main.c` and passes here (Measurements). `host/hos_main.c` compiled to an object for Windows (llvm-mingw clang, `x86_64-w64-mingw32`) and for Linux (gcc, Docker `python:3.12`, with `host/posix`), with the runtime headers a lift makes (`a64.h`, `a64_suyu.h`, `a64_fpx.h`) copied from a local work folder: both clean. **Not tested:** in the game (the change is one refused name in the file's allow-list, which the check runs as it is); the whole game build on Linux. **Must be tested:** None ## Risks **What could break:** someone who set `HOS_CONTROL_PEER_SID` in `longshot_env.txt` (none known: the Test Farm's agent sets it in the environment) now has the pipe the game user's alone, with the line logged as left out; setting it in the environment restores it. With #62 (one list of the switches, `host/switches.def`): no textual conflict (the two merge cleanly: this change sits apart from the table #62 replaces), but #62 lists `HOS_CONTROL_PEER_SID` as `GAME`; whichever merges second should mark it `LOCAL` there, one line, so the list says what the allow-list does. **Turning it off:** set the switch in the environment instead; reverting the commit brings the old behaviour back. **Compatibility:** Nothing changes for a player: saves, `longshot_options.ini`, the caches and the vk ABI (`MKWVK_API_VERSION`) are untouched; only a `longshot_env.txt` line for this switch is now left out. ## Issues See #544 (the switch). ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. - [x] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(host): longshot_env.txt can't set HOS_CONTROL_PEER_SID
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 10s
PR description / Description follows the template (pull_request_target) Successful in 4s
0b1562783d
HOS_CONTROL_PEER_SID lets one more account into the control bridge's pipe
(#544). longshot_env.txt is a file players pass around, and it could set
it, so a shared file could let another user of the same PC steer the
game and read its memory over the bridge. env_line_allowed now refuses
it, as it refuses HOS_ENV_FILE; the environment the game starts with
still sets it (the Test Farm's agent does). tests/test_env_file.py: the
player's file is refused it, the environment's value is kept.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
dyst changed title from WIP: fix(host): longshot_env.txt can't set HOS_CONTROL_PEER_SID to fix(host): longshot_env.txt can't set HOS_CONTROL_PEER_SID 2026-11-15 20:17:31 +00:00
Some checks failed
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 3s
CI / Workflow lint (actionlint) (pull_request) Successful in 6s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 5s
Third-party parts / As their notes say (pull_request) Successful in 10s
PR description / Description follows the template (pull_request_target) Successful in 4s
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/env-file-peer-sid:dyst-fix/env-file-peer-sid'
git switch 'dyst-fix/env-file-peer-sid'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!911
No description provided.