Backport of the input-device name fix (PR #8129 by @acrogenesis, merged to
quattro as 9285b19d) onto the v4-0-1 release branch.
Hyprland input-device and monitor names come from USB descriptors and hyprctl
output, so they are attacker-influenceable, yet the toggle and monitor commands
interpolated them straight into hyprctl eval and into generated Lua that
Hyprland re-executes on every reload. XF86TouchpadToggle is bound with
locked = true, so a malicious USB name reached Lua execution from the lock
screen as the logged-in user, and a persisted disable made it run on every
start. Publicly reported by Jorrit Jongma / Chainfire.
The disable is no longer executable Lua anywhere. The device name is stored as
plain-text data in a *-disabled-name sidecar and read back by a packaged module,
default/hypr/disabled-input-device.lua, on every reload; the live hyprctl eval
Lua-quotes the name and rejects control characters outright. The reload loader
excludes the two legacy filenames, so a leftover generated *-disabled.lua on a
not-yet-migrated install can never be sourced as code again, and a migration
recovers the device name from it and deletes it, sanitizing installs that ran
the vulnerable version. All four monitor scripts validate an output name against
a plain-connector-name pattern before writing it as Lua, closing the same latent
pattern in the siblings, and paths.lua treats a set-but-empty XDG_STATE_HOME as
unset to match the bash side.
Clean cherry-pick: all fourteen files are byte-identical to quattro, so merging
v4-0-1 into quattro resolves without a conflict. This branch ships no leftover
*-disabled.lua template of its own -- the tracked "disabled" files are the same
two quattro has -- so the migration is the only path that has to sanitize
anything here.
test/shell passes: 192 files, including the three this adds. The toggle suite's
public-PoC case passes here, as do the monitor scripts' accept/reject cases and
the XDG path cases. test/cli passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
40 lines
1.4 KiB
Bash
40 lines
1.4 KiB
Bash
echo "Store Hyprland input-device names as data instead of generated Lua"
|
|
|
|
# omarchy-toggle-input-device used to interpolate hyprctl device names into
|
|
# hyprctl eval and a generated Lua file. Those names come from USB descriptors,
|
|
# so recover the plain device name as data and delete the generated Lua. A name
|
|
# that could have broken out of the old Lua string literal is discarded, not
|
|
# trusted. The old script wrote to ~/.local/state regardless of XDG_STATE_HOME.
|
|
toggles_dir="$HOME/.local/state/omarchy/toggles/hypr"
|
|
|
|
reapply=0
|
|
|
|
for kind in touchpad touchscreen; do
|
|
state_file="$toggles_dir/$kind-disabled.lua"
|
|
name_file="$toggles_dir/$kind-disabled-name"
|
|
|
|
[[ -f $state_file ]] || continue
|
|
|
|
if [[ ! -f $name_file && -r $state_file ]]; then
|
|
old=$(<"$state_file")
|
|
pattern='^hl\.device\(\{ name = "([^"\\[:cntrl:]]+)", enabled = false \}\)$'
|
|
if [[ $old =~ $pattern ]]; then
|
|
printf '%s\n' "${BASH_REMATCH[1]}" >"$name_file"
|
|
fi
|
|
fi
|
|
|
|
rm -f "$state_file"
|
|
|
|
if [[ -f $name_file ]]; then
|
|
reapply=1
|
|
fi
|
|
done
|
|
|
|
# The package hook reloads Hyprland before migrations run, so this session has
|
|
# already dropped the disable: the generated Lua is no longer loaded and the
|
|
# name file did not exist yet to replace it. Reload once more now that it does,
|
|
# or the device the user switched off stays on until their next login.
|
|
if (( reapply )); then
|
|
hyprctl reload >/dev/null 2>&1 || true
|
|
fi
|