summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-08-24 09:47:48 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-08-24 10:24:41 +0200
commit2e2865ae53a65c00dd55a892d5b48458f3110366 (patch)
tree75547baee53574ba399f179b7a62ab651e8cf7c0 /apt-pkg
parentac103d45f63bd9a57ff867a52c7c95616f6daf51 (diff)
do fail on weakhash/loop earlier in acquire
The bugreport shows a segfault caused by the code not doing the correct magical dance to remove an item from inside a queue in all cases. We could try hard to fix this, but it is actually better and also easier to perform these checks (which cause instant failure) earlier so that they haven't entered queue(s) yet, which in return makes cleanup trivial. The result is that we actually end up failing "too early" as if we wouldn't be careful download errors would be logged before that process was even started. Not a problem for the acquire system, but likely to confuse users and programs alike if they see the download process producing errors before apt was technically allowed to do an acquire (it didn't, so no violation, but it looks like it to the untrained eye). Closes: 835195
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire-item.cc3
-rw-r--r--apt-pkg/acquire-worker.cc42
-rw-r--r--apt-pkg/acquire.cc59
3 files changed, 58 insertions, 46 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 7abb7b206..7fbbf08f8 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -3279,9 +3279,8 @@ bool pkgAcqArchive::QueueNext()
// Create the item
Local = false;
- QueueURI(Desc);
-
++Vf;
+ QueueURI(Desc);
return true;
}
return false;
diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc
index a4fbc7651..5b6634db8 100644
--- a/apt-pkg/acquire-worker.cc
+++ b/apt-pkg/acquire-worker.cc
@@ -661,55 +661,15 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
if (OutFd == -1)
return false;
- HashStringList const hsl = Item->GetExpectedHashes();
-
if (isDoomedItem(Item->Owner))
return true;
- if (hsl.usable() == false && Item->Owner->HashesRequired() &&
- _config->Exists("Acquire::ForceHash") == false)
- {
- std::string const Message = "400 URI Failure"
- "\nURI: " + Item->URI +
- "\nFilename: " + Item->Owner->DestFile +
- "\nFailReason: WeakHashSums";
-
- auto const ItmOwners = Item->Owners;
- for (auto &O: ItmOwners)
- {
- O->Status = pkgAcquire::Item::StatAuthError;
- O->Failed(Message, Config);
- if (Log != nullptr)
- Log->Fail(O->GetItemDesc());
- }
- // "queued" successfully, the item just instantly failed
- return true;
- }
-
- if (Item->Owner->IsRedirectionLoop(Item->URI))
- {
- std::string const Message = "400 URI Failure"
- "\nURI: " + Item->URI +
- "\nFilename: " + Item->Owner->DestFile +
- "\nFailReason: RedirectionLoop";
-
- auto const ItmOwners = Item->Owners;
- for (auto &O: ItmOwners)
- {
- O->Status = pkgAcquire::Item::StatError;
- O->Failed(Message, Config);
- if (Log != nullptr)
- Log->Fail(O->GetItemDesc());
- }
- // "queued" successfully, the item just instantly failed
- return true;
- }
-
string Message = "600 URI Acquire\n";
Message.reserve(300);
Message += "URI: " + Item->URI;
Message += "\nFilename: " + Item->Owner->DestFile;
+ HashStringList const hsl = Item->GetExpectedHashes();
for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs)
Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue();
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc
index 1efb772b4..affc0c791 100644
--- a/apt-pkg/acquire.cc
+++ b/apt-pkg/acquire.cc
@@ -269,6 +269,42 @@ void pkgAcquire::Remove(Worker *Work)
it is constructed which creates a queue (based on the current queue
mode) and puts the item in that queue. If the system is running then
the queue might be started. */
+static bool DoesAcquireResultInInstantFailure(pkgAcquire::Item * const Item,
+ pkgAcquire::MethodConfig const * const Config, pkgAcquireStatus * const Log)
+{
+ auto SavedDesc = Item->GetItemDesc();
+ if (Item->IsRedirectionLoop(SavedDesc.URI))
+ {
+ std::string const Message = "400 URI Failure"
+ "\nURI: " + SavedDesc.URI +
+ "\nFilename: " + Item->DestFile +
+ "\nFailReason: RedirectionLoop";
+
+ Item->Status = pkgAcquire::Item::StatError;
+ Item->Failed(Message, Config);
+ if (Log != nullptr)
+ Log->Fail(SavedDesc);
+ return true;
+ }
+
+ HashStringList const hsl = Item->GetExpectedHashes();
+ if (hsl.usable() == false && Item->HashesRequired() &&
+ _config->Exists("Acquire::ForceHash") == false)
+ {
+ std::string const Message = "400 URI Failure"
+ "\nURI: " + SavedDesc.URI +
+ "\nFilename: " + Item->DestFile +
+ "\nFailReason: WeakHashSums";
+
+ auto SavedDesc = Item->GetItemDesc();
+ Item->Status = pkgAcquire::Item::StatAuthError;
+ Item->Failed(Message, Config);
+ if (Log != nullptr)
+ Log->Fail(SavedDesc);
+ return true;
+ }
+ return false;
+}
void pkgAcquire::Enqueue(ItemDesc &Item)
{
// Determine which queue to put the item in
@@ -277,6 +313,13 @@ void pkgAcquire::Enqueue(ItemDesc &Item)
if (Name.empty() == true)
return;
+ /* the check for running avoids that we produce errors
+ in logging before we actually have started, which would
+ be easier to implement but would confuse users/implementations
+ so we check the items skipped here in #Startup */
+ if (Running && DoesAcquireResultInInstantFailure(Item.Owner, Config, Log))
+ return;
+
// Find the queue structure
Queue *I = Queues;
for (; I != 0 && I->Name != Name; I = I->Next);
@@ -912,10 +955,20 @@ bool pkgAcquire::Queue::Startup()
if (Workers == 0)
{
URI U(Name);
- pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(U.Access);
- if (Cnf == 0)
+ pkgAcquire::MethodConfig * const Cnf = Owner->GetConfig(U.Access);
+ if (unlikely(Cnf == nullptr))
return false;
-
+
+ // now-running twin of the pkgAcquire::Enqueue call
+ for (QItem *I = Items; I != 0; )
+ {
+ bool pointless = false;
+ for (auto &&O: I->Owners)
+ if (DoesAcquireResultInInstantFailure(O, Cnf, Owner->Log))
+ pointless = true;
+ I = pointless ? Items : I->Next;
+ }
+
Workers = new Worker(this,Cnf,Owner->Log);
Owner->Add(Workers);
if (Workers->Start() == false)