Skip to content

fix(runtime): ignore child mounts during container detection - #65494

Open
the3asic wants to merge 2 commits into
NousResearch:mainfrom
the3asic:upstream/root-mount-container-detection-20260716T081149Z
Open

fix(runtime): ignore child mounts during container detection#65494
the3asic wants to merge 2 commits into
NousResearch:mainfrom
the3asic:upstream/root-mount-container-detection-20260716T081149Z

Conversation

@the3asic

Copy link
Copy Markdown
Contributor

What does this PR do?

The Linux container fallback currently scans all of /proc/self/mountinfo for runtime markers. A normal host that runs Docker or containerd can therefore be misclassified as a container because one of its child mounts contains a runtime path.

This change:

  • inspects only the mountinfo entry whose mount point is /;
  • decodes standard mountinfo path escapes before comparing the mount point;
  • preserves positive detection when the process root is backed by Docker, containerd, Kubernetes, LXC, CRI-O, or containers/storage;
  • safely ignores malformed or empty mountinfo data;
  • adds synthetic tests proving that container-like child mounts do not classify the host root as containerized.

Verification

  • Tested on Ubuntu 26.04 / Linux x86_64
  • pytest tests/test_hermes_constants.py -q — 132 passed
  • ruff check hermes_constants.py tests/test_hermes_constants.py
  • python -m py_compile hermes_constants.py tests/test_hermes_constants.py
  • git diff --check

The tests use synthetic mountinfo rows and do not read live /proc, credentials, or environment-specific paths.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint area/docker Docker image, Compose, packaging P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 16, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #58141 uses the same root-mount-only strategy, while #65060 broadens the container-detection structural checks. This PR adds a distinct partial variant; please consolidate the preferred scope.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for targeting the verified cgroup-v2 false positive: current main still scans the whole mountinfo payload at hermes_constants.py:1131-1135.

Problems

  • In the added helper, hermes_constants.py:1118 searches the entire raw root-mount line after filtering on field 5. That also searches the mount source. A host root source such as /dev/mapper/docker--vg-root would match docker despite being device provenance, not containment. The proposed tests cover marker-bearing root overlays but not this false-positive shape.

Suggested changes

  • Parse the separator and probe only mountinfo field 3 plus super options after -; exclude filesystem type and source.
  • Add an is_container() regression test for a markerless cgroup plus /dev/mapper/docker--vg-root root source.
  • Please consolidate the preferred scope with the linked #58141 / #65060 variants, as noted in the existing member comment.

Automated hermes-sweeper review.

Comment thread hermes_constants.py
if mount_point == "/" and any(
marker in line.lower() for marker in runtime_markers
):
return True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scans the complete root-mount row, including the mount source. A host root such as /dev/mapper/docker--vg-root would match docker even though that names the backing device rather than a container runtime. Parse mountinfo and restrict the probe to the filesystem-root field and super options after -.

@teknium1 teknium1 added the sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform label Jul 18, 2026
@the3asic

Copy link
Copy Markdown
Contributor Author

Scope note from the triage pointer to #58141 / #65060: both of those change is_container() itself (root-mount-only cgroup-v2 fallback, and broader structural checks). This PR is narrower and upstream of that decision point: it only ignores child mounts when scanning /proc/self/mountinfo in _running_in_container_runtime() — i.e. it fixes the false "you are inside a container" signal from bind-mounted children on a host that runs containers (dev boxes with Docker, Proxmox LXC hosts with nesting), without touching is_container() or its cgroup heuristics at all. So it does not overlap their diff; if one of them lands and the maintainers prefer consolidating detection strategy, this change composes with either (child-mount filtering is orthogonal to how the root mount is classified). Happy to rebase onto whichever lands first, or to fold it in if you want a single container-detection PR — your call.

The root-mount scan still matched runtime markers against the whole
mountinfo line, so a host root on a backing device such as
/dev/mapper/docker--vg-root was reported as a container. Match only the
mount point, the root path, the fstype, and the super options; keep the
mount source and pre-separator device fields out of the scan. Adds the
device-name false-positive cases and a super-options true positive to
the mountinfo tests.
@the3asic

Copy link
Copy Markdown
Contributor Author

Addressed in 5626de2. Runtime-marker matching now excludes the mount-source field after the mountinfo separator, so a host root backed by a device such as /dev/mapper/docker--vg-root is not treated as a container. The root path, filesystem type, and super options remain eligible for matching, preserving the existing containerd-root and overlay lower/upper-dir detections. Regression coverage includes the reported docker-named host-device case plus a markerless-cgroup variant, and a positive super-options case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docker Docker image, Compose, packaging comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants