Skip to content

capability: Load: read status of the current thread - #273

Merged
thaJeztah merged 1 commit into
moby:mainfrom
kolyshkin:cap-thread-self
Oct 28, 2026
Merged

thaJeztah merged 1 commit into
moby:mainfrom
kolyshkin:cap-thread-self

Conversation

@kolyshkin

Copy link
Copy Markdown
Collaborator

Capabilities (including ambient ones) are per-thread, and capget(2) with pid of 0, as well as Apply, operate on the calling thread. Yet, Load reads ambient and bounding sets from /proc/self/status, which describes the thread group leader (the main thread).

As a result, if Load is called from a thread other than the main one (e.g. a goroutine which did runtime.LockOSThread), it returns ambient and bounding sets of the main thread, not the current one. This is the cause of occasional TestAmbientCapSet failures in CI (e.g. https://github.com/moby/sys/actions/runs/40385946276/job/121794105561):

capability_test.go:171: Get(AMBIENT, kill): want true, got false

Fix this by reading /proc/thread-self/status, with fallbacks to /proc/self/task/<tid>/status (for pre-3.17 kernels) and /proc/self/status (when our pid namespace differs from that of /proc), similar to what mountinfo does. Also, lock the OS thread in Load so that capget and the status file refer to the same thread.

To make the test failure deterministic rather than occasional, lock the main goroutine of a test helper process to the main thread, so that tests never run on it. With this test change but without the fix, TestAmbientCapSet fails 20 out of 20 runs; with the fix, it passes.

Capabilities (including ambient ones) are per-thread, and capget(2)
with pid of 0, as well as Apply, operate on the calling thread.
Yet, Load reads ambient and bounding sets from /proc/self/status,
which describes the thread group leader (the main thread).

As a result, if Load is called from a thread other than the main one
(e.g. a goroutine which did runtime.LockOSThread), it returns ambient
and bounding sets of the main thread, not the current one. This is
the cause of occasional TestAmbientCapSet failures in CI:

	capability_test.go:171: Get(AMBIENT, kill): want true, got false

Fix this by reading /proc/thread-self/status, with fallbacks to
/proc/self/task/<tid>/status (for pre-3.17 kernels) and
/proc/self/status (when our pid namespace differs from that of
/proc), similar to what mountinfo does. Also, lock the OS thread
in Load so that capget and the status file refer to the same thread.

To make the test failure deterministic rather than occasional, lock
the main goroutine of a test helper process to the main thread, so
that tests never run on it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No active review issues were identified for the calling-thread capability loading fix.

No open issues 🎉

What changed in this PR

Fixes capability loading so ambient and bounding sets reflect the calling thread rather than the main thread.

Changes:

  • Reads the current thread’s status with fallbacks for older kernels and PID namespace mismatches.
  • Locks the OS thread during current-thread loading to keep capability reads consistent.
  • Makes the test setup reliably exercise non-main threads and documents the fix.
File Description
capability/​CHANGELOG.md Documents the current-thread capability loading fix.
capability/​capability_test.go Pins the helper process’s main goroutine so tests run on other threads.
capability/​capability_linux.go Adds thread-specific status lookup, fallbacks, and OS-thread locking during loading.

Review effort: Balanced

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@thaJeztah
thaJeztah merged commit 021f596 into moby:main Oct 28, 2026
25 checks passed
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.

3 participants