# Foundations The kernel work that [wayland.md](wayland.md) and [hybrid.md](hybrid.md) both stop at. **This is the critical path**, and it is the reason those two are one plan rather than two. The insight is small and it decides the schedule: the substrate for passing a buffer to a compositor and the substrate for handing a device to a driver process are the same substrate. Descriptor passing and shared memory, built once. --- ## What is actually in the tree Measured against the source, not against a README. Each of these was checked before anything below was planned around it: | | | |---|---| | `sendmsg`/`recvmsg`, and therefore **`SCM_RIGHTS`** | **Do not exist.** Not in `kernel/sys/table.inc`, not anywhere in `kernel/`. | | Writable `MAP_SHARED` of a file | **Refused** — `kernel/sys/sys_mem.c:131` returns `-ENODEV`. | | `memfd_create` | Does not exist. | | `AF_UNIX` names | In a table in `kernel/net/unix.c`, not in the filesystem. | | `setsockopt` | `return 0;` unconditionally — `kernel/sys/sys_net.c:436`. | | `exec` | `ET_EXEC` only. No `PT_INTERP`, no `ET_DYN`. | > **`projects/schcom/README.md` says `SCM_RIGHTS` is done. That line is wrong**, > and it is the most load-bearing wrong line in the tree — an entire GUI plan was > drawn on top of it. It is corrected as part of this work. The `MAP_SHARED` refusal is worth defending rather than fixing carelessly. The code returns `-ENODEV` *honestly*: the contract of a writable shared mapping is that stores land in the file and other mappers see them, and there is no page cache that could make that true. Quietly handing back a private copy would be the same lie in a new place. --- ## The five items In dependency order. The first three are what Wayland cannot start without. ### 1. `sendmsg` / `recvmsg` with `SCM_RIGHTS` Not optional and not substitutable. `wl_shm_create_pool` passes a **file descriptor**; there is no path in the Wayland protocol that passes an integer instead. The `handle_kind` field in `projects/schcom/proto.h` was good foresight and it cannot help here — *our* protocol is the flexible one, and Wayland's is not. Needs: `struct msghdr`/`cmsghdr` handling, ancillary data queued alongside the byte stream in `kernel/net/unix.c`, descriptor installation into the receiver's file table, and correct behaviour when a message carrying descriptors is never received (they must be closed, not leaked). **This is also item 1 of the hybrid work**, where it is how a driver process is handed the device it is allowed to touch. ### 2. A shareable memory object `memfd_create`, plus `mmap(MAP_SHARED)` on it genuinely working between two processes. Narrower than a general page cache, and sufficient. An anonymous shared object needs no file behind it, which is exactly why `memfd` exists on Linux at all — and it means this can be built on the shared-memory machinery already in `kernel/sys/sys_mem.c` (`shmget`/`shmat`/`shmdt` work, and `struct vma` already carries `shmid` and a `no_free` flag for pages that are not ours to release). The general answer — a page cache, and writable `MAP_SHARED` of a real file — stays owed. It is a larger project and nothing on this plan needs it. ### 3. `AF_UNIX` sockets in the filesystem namespace Clients find a Wayland compositor by `bind()`ing `$XDG_RUNTIME_DIR/wayland-0` as a real path, and libwayland `flock()`s the lock file beside it. A name table can express neither. `kernel/net/unix.c`'s own header comment already predicted this: > *"What is lost is `ls -l /tmp/schcom` showing an `s`, and `unlink()` of a socket > path failing with ENOENT. Both are worth fixing when the VFS next gets opened > up; neither blocks anything."* They block something now. This is that moment, and it is a VFS change rather than a socket change: a socket inode type threaded through `iget`, `dirlookup` and `stat`, plus `flock`. ### 4. `setsockopt` that does not lie At minimum `SO_PASSCRED` and `SO_SNDBUF`. Returning 0 for an option you ignored is worse than `ENOPROTOOPT`, because the caller adjusts its behaviour on the strength of the lie. Small, and grouped here because it is in the same file as item 3 and will be found by the same testing. ### 5. Dynamic linking `PT_INTERP` and `ET_DYN` in `kernel/fs/exec.c`. **Deferrable, and deferred.** Static binaries are enough to reach a working desktop with software rendering. This becomes necessary when Mesa does — EGL means `dlopen` means a loader — and that is a separate decision made later. --- ## Verification Each item gets a test before the thing that needs it is built, because a substrate that is subtly wrong fails inside the consumer and looks like the consumer's bug. - **Item 1:** two processes, one passes an open descriptor, the other reads through it. Plus the leak case: a sender that exits with descriptors in flight. - **Item 2:** two processes map the same `memfd`, one writes, the other sees it. - **Item 3:** `bind()` a socket, then `stat()` and `ls -l` the path and see an `s`, then `unlink()` it. - **Items 1–3 together:** a third test that does all of it at once, because that combination is what Wayland actually performs and the three passing separately does not prove it. These belong in `bootcheck` as a new switch, following the `-Sock` model. --- ## What this does not deliver - **No page cache**, so writable `MAP_SHARED` of a real file stays refused. - **No `dlopen`** until item 5 is done, which means no Mesa and no third-party shared libraries. - **`SO_*` coverage is the two options named**, not the full set. - **No credential passing** (`SCM_CREDENTIALS`) — only descriptors. Nothing on this plan needs it, and a compositor that wants to know who connected will.