wren-linux / parts / hidepid.sh
#!/bin/bash
# Programs of other users hidden from each other: /proc is mounted with hidepid=invisible, so a
# user sees only its own processes. Without it, every sandbox user (the sandboxed browsers,
# Claude's own user, the VMs' helpers) can read the command line of every program on the
# computer: which sites you have profiles for, which files you opened, what you typed after a
# command. Root still sees everything, and so does the group wren-proc, which holds what the
# system itself needs to: systemd-logind and polkit (they ask who owns a session and a program).
# Side effects: ps, top and pgrep show only your own programs, as does a program you start; use
# sudo to look further. A sandbox still sees all of its own.
# It applies from the next boot on, every boot (a service that remounts /proc before logind starts:
# systemd, tried for real, makes no mount unit from an /etc/fstab line for /proc, so a line there
# would do nothing). Not on a running desktop: closing /proc and restarting logind under sway
# takes sway's seat from it, so nothing is remounted or restarted until the reboot.
# Usage: bash hidepid.sh [--remove]
# status: file:/etc/systemd/system/wren-hidepid.service
. "$(dirname -- "${BASH_SOURCE[0]}")/../lib.sh"
need_user
GROUP=wren-proc
UNIT=/etc/systemd/system/wren-hidepid.service
MARK='# Written by Wren Linux parts/hidepid.sh'
# The services that must still see everyone's programs
UNITS=(systemd-logind polkit)
DROPIN=wren-hidepid.conf
if [ "${1:-}" = --remove ]; then
sudo systemctl disable wren-hidepid.service >/dev/null 2>&1 || true
sudo rm -f "$UNIT"
for u in "${UNITS[@]}"; do sudo rm -f "/etc/systemd/system/$u.service.d/$DROPIN"; done
sudo systemctl daemon-reload || true
sudo mount -o remount,hidepid=off,gid=0 /proc 2>/dev/null || true
if getent group "$GROUP" >/dev/null; then sudo groupdel "$GROUP" || true; fi
note "Everyone sees every program again, now."
exit
fi
say "Programs of other users, hidden"
getent group "$GROUP" >/dev/null || sudo groupadd --system "$GROUP"
gid=$(getent group "$GROUP" | cut -d: -f3)
[[ $gid =~ ^[0-9]+$ ]] || die "couldn't find the number of the group $GROUP."
# The services first: if /proc were closed to them they couldn't work out who you are. Both,
# always: polkit may not be here yet (network-manager.sh and usb.sh install it, after this part),
# and a drop-in waiting for a service that comes later applies when it does. Written only when
# polkit was already here, it was skipped on a fresh install, and polkit then couldn't see
# your programs.
for u in "${UNITS[@]}"; do
sudo install -d -o root -g root -m 0755 "/etc/systemd/system/$u.service.d"
printf '%s\n' "$MARK" '[Service]' "SupplementaryGroups=$GROUP" |
sudo tee "/etc/systemd/system/$u.service.d/$DROPIN" >/dev/null
done
sudo systemctl daemon-reload
# At every boot, early, before anything logs in: /proc remounted (the numbers, not the name:
# the kernel takes only the number). Before logind, which already has the group.
printf '%s\n' "$MARK" '[Unit]' "Description=Hide each user's programs from the others (Wren Linux)" \
'DefaultDependencies=no' 'After=systemd-remount-fs.service' 'Before=sysinit.target systemd-logind.service' '' \
'[Service]' 'Type=oneshot' 'RemainAfterExit=yes' \
"ExecStart=/usr/bin/mount -o remount,hidepid=invisible,gid=$gid /proc" '' \
'[Install]' 'WantedBy=sysinit.target' | sudo tee "$UNIT" >/dev/null
sudo systemctl daemon-reload
sudo systemctl enable wren-hidepid.service >/dev/null 2>&1 || warn "Couldn't enable $UNIT: it won't apply at boot."
# Not now. A restart of systemd-logind under a running desktop takes sway's seat from it (it
# crashed on the owner's laptop, the moment this script finished), and closing /proc to a logind
# that doesn't yet hold the group would blind it. At the next boot the service above runs before
# logind starts, and logind starts with the group: the one safe order.
note "Done. Programs of other users are hidden from the next boot on: restart this computer once."