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