SchOS/docs/architecture/users.md
Nexoniarz 2aef583aad Twelve login terminals, root only, console fixes, a faster build, a Niveus splash, and X back on evdev
- tty1-tty12 all run login; the image has only root. /dev/tty7..12 could not
  be written (cdev.c knew minors 10-16 only), which sent their jobs into a
  restart storm that took the supervisor down; fixed, and stat reports them as
  Linux's tty7..12.
- Erasing text at a prompt did nothing: erase_one sent a bare backspace, which
  only moves; it and the echo path now send back-blank-back through vt_feed.
- A white cursor block was left at the end of every line of a verbose boot:
  a line feed at the bottom scrolls the pixels, cursor included, and the
  cursor was erased after the scroll. It comes off first now. A blank cell is
  also marked dirty, which it was not.
- ldlsd died with a general protection fault on real hardware in its variadic
  log function: Linux module code calls with an 8-byte-aligned stack and an
  unset %al, and the prologue's movaps faults. LDLS guest code is built with
  -mstackrealign.
- make iso took over a minute for any change, because staging r8169 rewrote
  the same files and every mtime moved; it now replaces files only if their
  contents differ (about 10 s).
- The loader's splash is redrawn in the boot manager's style, and the boot
  manager shows its cursor whenever a pointer device exists.
- xf86-input-libinput is out of the image again: with it Xorg took both
  keyboard and pointer from libinput and, on the user's laptop, neither worked.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
2026-10-26 17:43:44 +01:00

79 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Users and permissions
SchOS has accounts, a login prompt, and file permissions that the kernel
enforces. Until now every process was root and `uid` was bookkeeping; this is
the part that makes it a multi-user system.
## What you meet
- **`login` on all twelve terminals, tty1–tty12.** `etc/schos-getty` takes the
terminal back from whoever had it and runs `login`, which asks who is there
and starts their shell; when the shell exits `schinit` starts the prompt
again. Alt+F1…F12 (or Ctrl+Alt+F1…F12) switches between them. (There is no
longer a login-free root shell on tty6.)
- **One account in the image: `root`**, with an empty password, so `login` lets
it in without asking — it is a live image. `passwd` sets one. More users are
an `adduser` away; `wheel` is empty, so `su` and `doas` have no one to serve
until then.
- **`su` and `passwd`** (`cmd/su`, `cmd/passwd`) are setuid root and small
programs of their own, not toybox applets: toybox is one binary under every
name, and a setuid copy of it can be asked for any applet by naming it, as
root. `su` to root takes membership in `wheel`, whatever the password.
- **`doas`** (Alpine's, setuid) with `permit nopass :wheel` in `/etc/doas.conf`.
## What the kernel enforces
| | |
|---|---|
| open, create, unlink, rename, link | the usual owner/group/other bits, `w`+`x` on the directory, and the sticky bit (`/tmp`) |
| path walk | `x` on every directory searched |
| `exec` | `x` on the file; set-user-id and set-group-id make the new image run as its owner or group, and the saved ids follow |
| `chmod`, `chown`, `utimensat` | owner or root; a non-root `chown` drops the set-id bits |
| `access` / `faccessat` | by the *real* ids (`AT_EACCESS` for the effective ones) |
| `kill`, `tkill`, `tgkill` | root, or a target whose real or saved uid is one of yours. The kernel's own signals (`SIGPIPE`, the terminal's) are nobody's to refuse |
| `mount`, `umount`, `chroot`, `reboot`, `shutdown`, `setgroups`, `mknod` of a device | root |
| `setuid` family | root may set anything; anyone else only to an id they already hold |
Root reads and writes everything and executes a file only if some execute bit
is set. A process's supplementary groups (`setgroups`) are consulted along with
its effective group. Ownership is stored by SchFS (it always had the fields);
FAT volumes belong to everyone, since they cannot say otherwise, and `/proc`
and `/sys` are root's.
`inode_permission()` in `kernel/fs/fs.c` is the one check; the rest of this is
call sites.
## Devices
`/dev` is built by the kernel and each node has the owner, group and mode in the
`devnodes[]` table of `kernel/fs/devfs.c`: `null` and `zero` are 0666,
terminals `root:tty 0660`, `fb0` `root:video`, input `root:input`, raw disks
`root:disk`, `pci`, `dbg` and `netdev` root's alone. `chmod` and `chown` on a
node are kept (login claims its terminal this way, and udev sets modes) in an
override table applied whenever the inode is loaded. A new pseudo-terminal's
slave belongs to whoever opened `ptmx`.
udev would set a node it has no rule for to 0600, which made `/dev/null`
root-only, so `etc/udev-schos.rules` (installed as `90-schos.rules`) names the
kernel's devices with the answers the kernel gave.
## The image
Everything in the image is owned by root: the build host's user means nothing
inside it. `mkschfs --owners FILE` takes the exceptions, one `path uid gid
[mode]` per line (`tools/posix/mkaroot.sh` writes it: the modes of `/tmp`,
`/var/tmp` and `/root`). The setuid bits are set
on `su`, `passwd` and `doas` in the root tree directly, because `apk` run as an
ordinary user may have dropped them.
## Not done
- **No PAM and no `/etc/securetty`.** `login` is busybox's and checks
`/etc/shadow` itself.
- **No capabilities.** Root is `euid == 0`, all of it.
- **No per-user `/run`, no logind.** X as a non-root user works (`startx` as `schos`, under
QEMU: Window Maker up) by group permission alone — video, input and tty — and
`/etc/X11/Xwrapper.config` lets anyone start it, because the wrapper's "console users" test
looks for a Linux VT on a standard descriptor that xinit's server child does not keep.
- **`/proc` and `/sys` hide nothing from other users.**
- **`mprotect` is still not enforced** ([kernel.md](kernel.md)).