omaha_response_handler_action.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //
  2. // Copyright (C) 2011 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/omaha_response_handler_action.h"
  17. #include <limits>
  18. #include <string>
  19. #include <base/logging.h>
  20. #include <base/strings/string_number_conversions.h>
  21. #include <policy/device_policy.h>
  22. #include "update_engine/common/constants.h"
  23. #include "update_engine/common/hardware_interface.h"
  24. #include "update_engine/common/prefs_interface.h"
  25. #include "update_engine/common/utils.h"
  26. #include "update_engine/connection_manager_interface.h"
  27. #include "update_engine/omaha_request_params.h"
  28. #include "update_engine/payload_consumer/delta_performer.h"
  29. #include "update_engine/payload_state_interface.h"
  30. #include "update_engine/update_manager/policy.h"
  31. #include "update_engine/update_manager/update_manager.h"
  32. using chromeos_update_manager::Policy;
  33. using chromeos_update_manager::UpdateManager;
  34. using std::numeric_limits;
  35. using std::string;
  36. namespace chromeos_update_engine {
  37. OmahaResponseHandlerAction::OmahaResponseHandlerAction(
  38. SystemState* system_state)
  39. : system_state_(system_state),
  40. deadline_file_(constants::kOmahaResponseDeadlineFile) {}
  41. void OmahaResponseHandlerAction::PerformAction() {
  42. CHECK(HasInputObject());
  43. ScopedActionCompleter completer(processor_, this);
  44. const OmahaResponse& response = GetInputObject();
  45. if (!response.update_exists) {
  46. LOG(INFO) << "There are no updates. Aborting.";
  47. completer.set_code(ErrorCode::kNoUpdate);
  48. return;
  49. }
  50. // All decisions as to which URL should be used have already been done. So,
  51. // make the current URL as the download URL.
  52. string current_url = system_state_->payload_state()->GetCurrentUrl();
  53. if (current_url.empty()) {
  54. // This shouldn't happen as we should always supply the HTTPS backup URL.
  55. // Handling this anyway, just in case.
  56. LOG(ERROR) << "There are no suitable URLs in the response to use.";
  57. completer.set_code(ErrorCode::kOmahaResponseInvalid);
  58. return;
  59. }
  60. // This is the url to the first package, not all packages.
  61. install_plan_.download_url = current_url;
  62. install_plan_.version = response.version;
  63. install_plan_.system_version = response.system_version;
  64. OmahaRequestParams* const params = system_state_->request_params();
  65. PayloadStateInterface* const payload_state = system_state_->payload_state();
  66. // If we're using p2p to download and there is a local peer, use it.
  67. if (payload_state->GetUsingP2PForDownloading() &&
  68. !payload_state->GetP2PUrl().empty()) {
  69. LOG(INFO) << "Replacing URL " << install_plan_.download_url
  70. << " with local URL " << payload_state->GetP2PUrl()
  71. << " since p2p is enabled.";
  72. install_plan_.download_url = payload_state->GetP2PUrl();
  73. payload_state->SetUsingP2PForDownloading(true);
  74. }
  75. // Fill up the other properties based on the response.
  76. string update_check_response_hash;
  77. for (const auto& package : response.packages) {
  78. brillo::Blob raw_hash;
  79. if (!base::HexStringToBytes(package.hash, &raw_hash)) {
  80. LOG(ERROR) << "Failed to convert payload hash from hex string to bytes: "
  81. << package.hash;
  82. completer.set_code(ErrorCode::kOmahaResponseInvalid);
  83. return;
  84. }
  85. install_plan_.payloads.push_back(
  86. {.size = package.size,
  87. .metadata_size = package.metadata_size,
  88. .metadata_signature = package.metadata_signature,
  89. .hash = raw_hash,
  90. .type = package.is_delta ? InstallPayloadType::kDelta
  91. : InstallPayloadType::kFull});
  92. update_check_response_hash += package.hash + ":";
  93. }
  94. install_plan_.public_key_rsa = response.public_key_rsa;
  95. install_plan_.hash_checks_mandatory = AreHashChecksMandatory(response);
  96. install_plan_.is_resume = DeltaPerformer::CanResumeUpdate(
  97. system_state_->prefs(), update_check_response_hash);
  98. if (install_plan_.is_resume) {
  99. payload_state->UpdateResumed();
  100. } else {
  101. payload_state->UpdateRestarted();
  102. LOG_IF(WARNING,
  103. !DeltaPerformer::ResetUpdateProgress(system_state_->prefs(), false))
  104. << "Unable to reset the update progress.";
  105. LOG_IF(WARNING,
  106. !system_state_->prefs()->SetString(kPrefsUpdateCheckResponseHash,
  107. update_check_response_hash))
  108. << "Unable to save the update check response hash.";
  109. }
  110. if (params->is_install()) {
  111. install_plan_.target_slot = system_state_->boot_control()->GetCurrentSlot();
  112. install_plan_.source_slot = BootControlInterface::kInvalidSlot;
  113. } else {
  114. install_plan_.source_slot = system_state_->boot_control()->GetCurrentSlot();
  115. install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0;
  116. }
  117. // The Omaha response doesn't include the channel name for this image, so we
  118. // use the download_channel we used during the request to tag the target slot.
  119. // This will be used in the next boot to know the channel the image was
  120. // downloaded from.
  121. string current_channel_key =
  122. kPrefsChannelOnSlotPrefix + std::to_string(install_plan_.target_slot);
  123. system_state_->prefs()->SetString(current_channel_key,
  124. params->download_channel());
  125. // Checking whether device is able to boot up the returned rollback image.
  126. if (response.is_rollback) {
  127. if (!params->rollback_allowed()) {
  128. LOG(ERROR) << "Received rollback image but rollback is not allowed.";
  129. completer.set_code(ErrorCode::kOmahaResponseInvalid);
  130. return;
  131. }
  132. auto min_kernel_key_version = static_cast<uint32_t>(
  133. system_state_->hardware()->GetMinKernelKeyVersion());
  134. auto min_firmware_key_version = static_cast<uint32_t>(
  135. system_state_->hardware()->GetMinFirmwareKeyVersion());
  136. uint32_t kernel_key_version =
  137. static_cast<uint32_t>(response.rollback_key_version.kernel_key) << 16 |
  138. static_cast<uint32_t>(response.rollback_key_version.kernel);
  139. uint32_t firmware_key_version =
  140. static_cast<uint32_t>(response.rollback_key_version.firmware_key)
  141. << 16 |
  142. static_cast<uint32_t>(response.rollback_key_version.firmware);
  143. // Don't attempt a rollback if the versions are incompatible or the
  144. // target image does not specify the version information.
  145. if (kernel_key_version == numeric_limits<uint32_t>::max() ||
  146. firmware_key_version == numeric_limits<uint32_t>::max() ||
  147. kernel_key_version < min_kernel_key_version ||
  148. firmware_key_version < min_firmware_key_version) {
  149. LOG(ERROR) << "Device won't be able to boot up the rollback image.";
  150. completer.set_code(ErrorCode::kRollbackNotPossible);
  151. return;
  152. }
  153. install_plan_.is_rollback = true;
  154. }
  155. if (response.powerwash_required || params->ShouldPowerwash())
  156. install_plan_.powerwash_required = true;
  157. TEST_AND_RETURN(HasOutputPipe());
  158. if (HasOutputPipe())
  159. SetOutputObject(install_plan_);
  160. LOG(INFO) << "Using this install plan:";
  161. install_plan_.Dump();
  162. // Send the deadline data (if any) to Chrome through a file. This is a pretty
  163. // hacky solution but should be OK for now.
  164. //
  165. // TODO(petkov): Re-architect this to avoid communication through a
  166. // file. Ideally, we would include this information in D-Bus's GetStatus
  167. // method and UpdateStatus signal. A potential issue is that update_engine may
  168. // be unresponsive during an update download.
  169. if (!deadline_file_.empty()) {
  170. if (payload_state->GetRollbackHappened()) {
  171. // Don't do forced update if rollback has happened since the last update
  172. // check where policy was present.
  173. LOG(INFO) << "Not forcing update because a rollback happened.";
  174. utils::WriteFile(deadline_file_.c_str(), nullptr, 0);
  175. } else {
  176. utils::WriteFile(deadline_file_.c_str(),
  177. response.deadline.data(),
  178. response.deadline.size());
  179. }
  180. chmod(deadline_file_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  181. }
  182. // Check the generated install-plan with the Policy to confirm that
  183. // it can be applied at this time (or at all).
  184. UpdateManager* const update_manager = system_state_->update_manager();
  185. CHECK(update_manager);
  186. auto ec = ErrorCode::kSuccess;
  187. update_manager->PolicyRequest(
  188. &Policy::UpdateCanBeApplied, &ec, &install_plan_);
  189. completer.set_code(ec);
  190. }
  191. bool OmahaResponseHandlerAction::AreHashChecksMandatory(
  192. const OmahaResponse& response) {
  193. // We sometimes need to waive the hash checks in order to download from
  194. // sources that don't provide hashes, such as dev server.
  195. // At this point UpdateAttempter::IsAnyUpdateSourceAllowed() has already been
  196. // checked, so an unofficial update URL won't get this far unless it's OK to
  197. // use without a hash. Additionally, we want to always waive hash checks on
  198. // unofficial builds (i.e. dev/test images).
  199. // The end result is this:
  200. // * Base image:
  201. // - Official URLs require a hash.
  202. // - Unofficial URLs only get this far if the IsAnyUpdateSourceAllowed()
  203. // devmode/debugd checks pass, in which case the hash is waived.
  204. // * Dev/test image:
  205. // - Any URL is allowed through with no hash checking.
  206. if (!system_state_->request_params()->IsUpdateUrlOfficial() ||
  207. !system_state_->hardware()->IsOfficialBuild()) {
  208. // Still do a hash check if a public key is included.
  209. if (!response.public_key_rsa.empty()) {
  210. // The autoupdate_CatchBadSignatures test checks for this string
  211. // in log-files. Keep in sync.
  212. LOG(INFO) << "Mandating payload hash checks since Omaha Response "
  213. << "for unofficial build includes public RSA key.";
  214. return true;
  215. } else {
  216. LOG(INFO) << "Waiving payload hash checks for unofficial update URL.";
  217. return false;
  218. }
  219. }
  220. LOG(INFO) << "Mandating hash checks for official URL on official build.";
  221. return true;
  222. }
  223. } // namespace chromeos_update_engine