Most (if not all) solvers should be able to run perfectly fine without
root privileges as they get the entire state they are supposed to work
on via stdin and do not perform any action directly, but just pass
suggestions on via stdout.
The new default is to run them all as _apt hence, but each solver can
configure another user if it chooses/must. The security benefits are
minimal at best, but it helps preventing silly mistakes (see
35f3ed061f10a25a3fb28bc988fddbb976344c4d) and that is always good.
Note that our 'apt' and 'dump' solver already dropped privileges if they
had them.
dup2(external[3], STDOUT_FILENO);
auto const dumpfile = _config->FindFile((std::string("Dir::Log::") + type).c_str());
auto const dumpdir = flNotFile(dumpfile);
dup2(external[3], STDOUT_FILENO);
auto const dumpfile = _config->FindFile((std::string("Dir::Log::") + type).c_str());
auto const dumpdir = flNotFile(dumpfile);
+ auto const runasuser = _config->Find(std::string("APT::") + type + "::" + binary + "::RunAsUser",
+ _config->Find(std::string("APT::") + type + "::RunAsUser",
+ _config->Find("APT::Sandbox::User")));
if (dumper.empty() || dumpfile.empty() || dumper == file || CreateAPTDirectoryIfNeeded(dumpdir, dumpdir) == false)
{
if (dumper.empty() || dumpfile.empty() || dumper == file || CreateAPTDirectoryIfNeeded(dumpdir, dumpdir) == false)
{
+ _config->Set("APT::Sandbox::User", runasuser);
+ DropPrivileges();
char const * const calling[] = { file.c_str(), nullptr };
execv(calling[0], const_cast<char**>(calling));
}
else
{
char const * const calling[] = { file.c_str(), nullptr };
execv(calling[0], const_cast<char**>(calling));
}
else
{
- char const * const calling[] = { dumper.c_str(), dumpfile.c_str(), file.c_str(), nullptr };
+ char const * const calling[] = { dumper.c_str(), "--user", runasuser.c_str(), dumpfile.c_str(), file.c_str(), nullptr };
execv(calling[0], const_cast<char**>(calling));
}
std::cerr << "Failed to execute " << type << " '" << binary << "'!" << std::endl;
execv(calling[0], const_cast<char**>(calling));
}
std::cerr << "Failed to execute " << type << " '" << binary << "'!" << std::endl;
APT_SENTINEL static bool strcmp_match_in_list(char const * const Cmd, ...) /*{{{*/
{
APT_SENTINEL static bool strcmp_match_in_list(char const * const Cmd, ...) /*{{{*/
{
+ if (Cmd == nullptr)
+ return false;
va_list args;
bool found = false;
va_start(args, Cmd);
va_list args;
bool found = false;
va_start(args, Cmd);
-static bool addArgumentsAPTDumpSolver(std::vector<CommandLine::Args> &, char const * const)/*{{{*/
+static bool addArgumentsAPTDumpSolver(std::vector<CommandLine::Args> &Args, char const * const)/*{{{*/
+ addArg(0,"user","APT::Solver::RunAsUser",CommandLine::HasArg);
{
std::vector<CommandLine::Args> Args;
Args.reserve(50);
{
std::vector<CommandLine::Args> Args;
Args.reserve(50);
- if (Cmd == nullptr)
- {
- if (Program == APT_CMD::APT_EXTRACTTEMPLATES)
- addArgumentsAPTExtractTemplates(Args, Cmd);
- }
- else if (strcmp(Cmd, "help") == 0)
+ if (Cmd != nullptr && strcmp(Cmd, "help") == 0)
; // no options for help so no need to implement it in each
else
switch (Program)
; // no options for help so no need to implement it in each
else
switch (Program)
Solver = ExecFork();
if (Solver == 0) {
Solver = ExecFork();
if (Solver == 0) {
+ _config->Set("APT::Sandbox::User", _config->Find("APT::Solver::RunAsUser", _config->Find("APT::Sandbox::User")));
+ DropPrivileges();
dup2(external[0], STDIN_FILENO);
execv(CmdL.FileList[1], const_cast<char**>(CmdL.FileList + 1));
std::cerr << "Failed to execute '" << CmdL.FileList[1] << "'!" << std::endl;
dup2(external[0], STDIN_FILENO);
execv(CmdL.FileList[1], const_cast<char**>(CmdL.FileList + 1));
std::cerr << "Failed to execute '" << CmdL.FileList[1] << "'!" << std::endl;
of the solver you are using if and what is supported as a value here.
Defaults to the empty string.
of the solver you are using if and what is supported as a value here.
Defaults to the empty string.
+- **APT::Solver::RunAsUser**: if APT itself is run as root it will
+ change to this user before executing the solver. Defaults to the value
+ of APT::Sandbox::User, which itself defaults to `_apt`. Can be
+ disabled by set this option to `root`.
+
The options **Strict-Pinning** and **Preferences** can also be set for
a specific solver only via **APT::Solver::NAME::Strict-Pinning** and
**APT::Solver::NAME::Preferences** respectively where `NAME` is the name
The options **Strict-Pinning** and **Preferences** can also be set for
a specific solver only via **APT::Solver::NAME::Strict-Pinning** and
**APT::Solver::NAME::Preferences** respectively where `NAME` is the name
# destroys coverage reporting though, so we disable changing user for the calling gpgv
echo "Dir::Bin::apt-key \"${BUILDDIRECTORY}/apt-key\";" >> aptconfig.conf
if [ "$(id -u)" = '0' ]; then
# destroys coverage reporting though, so we disable changing user for the calling gpgv
echo "Dir::Bin::apt-key \"${BUILDDIRECTORY}/apt-key\";" >> aptconfig.conf
if [ "$(id -u)" = '0' ]; then
- echo 'Binary::gpgv::Debug::NoDropPrivs "true";' >>aptconfig.conf
+ echo 'Binary::gpgv::APT::Sandbox::User "root";' >> aptconfig.conf
+ # same for the solver executables
+ echo 'APT::Solver::RunAsUser "root";' >> aptconfig.conf
fi
cat > "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" <<EOF
fi
cat > "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" <<EOF