diff options
author | David Kalnischkies <david@kalnischkies.de> | 2015-08-31 11:00:12 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2015-08-31 11:00:12 +0200 |
commit | 7c8206bf26b8ef6020b543bbc027305dee8f2308 (patch) | |
tree | 0a2df6cb2f5979735a9532ea61e11fa2207793f4 /apt-pkg/acquire.cc | |
parent | dd6da7d2392e2ad35c444ebc2d7bc2308380530c (diff) |
if file is inaccessible for _apt, disable privilege drop in acquire
We had a very similar method previously for our own private usage, but
with some generalisation we can move this check into the acquire system
proper so that all frontends profit from this compatibility change.
As we are disabling a security feature here a warning is issued and
frontends are advised to consider reworking their download logic if
possible.
Note that this is implemented as an all or nothing situation: We can't
just (not) drop privileges for a subset of the files in a fetcher, so in
case you have to download some files with and some without you need to
use two fetchers.
Diffstat (limited to 'apt-pkg/acquire.cc')
-rw-r--r-- | apt-pkg/acquire.cc | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index f8b077367..cb32e8f2b 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -34,6 +34,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <fcntl.h> #include <pwd.h> #include <grp.h> #include <dirent.h> @@ -446,8 +447,58 @@ void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet) /* This runs the queues. It manages a select loop for all of the Worker tasks. The workers interact with the queues and items to manage the actual fetch. */ +static void CheckDropPrivsMustBeDisabled(pkgAcquire const &Fetcher) +{ + if(getuid() != 0) + return; + + std::string SandboxUser = _config->Find("APT::Sandbox::User"); + if (SandboxUser.empty()) + return; + + struct passwd const * const pw = getpwnam(SandboxUser.c_str()); + if (pw == NULL) + return; + + if (setegid(pw->pw_gid) != 0) + _error->Errno("setegid", "setegid %u failed", pw->pw_gid); + if (seteuid(pw->pw_uid) != 0) + _error->Errno("seteuid", "seteuid %u failed", pw->pw_uid); + + bool dropPrivs = true; + for (pkgAcquire::ItemCIterator I = Fetcher.ItemsBegin(); + I != Fetcher.ItemsEnd() && dropPrivs == true; ++I) + { + if ((*I)->DestFile.empty()) + continue; + + // we check directory instead of file as the file might or might not + // exist already as a link or not which complicates everything… + std::string dirname = flNotFile((*I)->DestFile); + if (DirectoryExists(dirname)) + ; + else + continue; // assume it is created correctly by the acquire system + + if (faccessat(AT_FDCWD, dirname.c_str(), R_OK | W_OK | X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) != 0) + { + dropPrivs = false; + _error->WarningE("pkgAcquire::Run", _("Can't drop privileges for downloading as file '%s' couldn't be accessed by user '%s'."), + (*I)->DestFile.c_str(), SandboxUser.c_str()); + _config->Set("APT::Sandbox::User", ""); + break; + } + } + + if (seteuid(0) != 0) + _error->Errno("seteuid", "seteuid %u failed", 0); + if (setegid(0) != 0) + _error->Errno("setegid", "setegid %u failed", 0); +} pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) { + CheckDropPrivsMustBeDisabled(*this); + Running = true; for (Queue *I = Queues; I != 0; I = I->Next) |