1 // 2 // Copyright (C) 2014 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 17 #include "update_engine/update_manager/chromeos_policy.h" 18 19 #include <algorithm> 20 #include <set> 21 #include <string> 22 #include <vector> 23 24 #include <base/logging.h> 25 #include <base/strings/string_util.h> 26 #include <base/time/time.h> 27 28 #include "update_engine/common/error_code.h" 29 #include "update_engine/common/error_code_utils.h" 30 #include "update_engine/common/utils.h" 31 #include "update_engine/update_manager/device_policy_provider.h" 32 #include "update_engine/update_manager/enough_slots_ab_updates_policy_impl.h" 33 #include "update_engine/update_manager/enterprise_device_policy_impl.h" 34 #include "update_engine/update_manager/interactive_update_policy_impl.h" 35 #include "update_engine/update_manager/official_build_check_policy_impl.h" 36 #include "update_engine/update_manager/out_of_box_experience_policy_impl.h" 37 #include "update_engine/update_manager/policy_utils.h" 38 #include "update_engine/update_manager/shill_provider.h" 39 40 using base::Time; 41 using base::TimeDelta; 42 using chromeos_update_engine::ConnectionTethering; 43 using chromeos_update_engine::ConnectionType; 44 using chromeos_update_engine::ErrorCode; 45 using chromeos_update_engine::InstallPlan; 46 using std::get; 47 using std::min; 48 using std::set; 49 using std::string; 50 using std::vector; 51 52 namespace { 53 54 // Examines |err_code| and decides whether the URL index needs to be advanced, 55 // the error count for the URL incremented, or none of the above. In the first 56 // case, returns true; in the second case, increments |*url_num_error_p| and 57 // returns false; otherwise just returns false. 58 // 59 // TODO(garnold) Adapted from PayloadState::UpdateFailed() (to be retired). 60 bool HandleErrorCode(ErrorCode err_code, int* url_num_error_p) { 61 err_code = chromeos_update_engine::utils::GetBaseErrorCode(err_code); 62 switch (err_code) { 63 // Errors which are good indicators of a problem with a particular URL or 64 // the protocol used in the URL or entities in the communication channel 65 // (e.g. proxies). We should try the next available URL in the next update 66 // check to quickly recover from these errors. 67 case ErrorCode::kPayloadHashMismatchError: 68 case ErrorCode::kPayloadSizeMismatchError: 69 case ErrorCode::kDownloadPayloadVerificationError: 70 case ErrorCode::kDownloadPayloadPubKeyVerificationError: 71 case ErrorCode::kSignedDeltaPayloadExpectedError: 72 case ErrorCode::kDownloadInvalidMetadataMagicString: 73 case ErrorCode::kDownloadSignatureMissingInManifest: 74 case ErrorCode::kDownloadManifestParseError: 75 case ErrorCode::kDownloadMetadataSignatureError: 76 case ErrorCode::kDownloadMetadataSignatureVerificationError: 77 case ErrorCode::kDownloadMetadataSignatureMismatch: 78 case ErrorCode::kDownloadOperationHashVerificationError: 79 case ErrorCode::kDownloadOperationExecutionError: 80 case ErrorCode::kDownloadOperationHashMismatch: 81 case ErrorCode::kDownloadInvalidMetadataSize: 82 case ErrorCode::kDownloadInvalidMetadataSignature: 83 case ErrorCode::kDownloadOperationHashMissingError: 84 case ErrorCode::kDownloadMetadataSignatureMissingError: 85 case ErrorCode::kPayloadMismatchedType: 86 case ErrorCode::kUnsupportedMajorPayloadVersion: 87 case ErrorCode::kUnsupportedMinorPayloadVersion: 88 case ErrorCode::kPayloadTimestampError: 89 LOG(INFO) << "Advancing download URL due to error " 90 << chromeos_update_engine::utils::ErrorCodeToString(err_code) 91 << " (" << static_cast<int>(err_code) << ")"; 92 return true; 93 94 // Errors which seem to be just transient network/communication related 95 // failures and do not indicate any inherent problem with the URL itself. 96 // So, we should keep the current URL but just increment the 97 // failure count to give it more chances. This way, while we maximize our 98 // chances of downloading from the URLs that appear earlier in the response 99 // (because download from a local server URL that appears earlier in a 100 // response is preferable than downloading from the next URL which could be 101 // an Internet URL and thus could be more expensive). 102 case ErrorCode::kError: 103 case ErrorCode::kDownloadTransferError: 104 case ErrorCode::kDownloadWriteError: 105 case ErrorCode::kDownloadStateInitializationError: 106 case ErrorCode::kOmahaErrorInHTTPResponse: // Aggregate for HTTP errors. 107 LOG(INFO) << "Incrementing URL failure count due to error " 108 << chromeos_update_engine::utils::ErrorCodeToString(err_code) 109 << " (" << static_cast<int>(err_code) << ")"; 110 *url_num_error_p += 1; 111 return false; 112 113 // Errors which are not specific to a URL and hence shouldn't result in 114 // the URL being penalized. This can happen in two cases: 115 // 1. We haven't started downloading anything: These errors don't cost us 116 // anything in terms of actual payload bytes, so we should just do the 117 // regular retries at the next update check. 118 // 2. We have successfully downloaded the payload: In this case, the 119 // payload attempt number would have been incremented and would take care 120 // of the back-off at the next update check. 121 // In either case, there's no need to update URL index or failure count. 122 case ErrorCode::kOmahaRequestError: 123 case ErrorCode::kOmahaResponseHandlerError: 124 case ErrorCode::kPostinstallRunnerError: 125 case ErrorCode::kFilesystemCopierError: 126 case ErrorCode::kInstallDeviceOpenError: 127 case ErrorCode::kKernelDeviceOpenError: 128 case ErrorCode::kDownloadNewPartitionInfoError: 129 case ErrorCode::kNewRootfsVerificationError: 130 case ErrorCode::kNewKernelVerificationError: 131 case ErrorCode::kPostinstallBootedFromFirmwareB: 132 case ErrorCode::kPostinstallFirmwareRONotUpdatable: 133 case ErrorCode::kOmahaRequestEmptyResponseError: 134 case ErrorCode::kOmahaRequestXMLParseError: 135 case ErrorCode::kOmahaResponseInvalid: 136 case ErrorCode::kOmahaUpdateIgnoredPerPolicy: 137 case ErrorCode::kOmahaUpdateDeferredPerPolicy: 138 case ErrorCode::kNonCriticalUpdateInOOBE: 139 case ErrorCode::kOmahaUpdateDeferredForBackoff: 140 case ErrorCode::kPostinstallPowerwashError: 141 case ErrorCode::kUpdateCanceledByChannelChange: 142 case ErrorCode::kOmahaRequestXMLHasEntityDecl: 143 case ErrorCode::kFilesystemVerifierError: 144 case ErrorCode::kUserCanceled: 145 case ErrorCode::kUpdatedButNotActive: 146 LOG(INFO) << "Not changing URL index or failure count due to error " 147 << chromeos_update_engine::utils::ErrorCodeToString(err_code) 148 << " (" << static_cast<int>(err_code) << ")"; 149 return false; 150 151 case ErrorCode::kSuccess: // success code 152 case ErrorCode::kUmaReportedMax: // not an error code 153 case ErrorCode::kOmahaRequestHTTPResponseBase: // aggregated already 154 case ErrorCode::kDevModeFlag: // not an error code 155 case ErrorCode::kResumedFlag: // not an error code 156 case ErrorCode::kTestImageFlag: // not an error code 157 case ErrorCode::kTestOmahaUrlFlag: // not an error code 158 case ErrorCode::kSpecialFlags: // not an error code 159 // These shouldn't happen. Enumerating these explicitly here so that we 160 // can let the compiler warn about new error codes that are added to 161 // action_processor.h but not added here. 162 LOG(WARNING) << "Unexpected error " 163 << chromeos_update_engine::utils::ErrorCodeToString(err_code) 164 << " (" << static_cast<int>(err_code) << ")"; 165 // Note: Not adding a default here so as to let the compiler warn us of 166 // any new enums that were added in the .h but not listed in this switch. 167 } 168 return false; 169 } 170 171 // Checks whether |url| can be used under given download restrictions. 172 bool IsUrlUsable(const string& url, bool http_allowed) { 173 return http_allowed || 174 !base::StartsWith(url, "http://", 175 base::CompareCase::INSENSITIVE_ASCII); 176 } 177 178 } // namespace 179 180 namespace chromeos_update_manager { 181 182 const NextUpdateCheckPolicyConstants 183 ChromeOSPolicy::kNextUpdateCheckPolicyConstants = { 184 .timeout_initial_interval = 7 * 60, 185 .timeout_periodic_interval = 45 * 60, 186 .timeout_max_backoff_interval = 4 * 60 * 60, 187 .timeout_regular_fuzz = 10 * 60, 188 .attempt_backoff_max_interval_in_days = 16, 189 .attempt_backoff_fuzz_in_hours = 12, 190 }; 191 192 const int ChromeOSPolicy::kMaxP2PAttempts = 10; 193 const int ChromeOSPolicy::kMaxP2PAttemptsPeriodInSeconds = 5 * 24 * 60 * 60; 194 195 EvalStatus ChromeOSPolicy::UpdateCheckAllowed( 196 EvaluationContext* ec, State* state, string* error, 197 UpdateCheckParams* result) const { 198 // Set the default return values. 199 result->updates_enabled = true; 200 result->target_channel.clear(); 201 result->target_version_prefix.clear(); 202 result->is_interactive = false; 203 204 EnoughSlotsAbUpdatesPolicyImpl enough_slots_ab_updates_policy; 205 EnterpriseDevicePolicyImpl enterprise_device_policy; 206 OnlyUpdateOfficialBuildsPolicyImpl only_update_official_builds_policy; 207 InteractiveUpdatePolicyImpl interactive_update_policy; 208 OobePolicyImpl oobe_policy; 209 NextUpdateCheckTimePolicyImpl next_update_check_time_policy( 210 kNextUpdateCheckPolicyConstants); 211 212 vector<Policy const*> policies_to_consult = { 213 // Do not perform any updates if there are not enough slots to do A/B 214 // updates. 215 &enough_slots_ab_updates_policy, 216 217 // Check to see if Enterprise-managed (has DevicePolicy) and/or 218 // Kiosk-mode. If so, then defer to those settings. 219 &enterprise_device_policy, 220 221 // Check to see if an interactive update was requested. 222 &interactive_update_policy, 223 224 // Unofficial builds should not perform periodic update checks. 225 &only_update_official_builds_policy, 226 227 // If OOBE is enabled, wait until it is completed. 228 &oobe_policy, 229 230 // Ensure that periodic update checks are timed properly. 231 &next_update_check_time_policy, 232 }; 233 234 // Now that the list of policy implementations, and the order to consult them, 235 // has been setup, consult the policies. If none of the policies make a 236 // definitive decisions about whether or not to check for updates, then allow 237 // the update check to happen. 238 EvalStatus status = ConsultPolicies(policies_to_consult, 239 &Policy::UpdateCheckAllowed, 240 ec, 241 state, 242 error, 243 result); 244 if (EvalStatus::kContinue != status) { 245 return status; 246 } else { 247 // It is time to check for an update. 248 LOG(INFO) << "Allowing update check."; 249 return EvalStatus::kSucceeded; 250 } 251 } 252 253 EvalStatus ChromeOSPolicy::UpdateCanBeApplied(EvaluationContext* ec, 254 State* state, 255 std::string* error, 256 ErrorCode* result, 257 InstallPlan* install_plan) const { 258 *result = ErrorCode::kSuccess; 259 return EvalStatus::kSucceeded; 260 } 261 262 EvalStatus ChromeOSPolicy::UpdateCanStart( 263 EvaluationContext* ec, 264 State* state, 265 string* error, 266 UpdateDownloadParams* result, 267 const UpdateState update_state) const { 268 // Set the default return values. Note that we set persisted values (backoff, 269 // scattering) to the same values presented in the update state. The reason is 270 // that preemptive returns, such as the case where an update check is due, 271 // should not clear off the said values; rather, it is the deliberate 272 // inference of new values that should cause them to be reset. 273 result->update_can_start = false; 274 result->cannot_start_reason = UpdateCannotStartReason::kUndefined; 275 result->download_url_idx = -1; 276 result->download_url_allowed = true; 277 result->download_url_num_errors = 0; 278 result->p2p_downloading_allowed = false; 279 result->p2p_sharing_allowed = false; 280 result->do_increment_failures = false; 281 result->backoff_expiry = update_state.backoff_expiry; 282 result->scatter_wait_period = update_state.scatter_wait_period; 283 result->scatter_check_threshold = update_state.scatter_check_threshold; 284 285 // Make sure that we're not due for an update check. 286 UpdateCheckParams check_result; 287 EvalStatus check_status = UpdateCheckAllowed(ec, state, error, &check_result); 288 if (check_status == EvalStatus::kFailed) 289 return EvalStatus::kFailed; 290 bool is_check_due = (check_status == EvalStatus::kSucceeded && 291 check_result.updates_enabled == true); 292 293 // Check whether backoff applies, and if not then which URL can be used for 294 // downloading. These require scanning the download error log, and so they are 295 // done together. 296 UpdateBackoffAndDownloadUrlResult backoff_url_result; 297 EvalStatus backoff_url_status = UpdateBackoffAndDownloadUrl( 298 ec, state, error, &backoff_url_result, update_state); 299 if (backoff_url_status == EvalStatus::kFailed) 300 return EvalStatus::kFailed; 301 result->download_url_idx = backoff_url_result.url_idx; 302 result->download_url_num_errors = backoff_url_result.url_num_errors; 303 result->do_increment_failures = backoff_url_result.do_increment_failures; 304 result->backoff_expiry = backoff_url_result.backoff_expiry; 305 bool is_backoff_active = 306 (backoff_url_status == EvalStatus::kAskMeAgainLater) || 307 !backoff_url_result.backoff_expiry.is_null(); 308 309 DevicePolicyProvider* const dp_provider = state->device_policy_provider(); 310 bool is_scattering_active = false; 311 EvalStatus scattering_status = EvalStatus::kSucceeded; 312 313 const bool* device_policy_is_loaded_p = ec->GetValue( 314 dp_provider->var_device_policy_is_loaded()); 315 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) { 316 // Check whether scattering applies to this update attempt. We should not be 317 // scattering if this is an interactive update check, or if OOBE is enabled 318 // but not completed. 319 // 320 // Note: current code further suppresses scattering if a "deadline" 321 // attribute is found in the Omaha response. However, it appears that the 322 // presence of this attribute is merely indicative of an OOBE update, during 323 // which we suppress scattering anyway. 324 bool is_scattering_applicable = false; 325 result->scatter_wait_period = kZeroInterval; 326 result->scatter_check_threshold = 0; 327 if (!update_state.is_interactive) { 328 const bool* is_oobe_enabled_p = ec->GetValue( 329 state->config_provider()->var_is_oobe_enabled()); 330 if (is_oobe_enabled_p && !(*is_oobe_enabled_p)) { 331 is_scattering_applicable = true; 332 } else { 333 const bool* is_oobe_complete_p = ec->GetValue( 334 state->system_provider()->var_is_oobe_complete()); 335 is_scattering_applicable = (is_oobe_complete_p && *is_oobe_complete_p); 336 } 337 } 338 339 // Compute scattering values. 340 if (is_scattering_applicable) { 341 UpdateScatteringResult scatter_result; 342 scattering_status = UpdateScattering(ec, state, error, &scatter_result, 343 update_state); 344 if (scattering_status == EvalStatus::kFailed) { 345 return EvalStatus::kFailed; 346 } else { 347 result->scatter_wait_period = scatter_result.wait_period; 348 result->scatter_check_threshold = scatter_result.check_threshold; 349 if (scattering_status == EvalStatus::kAskMeAgainLater || 350 scatter_result.is_scattering) 351 is_scattering_active = true; 352 } 353 } 354 } 355 356 // Find out whether P2P is globally enabled. 357 bool p2p_enabled; 358 EvalStatus p2p_enabled_status = P2PEnabled(ec, state, error, &p2p_enabled); 359 if (p2p_enabled_status != EvalStatus::kSucceeded) 360 return EvalStatus::kFailed; 361 362 // Is P2P is enabled, consider allowing it for downloading and/or sharing. 363 if (p2p_enabled) { 364 // Sharing via P2P is allowed if not disabled by Omaha. 365 if (update_state.p2p_sharing_disabled) { 366 LOG(INFO) << "Blocked P2P sharing because it is disabled by Omaha."; 367 } else { 368 result->p2p_sharing_allowed = true; 369 } 370 371 // Downloading via P2P is allowed if not disabled by Omaha, an update is not 372 // interactive, and other limits haven't been reached. 373 if (update_state.p2p_downloading_disabled) { 374 LOG(INFO) << "Blocked P2P downloading because it is disabled by Omaha."; 375 } else if (update_state.is_interactive) { 376 LOG(INFO) << "Blocked P2P downloading because update is interactive."; 377 } else if (update_state.p2p_num_attempts >= kMaxP2PAttempts) { 378 LOG(INFO) << "Blocked P2P downloading as it was attempted too many " 379 "times."; 380 } else if (!update_state.p2p_first_attempted.is_null() && 381 ec->IsWallclockTimeGreaterThan( 382 update_state.p2p_first_attempted + 383 TimeDelta::FromSeconds(kMaxP2PAttemptsPeriodInSeconds))) { 384 LOG(INFO) << "Blocked P2P downloading as its usage timespan exceeds " 385 "limit."; 386 } else { 387 // P2P download is allowed; if backoff or scattering are active, be sure 388 // to suppress them, yet prevent any download URL from being used. 389 result->p2p_downloading_allowed = true; 390 if (is_backoff_active || is_scattering_active) { 391 is_backoff_active = is_scattering_active = false; 392 result->download_url_allowed = false; 393 } 394 } 395 } 396 397 // Check for various deterrents. 398 if (is_check_due) { 399 result->cannot_start_reason = UpdateCannotStartReason::kCheckDue; 400 return EvalStatus::kSucceeded; 401 } 402 if (is_backoff_active) { 403 result->cannot_start_reason = UpdateCannotStartReason::kBackoff; 404 return backoff_url_status; 405 } 406 if (is_scattering_active) { 407 result->cannot_start_reason = UpdateCannotStartReason::kScattering; 408 return scattering_status; 409 } 410 if (result->download_url_idx < 0 && !result->p2p_downloading_allowed) { 411 result->cannot_start_reason = UpdateCannotStartReason::kCannotDownload; 412 return EvalStatus::kSucceeded; 413 } 414 415 // Update is good to go. 416 result->update_can_start = true; 417 return EvalStatus::kSucceeded; 418 } 419 420 // TODO(garnold) Logic in this method is based on 421 // ConnectionManager::IsUpdateAllowedOver(); be sure to deprecate the latter. 422 // 423 // TODO(garnold) The current logic generally treats the list of allowed 424 // connections coming from the device policy as a whitelist, meaning that it 425 // can only be used for enabling connections, but not disable them. Further, 426 // certain connection types (like Bluetooth) cannot be enabled even by policy. 427 // In effect, the only thing that device policy can change is to enable 428 // updates over a cellular network (disabled by default). We may want to 429 // revisit this semantics, allowing greater flexibility in defining specific 430 // permissions over all types of networks. 431 EvalStatus ChromeOSPolicy::UpdateDownloadAllowed( 432 EvaluationContext* ec, 433 State* state, 434 string* error, 435 bool* result) const { 436 // Get the current connection type. 437 ShillProvider* const shill_provider = state->shill_provider(); 438 const ConnectionType* conn_type_p = ec->GetValue( 439 shill_provider->var_conn_type()); 440 POLICY_CHECK_VALUE_AND_FAIL(conn_type_p, error); 441 ConnectionType conn_type = *conn_type_p; 442 443 // If we're tethering, treat it as a cellular connection. 444 if (conn_type != ConnectionType::kCellular) { 445 const ConnectionTethering* conn_tethering_p = ec->GetValue( 446 shill_provider->var_conn_tethering()); 447 POLICY_CHECK_VALUE_AND_FAIL(conn_tethering_p, error); 448 if (*conn_tethering_p == ConnectionTethering::kConfirmed) 449 conn_type = ConnectionType::kCellular; 450 } 451 452 // By default, we allow updates for all connection types, with exceptions as 453 // noted below. This also determines whether a device policy can override the 454 // default. 455 *result = true; 456 bool device_policy_can_override = false; 457 switch (conn_type) { 458 case ConnectionType::kBluetooth: 459 *result = false; 460 break; 461 462 case ConnectionType::kCellular: 463 *result = false; 464 device_policy_can_override = true; 465 break; 466 467 case ConnectionType::kUnknown: 468 if (error) 469 *error = "Unknown connection type"; 470 return EvalStatus::kFailed; 471 472 default: 473 break; // Nothing to do. 474 } 475 476 // If update is allowed, we're done. 477 if (*result) 478 return EvalStatus::kSucceeded; 479 480 // Check whether the device policy specifically allows this connection. 481 if (device_policy_can_override) { 482 DevicePolicyProvider* const dp_provider = state->device_policy_provider(); 483 const bool* device_policy_is_loaded_p = ec->GetValue( 484 dp_provider->var_device_policy_is_loaded()); 485 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) { 486 const set<ConnectionType>* allowed_conn_types_p = ec->GetValue( 487 dp_provider->var_allowed_connection_types_for_update()); 488 if (allowed_conn_types_p) { 489 if (allowed_conn_types_p->count(conn_type)) { 490 *result = true; 491 return EvalStatus::kSucceeded; 492 } 493 } else if (conn_type == ConnectionType::kCellular) { 494 // Local user settings can allow updates over cellular iff a policy was 495 // loaded but no allowed connections were specified in it. 496 const bool* update_over_cellular_allowed_p = ec->GetValue( 497 state->updater_provider()->var_cellular_enabled()); 498 if (update_over_cellular_allowed_p && *update_over_cellular_allowed_p) 499 *result = true; 500 } 501 } 502 } 503 504 return (*result ? EvalStatus::kSucceeded : EvalStatus::kAskMeAgainLater); 505 } 506 507 EvalStatus ChromeOSPolicy::P2PEnabled(EvaluationContext* ec, 508 State* state, 509 string* error, 510 bool* result) const { 511 bool enabled = false; 512 513 // Determine whether use of P2P is allowed by policy. Even if P2P is not 514 // explicitly allowed, we allow it if the device is enterprise enrolled (that 515 // is, missing or empty owner string). 516 DevicePolicyProvider* const dp_provider = state->device_policy_provider(); 517 const bool* device_policy_is_loaded_p = ec->GetValue( 518 dp_provider->var_device_policy_is_loaded()); 519 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) { 520 const bool* policy_au_p2p_enabled_p = ec->GetValue( 521 dp_provider->var_au_p2p_enabled()); 522 if (policy_au_p2p_enabled_p) { 523 enabled = *policy_au_p2p_enabled_p; 524 } else { 525 const string* policy_owner_p = ec->GetValue(dp_provider->var_owner()); 526 if (!policy_owner_p || policy_owner_p->empty()) 527 enabled = true; 528 } 529 } 530 531 // Enable P2P, if so mandated by the updater configuration. This is additive 532 // to whether or not P2P is enabled by device policy. 533 if (!enabled) { 534 const bool* updater_p2p_enabled_p = ec->GetValue( 535 state->updater_provider()->var_p2p_enabled()); 536 enabled = updater_p2p_enabled_p && *updater_p2p_enabled_p; 537 } 538 539 *result = enabled; 540 return EvalStatus::kSucceeded; 541 } 542 543 EvalStatus ChromeOSPolicy::P2PEnabledChanged(EvaluationContext* ec, 544 State* state, 545 string* error, 546 bool* result, 547 bool prev_result) const { 548 EvalStatus status = P2PEnabled(ec, state, error, result); 549 if (status == EvalStatus::kSucceeded && *result == prev_result) 550 return EvalStatus::kAskMeAgainLater; 551 return status; 552 } 553 554 EvalStatus ChromeOSPolicy::UpdateBackoffAndDownloadUrl( 555 EvaluationContext* ec, State* state, string* error, 556 UpdateBackoffAndDownloadUrlResult* result, 557 const UpdateState& update_state) const { 558 // Sanity checks. 559 DCHECK_GE(update_state.download_errors_max, 0); 560 561 // Set default result values. 562 result->do_increment_failures = false; 563 result->backoff_expiry = update_state.backoff_expiry; 564 result->url_idx = -1; 565 result->url_num_errors = 0; 566 567 const bool* is_official_build_p = ec->GetValue( 568 state->system_provider()->var_is_official_build()); 569 bool is_official_build = (is_official_build_p ? *is_official_build_p : true); 570 571 // Check whether backoff is enabled. 572 bool may_backoff = false; 573 if (update_state.is_backoff_disabled) { 574 LOG(INFO) << "Backoff disabled by Omaha."; 575 } else if (update_state.is_interactive) { 576 LOG(INFO) << "No backoff for interactive updates."; 577 } else if (update_state.is_delta_payload) { 578 LOG(INFO) << "No backoff for delta payloads."; 579 } else if (!is_official_build) { 580 LOG(INFO) << "No backoff for unofficial builds."; 581 } else { 582 may_backoff = true; 583 } 584 585 // If previous backoff still in effect, block. 586 if (may_backoff && !update_state.backoff_expiry.is_null() && 587 !ec->IsWallclockTimeGreaterThan(update_state.backoff_expiry)) { 588 LOG(INFO) << "Previous backoff has not expired, waiting."; 589 return EvalStatus::kAskMeAgainLater; 590 } 591 592 // Determine whether HTTP downloads are forbidden by policy. This only 593 // applies to official system builds; otherwise, HTTP is always enabled. 594 bool http_allowed = true; 595 if (is_official_build) { 596 DevicePolicyProvider* const dp_provider = state->device_policy_provider(); 597 const bool* device_policy_is_loaded_p = ec->GetValue( 598 dp_provider->var_device_policy_is_loaded()); 599 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) { 600 const bool* policy_http_downloads_enabled_p = ec->GetValue( 601 dp_provider->var_http_downloads_enabled()); 602 http_allowed = (!policy_http_downloads_enabled_p || 603 *policy_http_downloads_enabled_p); 604 } 605 } 606 607 int url_idx = update_state.last_download_url_idx; 608 if (url_idx < 0) 609 url_idx = -1; 610 bool do_advance_url = false; 611 bool is_failure_occurred = false; 612 Time err_time; 613 614 // Scan the relevant part of the download error log, tracking which URLs are 615 // being used, and accounting the number of errors for each URL. Note that 616 // this process may not traverse all errors provided, as it may decide to bail 617 // out midway depending on the particular errors exhibited, the number of 618 // failures allowed, etc. When this ends, |url_idx| will point to the last URL 619 // used (-1 if starting fresh), |do_advance_url| will determine whether the 620 // URL needs to be advanced, and |err_time| the point in time when the last 621 // reported error occurred. Additionally, if the error log indicates that an 622 // update attempt has failed (abnormal), then |is_failure_occurred| will be 623 // set to true. 624 const int num_urls = update_state.download_urls.size(); 625 int prev_url_idx = -1; 626 int url_num_errors = update_state.last_download_url_num_errors; 627 Time prev_err_time; 628 bool is_first = true; 629 for (const auto& err_tuple : update_state.download_errors) { 630 // Do some sanity checks. 631 int used_url_idx = get<0>(err_tuple); 632 if (is_first && url_idx >= 0 && used_url_idx != url_idx) { 633 LOG(WARNING) << "First URL in error log (" << used_url_idx 634 << ") not as expected (" << url_idx << ")"; 635 } 636 is_first = false; 637 url_idx = used_url_idx; 638 if (url_idx < 0 || url_idx >= num_urls) { 639 LOG(ERROR) << "Download error log contains an invalid URL index (" 640 << url_idx << ")"; 641 return EvalStatus::kFailed; 642 } 643 err_time = get<2>(err_tuple); 644 if (!(prev_err_time.is_null() || err_time >= prev_err_time)) { 645 // TODO(garnold) Monotonicity cannot really be assumed when dealing with 646 // wallclock-based timestamps. However, we're making a simplifying 647 // assumption so as to keep the policy implementation straightforward, for 648 // now. In general, we should convert all timestamp handling in the 649 // UpdateManager to use monotonic time (instead of wallclock), including 650 // the computation of various expiration times (backoff, scattering, etc). 651 // The client will do whatever conversions necessary when 652 // persisting/retrieving these values across reboots. See chromium:408794. 653 LOG(ERROR) << "Download error timestamps not monotonically increasing."; 654 return EvalStatus::kFailed; 655 } 656 prev_err_time = err_time; 657 658 // Ignore errors that happened before the last known failed attempt. 659 if (!update_state.failures_last_updated.is_null() && 660 err_time <= update_state.failures_last_updated) 661 continue; 662 663 if (prev_url_idx >= 0) { 664 if (url_idx < prev_url_idx) { 665 LOG(ERROR) << "The URLs in the download error log have wrapped around (" 666 << prev_url_idx << "->" << url_idx 667 << "). This should not have happened and means that there's " 668 "a bug. To be conservative, we record a failed attempt " 669 "(invalidating the rest of the error log) and resume " 670 "download from the first usable URL."; 671 url_idx = -1; 672 is_failure_occurred = true; 673 break; 674 } 675 676 if (url_idx > prev_url_idx) { 677 url_num_errors = 0; 678 do_advance_url = false; 679 } 680 } 681 682 if (HandleErrorCode(get<1>(err_tuple), &url_num_errors) || 683 url_num_errors > update_state.download_errors_max) 684 do_advance_url = true; 685 686 prev_url_idx = url_idx; 687 } 688 689 // If required, advance to the next usable URL. If the URLs wraparound, we 690 // mark an update attempt failure. Also be sure to set the download error 691 // count to zero. 692 if (url_idx < 0 || do_advance_url) { 693 url_num_errors = 0; 694 int start_url_idx = -1; 695 do { 696 if (++url_idx == num_urls) { 697 url_idx = 0; 698 // We only mark failure if an actual advancing of a URL was required. 699 if (do_advance_url) 700 is_failure_occurred = true; 701 } 702 703 if (start_url_idx < 0) 704 start_url_idx = url_idx; 705 else if (url_idx == start_url_idx) 706 url_idx = -1; // No usable URL. 707 } while (url_idx >= 0 && 708 !IsUrlUsable(update_state.download_urls[url_idx], http_allowed)); 709 } 710 711 // If we have a download URL but a failure was observed, compute a new backoff 712 // expiry (if allowed). The backoff period is generally 2 ^ (num_failures - 1) 713 // days, bounded by the size of int and kAttemptBackoffMaxIntervalInDays, and 714 // fuzzed by kAttemptBackoffFuzzInHours hours. Backoff expiry is computed from 715 // the latest recorded time of error. 716 Time backoff_expiry; 717 if (url_idx >= 0 && is_failure_occurred && may_backoff) { 718 CHECK(!err_time.is_null()) 719 << "We must have an error timestamp if a failure occurred!"; 720 const uint64_t* seed = ec->GetValue(state->random_provider()->var_seed()); 721 POLICY_CHECK_VALUE_AND_FAIL(seed, error); 722 PRNG prng(*seed); 723 int exp = min(update_state.num_failures, 724 static_cast<int>(sizeof(int)) * 8 - 2); 725 TimeDelta backoff_interval = TimeDelta::FromDays(min( 726 1 << exp, 727 kNextUpdateCheckPolicyConstants.attempt_backoff_max_interval_in_days)); 728 TimeDelta backoff_fuzz = TimeDelta::FromHours( 729 kNextUpdateCheckPolicyConstants.attempt_backoff_fuzz_in_hours); 730 TimeDelta wait_period = NextUpdateCheckTimePolicyImpl::FuzzedInterval( 731 &prng, backoff_interval.InSeconds(), backoff_fuzz.InSeconds()); 732 backoff_expiry = err_time + wait_period; 733 734 // If the newly computed backoff already expired, nullify it. 735 if (ec->IsWallclockTimeGreaterThan(backoff_expiry)) 736 backoff_expiry = Time(); 737 } 738 739 result->do_increment_failures = is_failure_occurred; 740 result->backoff_expiry = backoff_expiry; 741 result->url_idx = url_idx; 742 result->url_num_errors = url_num_errors; 743 return EvalStatus::kSucceeded; 744 } 745 746 EvalStatus ChromeOSPolicy::UpdateScattering( 747 EvaluationContext* ec, 748 State* state, 749 string* error, 750 UpdateScatteringResult* result, 751 const UpdateState& update_state) const { 752 // Preconditions. These stem from the postconditions and usage contract. 753 DCHECK(update_state.scatter_wait_period >= kZeroInterval); 754 DCHECK_GE(update_state.scatter_check_threshold, 0); 755 756 // Set default result values. 757 result->is_scattering = false; 758 result->wait_period = kZeroInterval; 759 result->check_threshold = 0; 760 761 DevicePolicyProvider* const dp_provider = state->device_policy_provider(); 762 763 // Ensure that a device policy is loaded. 764 const bool* device_policy_is_loaded_p = ec->GetValue( 765 dp_provider->var_device_policy_is_loaded()); 766 if (!(device_policy_is_loaded_p && *device_policy_is_loaded_p)) 767 return EvalStatus::kSucceeded; 768 769 // Is scattering enabled by policy? 770 const TimeDelta* scatter_factor_p = ec->GetValue( 771 dp_provider->var_scatter_factor()); 772 if (!scatter_factor_p || *scatter_factor_p == kZeroInterval) 773 return EvalStatus::kSucceeded; 774 775 // Obtain a pseudo-random number generator. 776 const uint64_t* seed = ec->GetValue(state->random_provider()->var_seed()); 777 POLICY_CHECK_VALUE_AND_FAIL(seed, error); 778 PRNG prng(*seed); 779 780 // Step 1: Maintain the scattering wait period. 781 // 782 // If no wait period was previously determined, or it no longer fits in the 783 // scatter factor, then generate a new one. Otherwise, keep the one we have. 784 TimeDelta wait_period = update_state.scatter_wait_period; 785 if (wait_period == kZeroInterval || wait_period > *scatter_factor_p) { 786 wait_period = TimeDelta::FromSeconds( 787 prng.RandMinMax(1, scatter_factor_p->InSeconds())); 788 } 789 790 // If we surpassed the wait period or the max scatter period associated with 791 // the update, then no wait is needed. 792 Time wait_expires = (update_state.first_seen + 793 min(wait_period, update_state.scatter_wait_period_max)); 794 if (ec->IsWallclockTimeGreaterThan(wait_expires)) 795 wait_period = kZeroInterval; 796 797 // Step 2: Maintain the update check threshold count. 798 // 799 // If an update check threshold is not specified then generate a new 800 // one. 801 int check_threshold = update_state.scatter_check_threshold; 802 if (check_threshold == 0) { 803 check_threshold = prng.RandMinMax( 804 update_state.scatter_check_threshold_min, 805 update_state.scatter_check_threshold_max); 806 } 807 808 // If the update check threshold is not within allowed range then nullify it. 809 // TODO(garnold) This is compliant with current logic found in 810 // OmahaRequestAction::IsUpdateCheckCountBasedWaitingSatisfied(). We may want 811 // to change it so that it behaves similarly to the wait period case, namely 812 // if the current value exceeds the maximum, we set a new one within range. 813 if (check_threshold > update_state.scatter_check_threshold_max) 814 check_threshold = 0; 815 816 // If the update check threshold is non-zero and satisfied, then nullify it. 817 if (check_threshold > 0 && update_state.num_checks >= check_threshold) 818 check_threshold = 0; 819 820 bool is_scattering = (wait_period != kZeroInterval || check_threshold); 821 EvalStatus ret = EvalStatus::kSucceeded; 822 if (is_scattering && wait_period == update_state.scatter_wait_period && 823 check_threshold == update_state.scatter_check_threshold) 824 ret = EvalStatus::kAskMeAgainLater; 825 result->is_scattering = is_scattering; 826 result->wait_period = wait_period; 827 result->check_threshold = check_threshold; 828 return ret; 829 } 830 831 } // namespace chromeos_update_manager 832