memwrite: per-process (cr3) target and full-extent socket SRC

- CMD_MEMWRITE now carries a target page-table root (cr3) as its first field;
  cr3 == 0 keeps the kernel address-space default (backward-compatible). A control
  that has discovered a process's cr3 through its own read-only perception can
  write that process's private memory under the same exclusive write lease.
  Freshness of the cr3 is the control's responsibility — signaling does not
  validate it (that is perception, not coherence), mirroring the read side.

- A socket control can now carry an SRC larger than the inline frame budget: a
  length-prefixed SRC tail follows the CMD_MEMWRITE frame (flag SRC_PAYLOAD, the
  length being the frame's own len). A per-connection two-phase receiver
  accumulates the tail into a fixed conn-owned buffer up to the extent bound,
  matching the in-process payload path. A zero or over-bound length is a framing
  violation that closes the connection: leaving the promised tail unread would
  desync the stream and draining an arbitrary length would be a denial of service.

The capability, exclusive lease, source and extent gates are unchanged and
reused; only the event header gained the cr3 field and the socket transport
gained the tail receiver. The adapter resolves cr3 == 0 to the kernel root on
its worker thread and writes atomically.
This commit is contained in:
2026-06-20 21:21:20 +03:00
parent e9aee057c7
commit e6c7aed8eb
7 changed files with 309 additions and 39 deletions
+20 -8
View File
@@ -168,20 +168,32 @@ typedef struct {
} vmsig_input; /* fits in vmsig_event.inln[48] */
/* ===== Memory write (DOWN VMSIG_EV_CMD_MEMWRITE) — NEUTRAL, write-signaled =====
* control describes an ATOMIC write into guest memory abstractly (guest VA + length),
* WITHOUT knowing vmie/cr3: the memctx adapter resolves it under the held kcr3 and does
* ONE gva_write. Requires CAP_MEMWRITE + an exclusive MEMWRITE lease + an extent check.
* control describes an ATOMIC write into guest memory abstractly: a TARGET address space
* (cr3) + a guest VA + a length, WITHOUT knowing vmie. The memctx adapter does ONE
* gva_write under the requested cr3. Requires CAP_MEMWRITE + an exclusive MEMWRITE lease
* + an extent check.
*
* cr3: the target page-table root (DirectoryTableBase). cr3 == 0 selects the adapter's
* permanent System DTB (kernel AS) — the backward-compatible default. A non-zero cr3
* addresses a PROCESS private AS that the control discovered out-of-band (RO proc_list).
* FRESHNESS of a process cr3 is the CONTROL's responsibility: a process may exit and its
* cr3 (page-table root PFN) be reused, so a stale cr3 would write into an UNRELATED AS.
* signaling does NOT validate cr3 (that is perception, not coherence) — symmetric to the
* read side, where the control already owns cr3 freshness for gva_read. The kernel default
* (cr3 == 0) has no such hazard: the System DTB is permanent for the VM session (epoch).
*
* SRC bytes: inline (<= VMSIG_MEMWRITE_INLINE) ride in the inln tail right after this header
* (flags & INLINE); larger in-proc writes ride in the borrowed payload (flags & PAYLOAD). */
#define VMSIG_MEMWRITE_INLINE 32u /* inln tail capacity for SRC (48 - 16 header) */
#define VMSIG_MEMWRITE_INLINE 24u /* inln tail capacity for SRC (48 - 24 header) */
#define VMSIG_MW_SRC_INLINE 0x1u /* SRC bytes are in inln tail (len<=INLINE) */
#define VMSIG_MW_SRC_PAYLOAD 0x2u /* SRC bytes are in ev->payload.data (in-proc) */
typedef struct {
uint64_t gva; /* guest virtual address to write (resolved under the adapter's kcr3) */
uint32_t len; /* number of bytes to write (1..VMSIG_MEMWRITE_MAX) */
uint32_t flags; /* VMSIG_MW_SRC_INLINE | VMSIG_MW_SRC_PAYLOAD */
uint64_t cr3; /* target page-table root; 0 => the adapter's System DTB (kernel AS) */
uint64_t gva; /* guest virtual address to write (translated under cr3) */
uint32_t len; /* number of bytes to write (1..VMSIG_MEMWRITE_MAX) */
uint32_t flags; /* VMSIG_MW_SRC_INLINE | VMSIG_MW_SRC_PAYLOAD */
/* inline SRC tail (when VMSIG_MW_SRC_INLINE): up to VMSIG_MEMWRITE_INLINE bytes follow */
} vmsig_memwrite; /* header = 8+4+4 = 16 bytes; +32 tail = 48 (exactly inln[48]) */
} vmsig_memwrite; /* header = 8+8+4+4 = 24 bytes; +24 tail = 48 (exactly inln[48]) */
/* ===== Cursor (UP VMSIG_EV_CURSOR_STATE, in inln) — NEUTRAL =====
* Cursor position from the SCREEN sensor (vgpu). NEUTRAL payload format only: emitted by the