Posts tagged with “infra”

Wifi card vanishing from the PCIe bus? Stop rebooting, make it self-heal

On a Toshiba CB35-3340 (Bay Trail Chromebook running MX Linux / Debian 13 on MrChromebox firmware), the internal Intel Wireless 7260 disappears every few hours. The SSID list goes empty, every scan fails with -EIO, and toggling wifi does nothing. Only a reboot brought it back.

The giveaway is in the kernel log:

iwlwifi 0000:01:00.0: iwlwifi device memory mapped registers:
iwlwifi 0000:01:00.0: 00000000: ffffffff ffffffff ffffffff ffffffff
WARNING: ... __iwl_trans_pcie_grab_nic_access+0x14c/0x150 [iwlwifi]
iwlwifi 0000:01:00.0: Error sending STATISTICS_CMD: enqueue_hcmd failed: -5

MMIO reads returning all-ones means the device is off the bus, not merely confused. That is why modprobe -r iwlwifi && modprobe iwlwifi fails with Could not load the [0] uCode section — there is nothing there to load firmware into.

Two things fix the recovery path. First, let the driver admit the device is gone:

…more

`ls` says the group has rwx, but access is denied — that's the ACL mask lying to you

I wanted a second local account to read /home/davidw. The user was already in group davidw, and ls looked like it should just work:

$ ls -ld /home/davidw
drwxrwx---+ 272 davidw davidw 16384 Aug 19 16:56 /home/davidw

Group davidw has rwx, right there in the middle. Except every access failed:

$ sudo -u desk ls /home/davidw
ls: cannot open directory '/home/davidw': Permission denied

The + at the end of the mode string is the tell. Once a file has a POSIX ACL, the middle triad printed by ls stops being the group permission and becomes the ACL mask — a ceiling on what every named user, named group, and the owning group may get. The real group entry is only visible via getfacl:

$ getfacl -p /home/davidw
user::rwx
user:libvirt-qemu:--x
group::---          <-- the actual group permission: nothing
mask::rwx           <-- this is what ls printed as "rwx"
other::---

So the directory was 700 all along. Someone (libvirt, in my case) added user:libvirt-qemu:--x at some point, and adding any named entry forces a mask into existence — set wide enough to cover that entry. ls dutifully displayed the mask, and it looked exactly like group access.

The mask cuts both ways: it can also revoke access that getfacl seems to grant. An entry of user:desk:rwx under mask::r-x yields read-only — getfacl marks it for you:

user:desk:rwx                   #effective:r-x

Two consequences worth internalizing. First, on any path with a +, getfacl is the only source of truth; don't reason from ls. Second, chmod g+rx on an ACL'd file doesn't set the group permission — it sets the mask, which is almost never what you meant. Grant access with a named entry instead, which is narrower and trivially reversible:

sudo setfacl -m u:desk:rwx /home/davidw   # grant
sudo setfacl -x u:desk     /home/davidw   # revert

One unrelated snag if you're doing this to share a checkout: git will refuse the now-reachable repos with detected dubious ownership in repository, because they're owned by a different uid. Fix it per-user, not with sudo:

sudo -u desk git config --global --add safe.directory '*'

Black screen when you RDP into your own Linux desktop? Give the console to a second user

Log in at the physical console, then RDP in as the same user, and you get a black screen. Worse, unlike Windows, the remote connection can't kick the console session — so any machine you walked away from while logged in is a machine you can't reach.

Neither is really an RDP problem, and one trick fixes both: create a second Unix account that owns the console.

sudo adduser desk

desk logs in at the display manager and holds the physical machine. Your real user never logs in locally at all — its desktop exists only as an xrdp session. When you're sitting at the machine, desk connects to it over loopback:

xfreerdp3 /v:127.0.0.1 /u:youruser +clipboard /multimon

Now every client is equal. Connect from a laptop on the other side of the world and it takes over the same session your local xfreerdp was showing; the local one just exits and desk's desktop is still sitting there underneath. Don't wrap that command in an auto-reconnect loop, or the machine at home will keep stealing the session back and you'll never get in from outside.

The black screen was never about RDP — it was one user running two concurrent desktop sessions, colliding on all the per-user singletons: the session D-Bus, xfce4-session, ibus, gvfs. The second session's window manager never comes up. Two different uids have none of that.

The takeover failure is a separate mechanism. "Taking over" is really xrdp-sesman reconnecting you to a session in its own table. A console session started by lightdm was never in that table, so nothing can ever reattach to it — which is also why a second RDP client can kick the first: those two are the same session.

…more

GNU tar treats `Temp\2` as octal escape on Windows Git Bash

mktemp -d on Windows Git Bash returns a path like C:\Users\you\AppData\Local\Temp\2/tmp.XXX. The 2 after Temp\ is not a separator — GNU tar reads it as the start of an octal escape (\2 → \002), so any tar -C <that-path> silently rewrites the destination to a non-existent path and the extract aborts with Cannot open: No such file or directory.

The fix is to stop passing the bad path as an argument at all:

# Wrong — passes $dst as -C argument, tar mangles the backslashes
tar -xf archive.tar.gz -C "${dst}"

# Right — cd into it first, reference files by basename
( cd "${dst}" && tar -xf archive.tar.gz )

This is the same shape as --force-local, the other GNU-tar-on-Windows gotcha: GNU tar sees the leading C: of a Windows path and reads it as host:spec for a remote archive. --force-local only fixes the second one; only cd-ing into the destination fixes the first.

How a Baton test killed every tmux session with `kill(-1)`

A desktop restart can look like an XRDP or systemd problem. In this incident, the real culprit was a Rust test for Baton: it accidentally broadcast SIGTERM to every process owned by the test user.

The audit record showed:

proctitle=kill -TERM -1072950
syscall=kill ... a0=0xffffffff a1=SIGTERM
ppid=1072584 ... comm=kill exe=/usr/bin/kill

The parent process was named baton-5b9d31243. That is a cargo test binary under target/debug/deps, not a resident Baton service. The test was exercising max-duration handling with a sleep 5 child, so Baton really was only active because an agent was running tests on the Baton project.

The code intended to signal a process group:

kill -TERM -1234

On Linux, procps parses the negative group ID as another option unless the option list is terminated. The resulting syscall is kill(-1, SIGTERM), which signals every process the caller is allowed to signal. That killed the desktop session, kitty, browsers, the systemd user manager, and tmux sessions. mat-keeper could not protect itself because it ran as the same user.

The safe form is:

kill -TERM -- -1234

The fix was applied to both the Rust Baton implementation and my-ai-team's shell Baton transport, including test cleanup paths. The RDP connection switch was a coincidence in the timeline; it did not directly invoke Baton. Full Baton tests and the relevant my-ai-team regressions pass with the corrected argument handling.