Skip to content

child: fix capget writing past its buffer in hasCaps - #658

Open
heppycat wants to merge 1 commit into
rootless-containers:masterfrom
heppycat:fix-capget-overflow
Open

heppycat wants to merge 1 commit into
rootless-containers:masterfrom
heppycat:fix-capget-overflow

Conversation

@heppycat

Copy link
Copy Markdown

hasCaps() calls capget with LINUX_CAPABILITY_VERSION_3 and a single unix.CapUserData. For versions 2 and 3 the kernel always writes two __user_cap_data_struct (caps 0-31 and 32-63, 24 bytes in total; see capget(2)), so it writes 12 bytes past data.

With this change the kernel's second struct shows up in the debug log, filled in (rootlesskit --debug, amd64, kernel 7.2):

Capabilities: [{Effective:4294967295 Permitted:4294967295 Inheritable:0} {Effective:511 Permitted:511 Inheritable:0}]

Those are the bytes that currently go past the end of data.

I haven't seen this crash rootlesskit. The same mistake in Xray-core's WireGuard code (XTLS/Xray-core#7274) corrupted a saved return address on 32-bit ARM and crashed the process every time, so it isn't harmless in general.

The fix passes [2]unix.CapUserData and checks the effective set of both words. Capabilities above 31, such as CAP_BPF and CAP_CHECKPOINT_RESTORE, now count too, which they didn't before.

Tested: gofmt is clean, and go vet ./pkg/child/ passes for linux/amd64, arm64, arm and 386. It builds for amd64 and arm, and runs unprivileged on amd64.

hasCaps asks for LINUX_CAPABILITY_VERSION_3, for which the kernel
always writes two CapUserData (caps 0-31 and 32-63, 24 bytes), but it
passed a single one (12 bytes), so the kernel wrote 12 bytes past it.
Pass two, and check the effective set of both.

Signed-off-by: heppycat <qls13d@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 capability-check buffer sizing and effective-capability handling changes.

No open issues 🎉

What changed in this PR

Fixes a buffer overrun in the child process’s capability check by allocating enough space for the Linux capability version 3 response.

Changes:

  • Uses a two-element CapUserData array to accommodate both capability words written by capget.
  • Checks both effective capability words, including capabilities above 31.
File Description
pkg/​child/​child.go Corrects the capget buffer size and checks the full effective capability set.

Review effort: Balanced

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