SteamDeckHomebrew / decky-installer

Installer for decky loader
GNU General Public License v2.0
26 stars 14 forks source link

Feature Suggestion: Password-less Reinstall/Update #5

Open eth-p opened 1 year ago

eth-p commented 1 year ago

Hi there! Thanks for the awesome work on Decky.

As someone who uses Steam's pre-release builds, I find that I'm usually stuck having to go into desktop mode to update Decky. I understand that this is a consequence of running bleeding-edge Steam client updates, but the inability to update Decky from gaming mode has been a frequent annoyance.

Unfortunately, adding the decky_installer.desktop as a non-Steam shortcut isn't a solution. For whatever reason, the sudo password prompt is unable to read Steam's OSK inputs. I came up with a solution for myself, and I thought I'd share the process as a feature suggestion.

Basically, the process involves adding an /etc/sudoers entry (via /etc/sudoers.d/x99-decky-install) which allows the deck user to run sudo without a password for a single executable. The name of the sudoers.d file is important, and must come after /etc/sudoers.d/sudo in order to take precedence over the builtin sudo group rule:

deck  ALL=(root) NOPASSWD: /root/update-decky.sh

It is critically important that the executable script is:

  1. Owned by root:root.
  2. Not world-writable.
  3. Not located under a directory that can be renamed, deleted, or moved by a non-root user. This means that it can't be stored under the user's home directory, since nothing will stop the user from mving ~/homebrew/ and moving their own executable under the no-longer-root-owned ~/homebrew/services/ its place. I chose to put the script under /root, but somewhere inside /etc would work too.

The executable script is similar to what the .desktop file does, but takes care to not allow LPE via race conditions with the download path:

#/bin/bash
set -euo pipefail
umask 0700

DOWNLOAD_URL="https://github.com/SteamDeckHomebrew/decky-installer/releases/latest/download/user_install_script.sh"

# Create a temporary download directory.
# Remove it once this script is done. 
DOWNLOAD_DIR="$(mktemp -d)"
trap 'rm -rf "$DOWNLOAD_DIR"' EXIT

# Ensure that it's owned by root, and nothing but root can change it.
# This will prevent the opportunity for LPE by replacing it after `curl` is done downloading.
chmod -R 700 "${DOWNLOAD_DIR}"
chown -R root:root "${DOWNLOAD_DIR}"

# To be extra safe, creating a temporary file within the directory.
# Can't replace files that we don't know the name of.
DOWNLOAD_FILE="$(TMPDIR="$DOWNLOAD_DIR" mktemp)"

# Download the Decky install script.
printf "\x1B[33mDownloading Decky install script...\x1B[0m\n"
curl -L -o "${DOWNLOAD_FILE}" "$DOWNLOAD_URL"

# Ask if it's okay to run the Decky install script.
installer_sha256="$(sha256sum "$DOWNLOAD_FILE" | cut -d' ' -f1)"
zenity \
    --question \
    --title="Steam Deck Tricks: Decky Installer" \
    --text="$(printf "The Decky installer has been downloaded with the SHA-256 hash \`%s\`.\n\nProceed?" "$installer_sha256")" \
    || exit 0

# Run the Decky install script.
printf "\x1B[33mRunning Decky install script...\x1B[0m\n"
bash "$DOWNLOAD_FILE"
jkluch commented 1 month ago

I followed along to this whole thing but I haven't figured out how to launch this. @eth-p can you give some inside as to how you're running this?

I tried setting /root/update-decky.sh to 755 and it's owned by root. From there I setup a non-steam game with a target of "sudo" and a launch option of /root/update-decky.sh

This works, but not from game mode. Desktop mode seems to work properly but I don't get the GUI popups in game mode it just fails silently there.