X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/245dde96193702f7f51389d3583dee547f8ba366..cd46d4ebd33e74ee53bbc73dcdb7fe1d4d006558:/apt-pkg/acquire.cc diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 75df858a8..a74f1c2f6 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +43,6 @@ #include #include #include -#include #include /*}}}*/ @@ -51,13 +52,13 @@ using namespace std; // Acquire::pkgAcquire - Constructor /*{{{*/ // --------------------------------------------------------------------- /* We grab some runtime state from the configuration space */ -pkgAcquire::pkgAcquire() : LockFD(-1), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), +pkgAcquire::pkgAcquire() : LockFD(-1), d(NULL), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), Debug(_config->FindB("Debug::pkgAcquire",false)), Running(false) { Initialize(); } -pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : LockFD(-1), Queues(0), Workers(0), +pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : LockFD(-1), d(NULL), Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), Debug(_config->FindB("Debug::pkgAcquire",false)), Running(false) @@ -447,8 +448,71 @@ 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; + + gid_t const old_euid = geteuid(); + gid_t const old_egid = getegid(); + 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); + + for (pkgAcquire::ItemCIterator I = Fetcher.ItemsBegin(); + I != Fetcher.ItemsEnd(); ++I) + { + std::string filename = (*I)->DestFile; + if (filename.empty()) + continue; + + // no need to drop privileges for a complete file + if ((*I)->Complete == true) + 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(filename); + if (unlikely(dirname.empty())) + continue; + // translate relative to absolute for DirectoryExists + // FIXME: What about ../ and ./../ ? + if (dirname.substr(0,2) == "./") + dirname = SafeGetCWD() + dirname.substr(2); + + if (DirectoryExists(dirname)) + ; + else + continue; // assume it is created correctly by the acquire system + + if (faccessat(-1, dirname.c_str(), R_OK | W_OK | X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) != 0) + { + _error->WarningE("pkgAcquire::Run", _("Can't drop privileges for downloading as file '%s' couldn't be accessed by user '%s'."), + filename.c_str(), SandboxUser.c_str()); + _config->Set("APT::Sandbox::User", ""); + break; + } + } + + if (seteuid(old_euid) != 0) + _error->Errno("seteuid", "seteuid %u failed", old_euid); + if (setegid(old_egid) != 0) + _error->Errno("setegid", "setegid %u failed", old_egid); +} pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) { + _error->PushToStack(); + CheckDropPrivsMustBeDisabled(*this); + Running = true; for (Queue *I = Queues; I != 0; I = I->Next) @@ -484,11 +548,9 @@ pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) _error->Errno("select","Select has failed"); break; } - + RunFds(&RFds,&WFds); - if (_error->PendingError() == true) - break; - + // Timeout, notify the log class if (Res == 0 || (Log != 0 && Log->Update == true)) { @@ -513,9 +575,11 @@ pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) // Shut down the items for (ItemIterator I = Items.begin(); I != Items.end(); ++I) - (*I)->Finished(); - - if (_error->PendingError()) + (*I)->Finished(); + + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + if (newError) return Failed; if (WasCancelled) return Cancelled; @@ -595,10 +659,10 @@ bool pkgAcquire::Clean(string Dir) /* This is the total number of bytes needed */ APT_PURE unsigned long long pkgAcquire::TotalNeeded() { - unsigned long long Total = 0; - for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); ++I) - Total += (*I)->FileSize; - return Total; + return std::accumulate(ItemsBegin(), ItemsEnd(), 0, + [](unsigned long long const T, Item const * const I) { + return T + I->FileSize; + }); } /*}}}*/ // Acquire::FetchNeeded - Number of bytes needed to get /*{{{*/ @@ -606,11 +670,13 @@ APT_PURE unsigned long long pkgAcquire::TotalNeeded() /* This is the number of bytes that is not local */ APT_PURE unsigned long long pkgAcquire::FetchNeeded() { - unsigned long long Total = 0; - for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); ++I) - if ((*I)->Local == false) - Total += (*I)->FileSize; - return Total; + return std::accumulate(ItemsBegin(), ItemsEnd(), 0, + [](unsigned long long const T, Item const * const I) { + if (I->Local == false) + return T + I->FileSize; + else + return T; + }); } /*}}}*/ // Acquire::PartialPresent - Number of partial bytes we already have /*{{{*/ @@ -618,11 +684,13 @@ APT_PURE unsigned long long pkgAcquire::FetchNeeded() /* This is the number of bytes that is not local */ APT_PURE unsigned long long pkgAcquire::PartialPresent() { - unsigned long long Total = 0; - for (ItemCIterator I = ItemsBegin(); I != ItemsEnd(); ++I) - if ((*I)->Local == false) - Total += (*I)->PartialSize; - return Total; + return std::accumulate(ItemsBegin(), ItemsEnd(), 0, + [](unsigned long long const T, Item const * const I) { + if (I->Local == false) + return T + I->PartialSize; + else + return T; + }); } /*}}}*/ // Acquire::UriBegin - Start iterator for the uri list /*{{{*/ @@ -653,8 +721,8 @@ pkgAcquire::MethodConfig::MethodConfig() : d(NULL), Next(0), SingleInstance(fals // Queue::Queue - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquire::Queue::Queue(string Name,pkgAcquire *Owner) : d(NULL), Next(0), - Name(Name), Items(0), Workers(0), Owner(Owner), PipeDepth(0), MaxPipeDepth(1) +pkgAcquire::Queue::Queue(string const &name,pkgAcquire * const owner) : d(NULL), Next(0), + Name(name), Items(0), Workers(0), Owner(owner), PipeDepth(0), MaxPipeDepth(1) { } /*}}}*/ @@ -846,8 +914,8 @@ bool pkgAcquire::Queue::Cycle() return true; I->Worker = Workers; - for (QItem::owner_iterator O = I->Owners.begin(); O != I->Owners.end(); ++O) - (*O)->Status = pkgAcquire::Item::StatFetching; + for (auto const &O: I->Owners) + O->Status = pkgAcquire::Item::StatFetching; PipeDepth++; if (Workers->QueueItem(I) == false) return false; @@ -899,11 +967,11 @@ HashStringList pkgAcquire::Queue::QItem::GetExpectedHashes() const /*{{{*/ APT_PURE unsigned long long pkgAcquire::Queue::QItem::GetMaximumSize() const /*{{{*/ { unsigned long long Maximum = std::numeric_limits::max(); - for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + for (auto const &O: Owners) { - if ((*O)->FileSize == 0) + if (O->FileSize == 0) continue; - Maximum = std::min(Maximum, (*O)->FileSize); + Maximum = std::min(Maximum, O->FileSize); } if (Maximum == std::numeric_limits::max()) return 0;