Skip to content

Repository files navigation

bolt — pure-asm screen locker

Image

Version Assembly License Platform Dependencies Binary X11

A small, fast screen locker for the CHasm (CHange to ASM) desktop suite. Two binaries:

  • bolt — pure x86_64 NASM, no libc, no toolkit. Owns the X session while it runs: creates a fullscreen override-redirect window, grabs keyboard + pointer, accepts keystrokes into a hidden buffer, draws one square per typed character.
  • bolt-auth — ~80 lines of C, suid root. Reads the password line on stdin, calls crypt() against the user's shadow entry, exits 0/1. bolt forks + pipes to it on Enter; nothing else has root.

Part of the CHasm suite alongside bare, show, glass, tile, chasm-bits and glyph.


bolt lock screen

The split keeps the audit-able privileged code small and language-boring, while the locker UI stays in the asm style of the rest of the suite.

Build

make            # both binaries
sudo make install

make install puts /usr/local/bin/bolt (mode 0755) and /usr/local/bin/bolt-auth (mode 4755, owner root, group root). The suid bit is what lets bolt-auth read /etc/shadow.

Use

/usr/local/bin/bolt

bolt reads ~/.lockrc for config (see .lockrc.example), connects to $DISPLAY, draws the lock screen, grabs input. Type your login password and hit Enter:

  • correct → bolt ungrabs and exits 0.
  • wrong → squares clear, lock screen stays up.
  • Esc clears the typed buffer; Backspace removes one byte.

Fingerprint: if /usr/bin/fprintd-verify is installed and you have an enrolled finger (fprintd-list $USER), bolt forks it as a sibling auth process at lock-start. A matching touch unlocks the screen without typing — bolt's poll(2) loop watches the fprintd child's stdout pipe, reaps the child on EOF, and unlocks if it exited 0. The password path runs in parallel; whichever signals success first wins. On unlock bolt sends SIGTERM to the fingerprint child so the reader goes cold immediately. Systems without fprintd installed silently fall through to the password-only path.

Trigger from your window manager. For tile (~/.tilerc):

bind Mod4+Ctrl+l        exec /usr/local/bin/bolt
bind Mod4+Escape        exec /usr/local/bin/bolt

Or wrap suspend so the laptop is locked before sleeping:

#!/usr/bin/env bash
/usr/local/bin/bolt &
disown
sudo systemctl suspend

For an idle-driven lock, pair with xss-lock:

xss-lock --notifier=- /usr/local/bin/bolt &

Lock screen image

bolt is intentionally dumb about graphics: it expects a single flat raw-RGB blob matching your screen geometry, mmaps it, and blits it as the background. No PNG/JPG decoder in asm, no per-frame overlay, no font rendering. You compose the entire lock screen (wallpaper + logo + tagline + whatever else) in your favourite image editor, then bake it once.

A helper script ships with the repo (chasm-bg) that bakes ALL the suite's backgrounds from one image — ~/.lockbg.rgb for the locker plus ~/.framebg for frame's compositor and the bolt-greet greeter (scale-to-cover, centre-crop, panel resolution):

./chasm-bg ~/wallpaper.png    # → ~/.lockbg.rgb + ~/.framebg

Then point ~/.lockrc at it:

bg_color   = 0x000000
bg_image   = /home/you/.lockbg.rgb
accent     = 0xffffff      # password-square colour
text_color = 0xffffff

If the file is missing or the wrong size bolt falls back to bg_color.

Configuration

~/.lockrc is line-based key = value. See .lockrc.example for the full list:

bg_color   = 0x000000                          # ARGB hex; 0xff alpha forced
bg_image   = /home/you/.lockbg.rgb             # raw RGB blob (W*H*3 bytes)
accent     = 0xffffff                          # password-square colour
text_color = 0xffffff                          # tagline / fallback text
tagline    = Make it Simple                    # only used when no bg_image
font       = -*-fixed-bold-r-normal-*-20-*-*-*-*-*-*-*

The tagline and font keys are only used when bolt falls back to its built-in render path (no bg_image, or an image that failed to load). With a bg_image, bolt skips text rendering entirely — the tagline lives in your baked PNG.

Security model

  • bolt itself never has elevated privileges. It runs entirely as your user.
  • bolt-auth is suid root; that is the only way it can read /etc/shadow. Its job is one fixed task: read a password from stdin, return 0/1. It calls mlock() on the password buffer, zeroes it before returning, and closes inherited fds 3+ before reading.
  • The password is wiped from bolt's memory the moment the helper returns, success or fail.
  • bolt calls XGrabKeyboard + XGrabPointer in a retry loop; if another client already holds the grabs (another locker, an unresponsive app), it bails out with exit 2 rather than half-locking the session.

bolt-greet — the greeter (v0.1.15)

A third binary: bolt-greet, a graphical session chooser that replaces the display manager. Pure asm like bolt, but it speaks no X11 at all — it runs before any session exists, drawing straight to the panel via DRM/KMS (frame's modeset path) and reading keyboards via evdev. ~25 KB static ELF, zero dependencies.

  • Press 1/2/3 to launch: 1 tile on frame, 2 tile on X, 3 i3 on X (safeguard)
  • s suspend, p power off, Esc exit to console
  • Shows clock, date, battery; wallpaper from ~/.framebg (same raw BGRX baked by chasm-bg)
  • Font: Lat15-Fixed16 (X11 misc-fixed, public domain), baked into the binary via greetfont.inc — no font files at runtime

Login gate (v0.1.15). Choosing a session no longer starts it. The greeter asks who you are first, and behaves exactly like the bolt locker does after resume: touch the reader or type your password, whichever you reach for. Both run at once, and the first to succeed wins. Typed characters show as squares; Backspace deletes, Esc returns to the menu.

Both paths go through /usr/local/bin/bolt-greet-auth, which the greeter runs with no arguments for the fingerprint and with --password (password on stdin) for the typed one. It starts the session only if that exits 0; anything else (wrong finger, wrong password, missing helper, helper killed) returns you to the menu. Copy bolt-greet-auth.example there, set GREET_USER, chmod 755. The example verifies fingerprints via fprintd and passwords via bolt-auth, the same suid helper the locker uses. The greeter only reads an exit status, so PAM or a smartcard drops in without touching the asm.

Locked out? Esc still drops to the login getty, which asks for a password. That is the intended fallback: an unenrolled reader costs you the graphical menu, never the machine. A missing helper refuses every login rather than waving them through, so a half-finished install fails shut.

On selection it releases DRM master and runs greet-session <n> (a small bash launcher): choice 1 hands the panel to frame; 2 and 3 start a root Xorg + the session as the user — the same privileged server / unprivileged session split gdm uses. When the session ends, bolt-greet re-takes DRM and shows the menu again.

make bolt-greet             # build
./bolt-greet --fbtest       # headless render test (no root needed)
sudo make install-greeter   # install binaries + systemd unit (NOT enabled)
# hand-test from a VT first:
sudo systemctl stop gdm3 && sudo bolt-greet-run
# make it the boot greeter:
sudo systemctl disable gdm3 && sudo systemctl enable bolt-greet
sudo loginctl enable-linger <user>

Known limits: timezone comes from --tz (the bolt-greet-run wrapper passes date +%z; DST updates at next greeter start), and after a VT switch away and back the menu redraws on the next keypress or 30 s tick.

Known v0.1 limits

  • Single output: bolt covers root-window extents. On multi-monitor it works but the bg_image is anchored at (0,0); your composition needs to know the combined-root resolution.
  • Background image is bake-once raw RGB. PNG / JPG decoding inside asm is a separate project (we already have a TTF rasterizer in glyph; an image decoder would be similar). Bake at install time.
  • Fallback tagline uses an X11 core font (XLoadFont + PolyText8). Looks pixel-fixed; fine for a fallback. With bg_image set, the tagline lives in the baked PNG so font choice is unconstrained.
  • No auto-lock daemon: trigger via tile keybinding, suspend wrapper, or xss-lock.

License

Unlicense — public domain.

Credits

Created by Geir Isene, with extensive pair-programming with Claude Code. Part of the CHasm desktop suite.

About

Pure-asm screen locker for the CHasm desktop suite (x86_64 NASM, no libc)

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages