vmsig: management daemon, runtime endpoint lifecycle, roster, discovery, in-tree drivers, packaging

- core: runtime attach/detach of a per-endpoint adapter trio (runtime-safe add_adapter + vmsig_core_detach_endpoint, deferred reap)
- roster: VMSIG_EV_ROSTER + CAP_ROSTER, retained per-endpoint and replayed to late subscribers
- discovery: inotify trigger dir, vmid/endpoint slot allocator, host probe; vmsigd daemon with config + per-uid admission
- input driver and vgpu perception built in-tree; vgpu perception as a separate library
- memctx: own the supplied ro_fd (closed at detach)
- deb packaging: install rules, systemd unit, tmpfiles, default config
This commit is contained in:
2026-06-22 17:25:06 +03:00
parent 0d387a4249
commit 9bde398b6c
55 changed files with 4703 additions and 61 deletions
+66
View File
@@ -16,6 +16,7 @@
#include "vmsig.h"
#include "vmsig_socket.h" /* vmsig_wire, vmsig_socket_attach */
#include "core_internal.h" /* core_emit_up (synthetic lifecycle injection) */
#include "memctx.h" /* vmsig_memctx_cfg (infra ro_fd ownership test) */
#include <stdio.h>
#include <string.h>
#include <stdint.h>
@@ -328,12 +329,77 @@ static void test_socket(void) {
vmsig_ctx_free(ctx);
}
/* ---- 6. ro_fd ownership: an infra-supplied RO-fd is closed by the adapter --- *
* Regression for the latent leak: cfg.ro_fd ownership transfers to the adapter at
* open(); mc_close() must close it, so a re-grant (detach + re-attach with a fresh
* infra ro_fd) does not leak the prior one. Only DUPS leave outward (one per share),
* so the original stays open across the run and is reaped at adapter close. */
#ifndef MFD_CLOEXEC
#include <sys/syscall.h>
#include <linux/memfd.h>
static int memfd_create(const char* name, unsigned int flags) {
return (int)syscall(SYS_memfd_create, name, flags);
}
#endif
#ifndef MFD_ALLOW_SEALING
#define MFD_ALLOW_SEALING 0x0002U
#endif
#ifndef F_ADD_SEALS
#define F_ADD_SEALS (1024 + 9)
#define F_SEAL_SHRINK 0x0002
#define F_SEAL_GROW 0x0004
#endif
#ifndef F_SEAL_FUTURE_WRITE
#define F_SEAL_FUTURE_WRITE 0x0010
#endif
static int make_ro_backing(uint32_t size) {
int fd = memfd_create("vmsig_test_ro", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0) fd = memfd_create("vmsig_test_ro", MFD_CLOEXEC);
if (fd < 0) return -1;
if (ftruncate(fd, (off_t)size) != 0) { close(fd); return -1; }
(void)fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_FUTURE_WRITE);
return fd;
}
static void test_ro_fd_ownership(void) {
printf("test_ro_fd_ownership\n");
int ro = make_ro_backing(0x10000u); /* >= the stub low so the holder can mmap */
CHECK(ro >= 0, "created an RO backing fd");
if (ro < 0) return;
vmsig_ctx* ctx = vmsig_ctx_new();
vmsig_core* core = vmsig_core_new(ctx);
holder h; memset(&h, 0, sizeof h);
h.core = core; h.is_driver = 1; h.expect_ep = 0; h.stop_epoch = -1;
add_holder(core, &h, VMSIG_CAP_MEMCTX, 0xFFFFFFFFu, 1ull << 0);
/* stub kcr3 (no VM) but a REAL infra ro_fd handed in for the RO share path. */
vmsig_memctx_cfg mc; memset(&mc, 0, sizeof mc);
mc.stub = 1; mc.ram_path = NULL; mc.low = 0; mc.ro_fd = ro;
CHECK(vmsig_core_add_adapter(core, vmsig_memctx_ops(), &mc, 0) >= 0, "add memctx (infra ro_fd)");
vmsig_core_run(core);
CHECK(h.memctx >= 1, "holder received MEMCTX over the infra ro_fd");
CHECK(h.ro_ok, "infra ro_fd re-shared and mmaps PROT_READ");
CHECK(fcntl(ro, F_GETFD) >= 0, "infra ro_fd still open before close (no premature close)");
vmsig_core_free(core); /* mc_close closes the owned cfg_ro_fd */
vmsig_ctx_free(ctx);
CHECK(fcntl(ro, F_GETFD) == -1, "infra ro_fd closed by mc_close after free (no leak)");
if (fcntl(ro, F_GETFD) >= 0) close(ro); /* belt-and-braces if the assert failed */
}
int main(void) {
test_multicast();
test_epoch();
test_retain();
test_multivm();
test_socket();
test_ro_fd_ownership();
printf("memctx tests: %s\n", g_fail ? "FAIL" : "PASS");
return g_fail ? 1 : 0;
}