mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-31 07:44:57 +08:00
* fix(sandbox): resolve symlinked binary paths in network policy matching Policy binary paths specified as symlinks (e.g., /usr/bin/python3) were silently denied because the kernel reports the canonical path via /proc/<pid>/exe (e.g., /usr/bin/python3.11). The strict string equality in Rego never matched. Expand policy binary paths by resolving symlinks through the container filesystem (/proc/<pid>/root/) after the entrypoint starts. The OPA data now contains both the original and resolved paths, so Rego's existing strict equality check naturally matches either. - Add resolve_binary_in_container() helper for Linux symlink resolution - Add from_proto_with_pid() and reload_from_proto_with_pid() to OpaEngine - Trigger one-shot OPA rebuild after entrypoint_pid is stored - Thread entrypoint_pid through run_policy_poll_loop for hot-reloads - Improve deny reason with symlink debugging hint - Add 18 new tests including hot-reload and Linux symlink e2e tests Closes #770 * fix(sandbox): skip procfs-dependent tests when /proc/<pid>/root/ is inaccessible The Linux-specific symlink resolution tests depend on /proc/<pid>/root/ being readable, which requires CAP_SYS_PTRACE or permissive ptrace scope. This is unavailable in CI containers, rootless containers, and hardened hosts. Add a procfs_root_accessible() guard that skips these tests gracefully instead of failing. * fix(sandbox): add explicit logging when symlink resolution fails and improve deny messages When /proc/<pid>/root/ is inaccessible (restricted ptrace, rootless containers, hardened hosts), resolve_binary_in_container now logs a per-binary warning with the specific error, the path it tried, and actionable guidance (use canonical path or grant CAP_SYS_PTRACE). Previously this was completely silent. The Rego deny reason for binary mismatches now leads with 'SYMLINK HINT' and includes a concrete fix command ('readlink -f' inside the sandbox) plus what to look for in logs if automatic resolution isn't working. * fix(sandbox): use read_link instead of canonicalize for symlink resolution std::fs::canonicalize resolves /proc/<pid>/root itself (a kernel pseudo-symlink to /) which strips the prefix needed for path extraction. This caused resolution to silently fail in all environments, not just CI. Replace with an iterative read_link loop that walks the symlink chain within the container namespace without resolving the /proc mount point. Add normalize_path helper for relative symlink targets containing .. components. Update procfs_root_accessible test guard to actually probe the full resolution path instead of just checking path existence. * fix(sandbox): defer symlink resolution until container filesystem is ready The one-shot resolve ran immediately after ProcessHandle::spawn, before the child's mount namespace and /proc/<pid>/root/ were populated. This caused symlink_metadata to fail with ENOENT on every binary, and the poll loop never retried because it only reloads when the policy hash changes on the server. Replace the synchronous resolve with an async task that probes /proc/<pid>/root/ with retries (10 attempts, 500ms apart, 5s total). The child's mount namespace is typically ready within a few hundred ms. Also inline error values into warning message strings so they appear in default log output (not just as structured tracing fields that may be elided), and add debug-level logs before each symlink_metadata call to aid diagnosis. --------- Co-authored-by: John Myers <johntmyers@users.noreply.github.com>