Skip to content

Add ScopedPrivileges RAII and sanitize env on elevation - #3138

Open
dxapd wants to merge 1 commit into
google:mainfrom
dxapd:nftables-privilege-raii
Open

Add ScopedPrivileges RAII and sanitize env on elevation#3138
dxapd wants to merge 1 commit into
google:mainfrom
dxapd:nftables-privilege-raii

Conversation

@dxapd

@dxapd dxapd commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

this pr does two things:

  1. create a RAII abstraction for holding elevated privileges
  2. within that abstraction, sanitize the entire provided environment, including the PATH, before elevating

not going to wire it up to cvdalloc until the final PR, though

@dxapd
dxapd marked this pull request as ready for review September 3, 2026 22:29
@dxapd
dxapd requested a review from 3405691582 September 3, 2026 22:30
@dxapd

dxapd commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

@3405691582 we can continue the discussion about whether or not the sanitization is necessary here. imo it's not a huge deal, but there's no harm in doing it given that we are using the PATH variable and also transitively conferring elevated caps onto other binaries.

Result<ScopedPrivileges> ScopedPrivileges::Elevate() {
uid_t orig = getuid();
// The child processes we exec run with elevated privilege (CAP_NET_ADMIN via
// ambient caps) but with AT_SECURE=0, so the dynamic linker won't scrub their

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we set this?


Result<ScopedPrivileges> ScopedPrivileges::Elevate() {
uid_t orig = getuid();
// The child processes we exec run with elevated privilege (CAP_NET_ADMIN via

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since this comment talks about Linux capabilities, it should probably belong in the #if block below.

// ambient caps) but with AT_SECURE=0, so the dynamic linker won't scrub their
// environment for us. Sanitize with an allowlist.
#if defined(__linux__)
// On Linux, only sanitize when this exec actually gained privilege (e.g. via

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

per the other pr, when I hear "sanitize" I think about clang's sanitizers, for example. We could still use the term if we qualified it, e.g., "only sanitize the environment when..." and "should_sanitize_env" for example.

const bool should_sanitize = getauxval(AT_SECURE) != 0;
#else
// Elsewhere we can't rely on AT_SECURE, so sanitize unconditionally.
const bool should_sanitize = true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think declaring in both branches of the #if will buy you much versus setting the default as non-const and then re-set it, then eliminate the #else branch.

const bool should_sanitize = true;
#endif
if (should_sanitize) {
CF_EXPECTF(clearenv() == 0, "Couldn't clear environment: {}",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You're hosing the environment here, but we're not saving and restoring it. Maybe it's sufficient to just force PATH?

}

namespace {
constexpr char kTrustedPath[] = "/usr/sbin:/usr/bin:/sbin:/bin";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

(this has a small possibility for future portability weirdness, but it's probably fine for now.)

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.

2 participants