Skip to content

macos support + VNC XFCE - #1233

Open
dywongcloud wants to merge 326 commits into
microsoft:mainfrom
dywongcloud:main
Open

macos support + VNC XFCE #1233
dywongcloud wants to merge 326 commits into
microsoft:mainfrom
dywongcloud:main

Conversation

@dywongcloud

Copy link
Copy Markdown
Contributor

No description provided.

Weiteng Chen (CvvT) and others added 30 commits June 30, 2026 17:33
Predefine `\\KnownDlls\\KnownDllPath` as C:\Windows\System32 so ntdll
loader initialization can open and query the known-DLL search path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…onThread` (microsoft#990)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a minimal broker-to-local notification channel skeleton for
readiness updates while keeping the control channel strictly paired
request/response. The PR defines event readiness notification DTOs, wire
codec coverage, channel traits, and Unix-socket notification
send/receive support without changing shim behavior or enabling blocking
eventfd yet.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cherry-picks 9bcaa50 (Fix alarm spin
test overflow) onto ulitebox.
Adds paired broker host serving over control and notification channels,
wiring broker-userland and the Linux userland runner through
`--broker-control-socket` and `--broker-notification-socket` Unix
endpoints. The broker core remains transport-neutral, while the runner
now opens and drains the notification stream so future broker-originated
wakeups have a real local endpoint. Event mutation readiness still
returns through the control response, avoiding duplicate readiness
notifications for control-originated changes.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Enables broker-backed eventfds to honor the file description's
O_NONBLOCK state instead of forcing broker operations to be nonblocking.
The local event counter already wakes waiters from add/consume
control-response readiness, so blocking read/write now works over the
broker-backed path. Adds focused broker integration coverage for
clearing O_NONBLOCK, blocking read/write wakeups, and epoll readiness
updates.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This PR adds support for `NtOpenSection`, `NtCreateSection`,
`NtQuerySection`, `NtMapViewOfSection` and `NtUnmapViewOfSection`.

Note LiteBox lacks shared anonymous backing, so a pagefile section is
only allowed to be mapped once. For image section, it can be mapped
multiple times by copying without copy-on-write mapping support.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a LiteBox broker notification dispatch path and a
BrokerHandleRegistry that maps broker object handles to local pollables,
so EventReadiness notifications can wake blocked broker-backed event
counters. Event counters register/unregister their pollable by handle,
and the Linux userland runner now dispatches notification-channel
messages through a narrow LiteBox dispatcher instead of only draining
them. Includes focused coverage that a broker readiness notification
wakes a blocked broker-backed event counter read.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Makes the Linux eventfd syscall path use the broker-backed EventCounter
implementation and removes the shim-local Linux eventfd fallback.
Non-broker Linux shim and runner tests now either expect eventfd
creation to fail without broker control or use pipes for
non-eventfd-specific fd coverage. Broker-backed Linux eventfd coverage
remains in the broker runner integration test, including
blocking/nonblocking behavior, poll/epoll readiness, sendfile in_fd
errno behavior, and EFD_CLOEXEC/FD_CLOEXEC handling.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix `NtSetInformationProcess` to support setting TLS. For now, the
Windows shim does not support multi-threading, so the implementation is
not complete yet.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1008)

This PR adds minimal Windows AppHelp cache-control support. Note that
this is a cacheless AppHelp implementation with some TODO left.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This PR wires the Windows CSR shared section through the shim as a real
named section object and maps it during process load. Due to the lack of
shared mapping support, it is not actually shared even within one
process.

It also consolidates Windows named-object handling into a single
object-manager namespace. Directory, symbolic link, event, and section
objects now live under one namespace tree, with typed object leaves and
shared resolution logic. This lets paths like \Windows\SharedSection
behave as an object-manager shortcut to
\Sessions\0\Windows\SharedSection while keeping a TODO for multi-session
resolution.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cherry picking PR microsoft#1019. It also fixes two places of the Windows shim.

---------

Co-authored-by: Sangho Lee <sanghle@microsoft.com>
…pped (microsoft#1023)

Cherry-pick of microsoft#985 (squash commit `f5ad1f20`) onto `ulitebox`.

Dynamically-linked ET_EXEC (non-PIE) binaries load at their low
canonical vaddrs and grow their glibc brk heap upward from there, but
the ELF interpreter was reserved at a fixed low offset directly above
the main image — capping the heap, so a heap-heavy process (e.g. a
bundled node) hit ENOMEM the moment it crossed that offset. This loads
the interpreter at the top of the address space instead, mirroring how
the kernel places ld.so for an ET_EXEC main and leaving the whole gap
above the main image free for the heap; it is a no-op for PIE mains,
whose interpreter already loads high.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactor console-driver (\Device\ConDrv) support in the Windows shim so
console objects are modeled as first-class NT file devices routed
through the object manager and adds `NtDeviceIoControlFile` so guest
console setup IOCTLs are handled. Previously ConDrv paths were resolved
by ad-hoc string prefix matching; this PR also unifies path resolution.
Implement the CSR `NtConnectPort` startup handshake so Windows guests
can connect to `\Windows\ApiPort`, receive CSR connection data, and map
their client section.

CSR client and CSRSS bases currently alias one mapping; distinct virtual
mappings over shared backing remain TODO. Also, only BASESRV static-data
slot 1 is populated; CSRSRV (0), CONSRV (2), USERSRV (3) remain TODO.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Sangho Lee <sanghle@microsoft.com>
…and confused deputy" (microsoft#1036)

Co-authored-by: Sangho Lee <sanghle@microsoft.com>
…hysical pages" (microsoft#1039)

Co-authored-by: Sangho Lee <sanghle@microsoft.com>
This PR replaces per-object principal rights with one object-rights set
for each principal. It keeps the static policy surface simple before
adding more broker object types.
This PR gives broker-backed objects one shared readiness flag
representation across control responses and asynchronous notifications.
Existing event counters are migrated to the object-neutral format.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This PR handles broker connection loss by invalidating the local control
channel and waking affected waiters with an error. Notification-channel
termination cancels pending control I/O so teardown cannot hang.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This PR fixes in-process pipe behavior for blocking writes, zero-length
writes after peer closure, and operations on the wrong endpoint.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dylanwongtencent and others added 30 commits August 24, 2026 20:54
…buffer

Adds litebox_rfb, a minimal hand-rolled RFB (VNC, RFC 6143) server:
protocol 3.8, security type None, Raw encoding only, little-endian
32bpp pixel format that matches litebox's in-memory XRGB8888 layout
byte-for-byte (zero pixel conversion on the hot path). Serves any
number of concurrent clients, each on its own thread, pushing
FramebufferUpdate on a fixed 50ms timer rather than tracking
per-client request/incremental state.

Deliberately not built on the rustvncserver crate: research found its
published README documents a fictional API that doesn't match what
actually compiles, its listen() cannot bind to a specific interface
(always 0.0.0.0, conflicting with this feature's localhost-only
default), and it would add tokio as litebox's first-ever async
runtime dependency to an otherwise very deliberately minimal
codebase. std::net plus one thread per connection matches the
existing std::thread pattern the macOS runner already uses for its
network-interaction worker.

Wired into litebox_runner_linux_on_macos_userland behind --vnc
(--vnc-port, --vnc-bind-all). Exposes LinuxShim::framebuffer() and a
FramebufferAdapter bridging litebox::fs::devices::Framebuffer to
litebox_rfb::FramebufferSource. The whole accept-loop-and-serve
worker is spawned BEFORE enable_seatbelt_sandbox(): Seatbelt's
(deny default) profile has no allow rule for accept() as a mediated
network operation, only for read/write on already-open fds (stdio,
utun) -- discovered live via EAGAIN-on-non-blocking-inherited-stream
during verification, then confirmed as a real Seatbelt policy gap
by moving the whole server (not just the bind) to pre-sandbox.

Live-verified end to end against a hand-written Python RFB client
speaking real wire protocol: full handshake, ServerInit geometry,
pixel format negotiation, and FramebufferUpdate payload matching a
guest-painted pixel pattern byte-for-byte at multiple offsets across
three independent runs.

Part of the litebox-fb-rfb-server PRD row (VNC-desktop graphics
support).
litebox_rfb uses std::net/std::thread for its RFB server (userland
only, never linked into the no_std shim/platform layers) -- same
category as litebox_packager/litebox_syscall_rewriter, which are
already on this list.
Adds litebox::fs::devices::input -- a virtual keyboard (event0, EV_KEY
codes 1..=127) and absolute-position pointer (event1, BTN_LEFT/RIGHT/
MIDDLE + ABS_X/ABS_Y over 0..=32767 + REL_WHEEL, QEMU usb-tablet
shape) behind an Arc-shared InputRegistry the runner injects into and
the shim drains from. Wire ABI follows include/uapi/linux/input.h and
drivers/input/evdev.c exactly: 24-byte LP64 input_event, EVIOC* per
asm-generic _IOC decoding (len rides in the size field), string/bitmap
reads returning the copied byte count, EVIOCGPHYS/GUNIQ -> ENOENT
(the errno libevdev tolerates), unknown 'E' commands -> EINVAL (the
kernel's actual answer, not ENOTTY), SYN_REPORT-terminated batches,
bounded 1024-event queues that drop oldest rather than block.

Shim integration: input fds are tagged with their evdev minor at open
time (entry metadata, so epoll's descriptor-table-only poll path can
recognize them); reads block on the device's pollee with the task's
wait context; the EVIOC* family dispatches from sys_ioctl's Raw arm;
poll/epoll report real queue-backed readiness instead of the dummy
always-ready file default (which would spin X11/libinput on empty
reads).

RFB bridge: litebox_rfb::keymap maps X11 keysyms to evdev codes (US
static table -- no arithmetic mapping exists; shifted symbols map to
their base key since real VNC clients send Shift_L down first), and
the macOS runner's --vnc input handler now injects KeyEvents and
PointerEvents (mask-delta button transitions, wheel from button-4/5
press edges, coordinates scaled against live framebuffer geometry)
through LinuxShim::input_registry().

Live-verified end to end under litebox_runner_linux_on_macos_userland
with a guest evtest-style binary + Python RFB client: EVIOCGVERSION
0x10001, GID bus=BUS_VIRTUAL, GNAME rc=17, type bitmaps 0x3/0xf,
EVIOCGABS max=32767, GPHYS -ENOENT, injected 'a' read back as
type=1 code=30(KEY_A) value=1, pointer-center as ABS 16383/16383.

Part of litebox-fb-evdev-input (VNC-desktop graphics support).
reserve_alignment_outputs_match_host_ntdll frees a probe reservation
and immediately reuses its exact address fixed -- racing the process's
own allocator (heap growth, loader, sibling tests). On CI runners the
reuse intermittently lands STATUS_CONFLICTING_ADDRESSES (observed on
runs 32801257181, 32802096031, 32810614666 -- always this one test,
always 0xc0000018), which is a stale probe address, not an
alignment-fidelity failure. Re-probe at a fresh address on conflict,
bounded at 8 attempts; the actual fidelity assertions are unchanged.

Resolves windows-mm-reserve-alignment-address-conflict-flake.
podman/docker export tars go through the same extract/rewrite pipeline as
registry-pulled --oci-image layers (gzip sniffed, symlinks materialized,
ELFs SVC-gate rewritten), with a default ImageConfig since an exported
rootfs carries none. Unblocks guest images built locally (e.g. a
Containerfile adding fbdev graphics packages) without a registry push.

Verified live: podman-built alpine+netsurf image exported, packaged
(666 entries, 400 ELFs rewritten), and booted under the macOS runner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every real fbdev graphics client draws through mmap(MAP_SHARED|PROT_WRITE)
of the framebuffer; litebox previously rejected all writable file-backed
shared mappings, so only the write(2) path could paint. Because the shim
and guest share one host address space on userland platforms, the mapping
can be genuinely coherent with no flush step: mmap of fb0 now allocates
anonymous MAP_SHARED pages, pre-fills them from the pixel store, and
registers them with the Framebuffer as its live store. All accessors
(read_at/write_at/read_visible_into, hence the RFB snapshot) read and
write through the registered pages.

Deregistration (with copy-back, preserving last-drawn content) happens at
every point the pages could go away: munmap, mremap of an overlapping
range, execve's owned-mappings bulk release, and geometry resize.
MAP_SHARED on the anonymous pages also keeps save_address_space from
private-copying them on a fork handoff.

Verified live on macOS/aarch64: a guest that mmaps fb0 and paints with
pure stores (no fb syscalls after mmap) shows solid red at the RFB probe,
repaints green and shows green, and still shows green after munmap
(copy-back) -- first_pixel bytes 0000ff00 then 00ff0000 twice over the
wire.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fbdev graphics clients (links2's fb driver is the archetype) require
VT_GETMODE/VT_SETMODE to succeed on their controlling tty before they
will draw, and issue VT_GETSTATE/VT_RELDISP/VT_ACTIVATE/VT_WAITACTIVE
fire-and-forget. litebox has no virtual terminals to switch between, so
the shim now answers the family ('V' 0x56, legacy non-_IOC commands) on
tty fds as a console whose single VT 1 is permanently active: VT_AUTO
mode, no release/acquire signals, VTs 0/1 open. Non-tty fds still get
ENOTTY, unknown VT commands EINVAL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The kernel reads pselect6's sixth argument as {const sigset_t *ss;
size_t ss_len} and treats a null ss as 'don't touch the mask'. musl's
plain select() always passes exactly that ({NULL, _NSIG/8}), so the
shim's unconditional read of the inner pointer returned EFAULT for
every select() call from a musl guest.

Observed live: links2's event loop died on 'select failed: Bad address'
at startup; with the null honored, links2 -g runs its full graphics UI
under the macOS runner (verified by RFB screenshot of a rendered HTML
page).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fbdev-console programs (links2 -g, shells, editors) read the keyboard
from the tty, not evdev, so VNC KeyEvents now feed both: evdev events as
before, plus a keysym-to-console-bytes translation (Latin-1 passthrough,
linux-terminfo sequences for arrows/nav keys/F-keys, Ctrl folding onto
C0) pushed through the platform's stdin pump, which wakes blocking
reads, select/pselect, and epoll observers identically to typed input.

--vnc also now holds guest stdin open across host-stdin EOF (new
Platform::new_with_options flag, set at construction because a
redirected stdin hits EOF in the pump thread within microseconds):
with the VNC keyboard as a second producer, a closed host stdin must
not read as end-of-input to a guest whose real keyboard is the bridge.

Verified live: with host stdin at /dev/null, RFB-typed 'hi<Enter>'
echoed back from a guest /bin/cat, and an RFB Enter dismissed links2's
graphics-mode welcome dialog (before/after RFB screenshots).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The keysym translation helper was inserted between run()'s doc comment
and the function, silently reattaching the docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The macOS host has no tun device without root, so the guest's IP packets
had nowhere to go. But the host owns the guest's smoltcp stack, so it
can terminate guest TCP itself. Three pieces:

- litebox_shim_linux::host_service: host-owned sockets inside the guest
  network -- LinuxShim::listen_in_guest plants a TCP listener (the
  listening-side counterpart of transport::ShimTransport), whose
  accepted GuestStreams host code services with non-blocking
  try_read/try_write. Graceful close uses GracefulIfNoPendingData, NOT
  Graceful: Graceful removes the descriptor entry (and channel proxy)
  immediately, orphaning queued TX-ring bytes before the network worker
  drains them (observed live as an HTTP response the guest never saw).

- runner --net-proxy: an HTTP proxy (CONNECT + absolute-URI, hop header
  rewrite, Connection: close) at 127.0.0.1:3128 in the guest, each
  request re-originated as an ordinary host connection. Hostname
  resolution is a hand-rolled UDP A-record client against resolvers
  snapshotted from /etc/resolv.conf pre-sandbox -- getaddrinfo's
  mDNSResponder path stays closed.

- Seatbelt: RUNNER_PROFILE_WITH_OUTBOUND_NETWORK adds network-outbound
  plus UDP-only network-bind/network-inbound (the DNS client's local
  ephemeral port and its replies; TCP listening stays denied). Installed
  only under --net-proxy.

Verified live: guest busybox wget through the proxy fetched the real
example.com (WGET_EXIT=0, '<title>Example Domain</title>'), and links2
-g -http-proxy rendered the live page in graphics mode over VNC
(screenshot: heading, body text, link, page title in the title bar).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mice device (in-progress /dev/input/mice) reached main mid-edit in
the previous commit; this restores the build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
links2's fb driver (and every svgalib-era fbdev app) takes its mouse
from /dev/input/mice speaking the PS/2 protocol, not evdev. The
registry now hosts mousedev's aggregate device (13:63) exactly:

- Protocol: every written byte advances the ImPS/2 (200,100,80) and
  Explorer (200,200,80) rate-knock matchers; the response buffer is
  REPLACED per byte -- mousedev semantics, and precisely what links2's
  read-until-ACK-then-read-ID handshake depends on (a per-command ACK
  stream would feed it 0xFA as the ID). GETID answers the negotiated
  mode (0/3/4), reset returns FA AA 00, poll a zero-motion packet.
- Motion: RFB absolute pixels are converted to deltas against the last
  event (a PS/2 mouse only speaks deltas; the client tracks position --
  the injector anchors at the client's known start to stay aligned),
  emitted as 3- or 4-byte packets per the negotiated mode, split when a
  delta exceeds the 8-bit field.
- Plumbing: byte-granular reads (the handshake reads 1 byte at a time,
  exempted from evdev's 24-byte floor), writes routed to the protocol
  machine, poll/select readiness via its own pollee, EVIOC* refused
  (mousedev is not an evdev node).

Verified live end-to-end: guest od dump shows exact packets
(08 00 00 | 08 0a 05 for a +10,-5-screen move); links2 -g negotiated
ExPS/2, tracked the cursor onto example.com's 'Learn more' link
(status bar showed the target URL), and a VNC click navigated to the
real https://iana.org page (RFB screenshot of the rendered result).
Debugging note for posterity: earlier 'cursor never moved' repros were
an artifact of screenshotting through a backlogged RFB connection --
the unsolicited 50ms pusher fills a non-draining probe's socket, so
reads return frames from seconds ago; a fresh connection screenshots
current state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
'Point a VNC viewer at 127.0.0.1' fails on the very machine the runner
runs on: macOS's built-in Screen Sharing refuses to dial localhost (it
never even opens the TCP connection -- observed live against a
listening server). A browser has no such rule and needs no install, so
--vnc-web <PORT> serves one: an embedded single-page canvas client at
/ and a WebSocket at /ws, HTTP + RFC 6455 hand-rolled (SHA-1 + base64
inline, proven against RFC 6455 s1.3's own handshake vector in a unit
test) for the same no-new-deps reason the RFB server is hand-rolled.

Wire protocol is deliberately simpler than RFB: whole RGBA frames
pushed only when the content hash changes; 6-byte binary key/pointer
messages carrying the same X11 keysyms and button masks RFB uses, so
one shared input-handler factory (extracted from the former inline VNC
closure) now feeds both servers identically -- evdev + PS/2 mice +
tty-byte injection. --vnc-web also holds guest stdin open across host
EOF, same as --vnc, and binds localhost-only.

Verified live end-to-end in a real browser: headless Chrome loaded
http://127.0.0.1:6080/, its canvas showed the links2 guest rendering
the live https example.com page (CDP screenshot), and an Escape
dispatched into the page traveled JS -> WebSocket -> guest stdin and
opened links2's menu bar in the next streamed frame. Protocol-level:
python client validated the handshake accept value, received 1024x768
frames, and its Enter dismissed the guest dialog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five gaps found and fixed by walking Xorg + XFCE bring-up to each
successive failure, every fix verified live against the real stack:

- linkat/link (was ENOSYS): X's /tmp/.X0-lock atomic-create idiom.
  DEVIATION, disclosed in the handler doc: the layered fs has no
  inode-sharing hard links yet, so this creates an exclusive copy --
  identical observable behavior for the write-link-unlink lock idiom
  every known caller uses; post-link write aliasing and st_nlink
  identity await real fs hard links.
- setresuid/setresgid (was ENOSYS): libc's seteuid/setegid wrappers
  issue these; xterm and every setuid-aware client aborts without them.
- unix sockaddr paths without a trailing NUL (was EINVAL): the kernel
  bounds sun_path by addrlen with the NUL optional, and dbus-daemon and
  X's own filesystem listener both bind exactly that way. This EINVAL
  killed every dbus session bus and X's /tmp/.X11-unix/X0 socket.
- fork with a netlink socket open (was EBADF, failing the whole fork):
  netlink is a seventh fd subsystem the six-way fork duplication never
  learned about, and Xorg holds libudev's uevent socket across every
  xkbcomp fork ('XKB: Could not invoke xkbcomp').
- evdev/mice reads now honor open-time O_NONBLOCK/O_NDELAY: Xorg's
  evdev driver opens devices O_NDELAY and drains them with reads it
  expects to EAGAIN; the previous always-blocking read wedged the X
  server's whole main loop on the first empty drain (observed live as
  a total desktop freeze).

Plus runner --guest-root: present uid/gid 0 instead of synthetic 1000
(identity is synthetic either way; isolation is litebox's, not the
guest uid's). Xorg's -nolock is root-only, dbus and session managers
hard-check uids, and a single-user appliance image has nothing to
distinguish.

Verified live: Xorg 21.1 starts on /dev/fb0 (fbdev+evdev drivers, our
virtual devices), draws its root weave through the coherent mmap
(ShadowFB off), accepts clients on both abstract and filesystem
sockets, survives xkbcomp forks, and dbus-daemon runs a session bus.
Regression sweep re-ran the cross-process unix epoll ping-pong and the
4-thread pthread guest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eque

The unix-socket transport's Channel split a ringbuf::HeapRb into that
crate's caching producer/consumer handles, each behind its own mutex.
A caching handle trusts a locally cached copy of the opposite index
that only its own push/pop operations refresh -- and this module's
peek-first consumption (peek_and_consume_one -> first_mut) observed
the cached view without ever refreshing it. Captured live with
paired diagnostics: try_push succeeded with producer-side
occupied_len()=1 while the consumer's occupied_len()=0 on the same
logical ring, permanently -- an X server's queued events that its
client (poll-parked on that very socket) never saw, wedging every
X11 client that depends on event delivery.

One VecDeque under one mutex, shared by both ends, has no index
caching to go stale; none of these paths are hot enough for the
extra lock to matter. New regression tests: peek-sees-push-immediately
(100 rounds) and EAGAIN-when-full; the existing shutdown-semantics
tests pass unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The header check requires it as the file prefix; browsers explicitly
allow comments before <!doctype>.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The in-memory layer ran every operation as its hardcoded construction
identity 1000/1000, so under --guest-root (uid 0) everything the guest
created was owned by a uid the guest didn't have. Observed live, twice:
Xorg silently refused to bind /tmp/.X11-unix/X0 (its socket dir owned
by 1000 while X ran as 0), leaving clients' wait-for-socket loops
hanging on a black screen forever; dbus-daemon rejected its
XDG_RUNTIME_DIR for the same mismatch. The in-mem filesystem now
exposes set_current_user, and the runner sets 0/0 when --guest-root is
active.

Verified live: the exact previously-black demo command (Xorg + xmessage
+ xclock, infinite wait on /tmp/.X11-unix/X0) now renders both windows
in the browser viewer with no script changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…probe

The 8-attempt re-probe still exhausted on CI: the guest path's FIRST
sys_nt_allocate_virtual_memory grows the shim's own heap and tracking
structures, and on some runners that growth deterministically reused
exactly the just-freed probe range, so every retry conflicted the same
way. One throwaway guest round trip before the loop moves that growth
out of the probe-to-attempt window; attempts also raised to 32 for the
genuinely random collisions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
'Address already in use' on --vnc-web/--vnc almost always means another
runner instance is still holding the port (observed live: a leftover
demo instance); say so, with the port number, instead of the bare
os error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fixed-x18

Live measurement in the XFCE image isolated the clock-only desktop to
XNU's x18 zeroing corrupting stock Alpine hot loops: busybox sha256sum
of a 7 MB library returned a different wrong digest per run while cat
of the same file was byte-perfect, and the same busybox rebuilt with
-ffixed-x18 hashed correctly 4/4 in the same guest session. GTK paint
loops, ld.so relocation and Xorg reply serialization are the same
mechanism landing elsewhere.

build-x18-desktop-repo.sh rebuilds the ~55 rendering-critical packages
(glib/GTK/cairo/pixman/pango/harfbuzz, X client libs, Xorg + drivers,
XFCE, busybox, dbus) from aports with -ffixed-x18 into a local APK repo
keyed pkgrel=999 so an image build overlays it with one apk upgrade.
Runs as root with abuild -F (fakeroot is broken in these containers),
appends the flag via /etc/abuild.conf (sourced after default.conf,
which assigns CFLAGS unconditionally), seeds busybox's Kbuild-only
CONFIG_EXTRA_CFLAGS, and verifies artifacts by objdump [wx]18 count
(busybox: 102 stock -> 0 rebuilt). Documented in the roadmap's x18
section.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rebuild the conservative Alpine 3.24 XFCE paint closure rather than the
initial partial list. Reserve x18 in C/C++ and Rust, make residual
instructions fatal, and patch four assembly/LTO/compiler-helper paths that
survive flags. Live rebuilt busybox, fontconfig, libffi, libXt, and pixman
artifacts scan at zero x18 operands.

Keep stock package revisions so Alpine's exact sibling dependencies remain
valid, retry transient fetches, resume via per-origin markers, reject stale
builder state, and preserve previous exports. Same-version APK replacement
was witnessed through explicit local paths: five exact packages planned as
Replacing, with no install/upgrade/downgrade, and produced a deterministic
fixed-busybox image.

Co-Authored-By: Claude <noreply@anthropic.com>
Add the pinned Alpine 3.24 recipe, direct fbdev/evdev Xorg config,
X11 dbus/XFCE launcher, and one build command that creates the x18-safe
APK overlay, applies only exact same-version installed APKs, exports the
local OCI rootfs, packages it, and appends the fbdevhw sysfs link.

The tracked Containerfile was live-built with the zero-x18 proof repo:
all five matching APKs were simulated and applied strictly as
same-version Replacing operations before the resulting image committed.
The launcher uses test -e for litebox's non-S_IFSOCK X0 entry, disables
unsupported GLX/ShadowFB paths, and serves through runner --vnc-web.

Co-Authored-By: Claude <noreply@anthropic.com>
Disable GCC's native three-stage bootstrap for the desktop overlay. Stages
2/3 intentionally replace package CFLAGS with BOOT_CFLAGS, reintroducing
x18 and spending roughly half an hour compiling a compiler the desktop
does not install. A one-stage native build keeps -ffixed-x18 in the target
libgcc/libstdc++ commands and all packaged host code.

Witnessed the live top-level configure with --disable-bootstrap and the
active CFLAGS/CXXFLAGS_FOR_BUILD carrying -ffixed-x18. The final package
artifact gate remains authoritative.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants