Files
slocker-lite/src/user_spec.h
T
ceamac 247e61d9d8 Add --user/--group support to -e/--exec, matching -r/--run
Previously -e/--exec always ran its command as the host's own invoking
credentials, ignoring whatever uid/gid the session's own -r/--run resolved
it to. Now it defaults to whatever the session's sandboxed command is
already running as (read from /proc/<pid>/status), and --user/--group can
override that, resolved against the session's own /etc/passwd/group
(fetched via nsenter, since the mount namespace isn't otherwise reachable).
Either way it's applied by reusing the already bind-mounted
slocker-lite-priv-drop helper from the original -r/--run, not a second copy.

Refactored resolve_user_and_group() (user_spec.{h,cpp}) to take passwd/group
*content* instead of a filesystem path, so both callers -- run_container()
(local file read) and exec_in_session() (nsenter + cat) -- can share it.
Exported priv_drop::path/helper_name and find_priv_drop_helper() from
bwrap.h so exec_session.cpp can reuse the same helper.

Caught and fixed a second bug during testing on a rootless dev machine:
under -r/--run's own --unshare-user, "root inside the container" is a uid
mapping, not a real privilege drop, so /proc/<pid>/status's uid/gid (read
from outside that namespace) is the host-mapped id, not the container's
own view -- defaulting to a priv-drop there was wrong and failed outright.
Fixed by skipping the default-identity lookup whenever --exec is already
joining a differing user namespace, since nsenter --preserve-credentials
alone already reproduces the container's view via that same kernel mapping.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
2026-08-29 08:05:55 +00:00

40 lines
2.1 KiB
C++

// Copyright (C) 2026 Viorel Munteanu
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <optional>
#include <string>
#include "bwrap.h"
// Resolves --user (name or numeric uid) and --group (optional, name or numeric gid)
// against the container's own /etc/passwd and /etc/group *content* -- NOT the
// host's. Callers are responsible for obtaining that content however is
// appropriate for them: run_container() (commands.cpp) reads it directly off the
// merged mount path, while exec_in_session() (exec_session.cpp) fetches it via
// nsenter, since a running session's mount namespace isn't otherwise reachable
// from this process. `nullopt` for either means "file unreadable/absent" -- a
// numeric `user`/`group` still resolves fine without it (see below); a named one
// doesn't. A numeric `user` with no `group` and no matching /etc/passwd entry
// defaults gid to the same numeric value as the uid; a named `user` always
// requires a resolvable /etc/passwd entry (for its uid and default gid). Logs a
// specific error and returns nullopt if a named user/group can't be resolved.
std::optional<ResolvedUser> resolve_user_and_group(const std::string& user,
const std::optional<std::string>& group,
const std::optional<std::string>& passwd_content,
const std::optional<std::string>& group_content);