| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/arc/arc_util.h" | 5 #include "chrome/browser/chromeos/arc/arc_util.h" |
| 6 | 6 |
| 7 #include <linux/magic.h> | 7 #include <linux/magic.h> |
| 8 #include <sys/statfs.h> | 8 #include <sys/statfs.h> |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/command_line.h" |
| 12 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
| 13 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/optional.h" |
| 15 #include "base/sys_info.h" | 17 #include "base/sys_info.h" |
| 16 #include "base/task_scheduler/post_task.h" | 18 #include "base/task_scheduler/post_task.h" |
| 17 #include "base/threading/thread_restrictions.h" | 19 #include "base/threading/thread_restrictions.h" |
| 20 #include "chrome/browser/browser_process.h" |
| 21 #include "chrome/browser/browser_process_platform_part.h" |
| 18 #include "chrome/browser/chromeos/arc/arc_session_manager.h" | 22 #include "chrome/browser/chromeos/arc/arc_session_manager.h" |
| 19 #include "chrome/browser/chromeos/login/user_flow.h" | 23 #include "chrome/browser/chromeos/login/user_flow.h" |
| 20 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" | 24 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" |
| 25 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| 26 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" |
| 21 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 27 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| 28 #include "chrome/browser/chromeos/settings/device_settings_service.h" |
| 22 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
| 23 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
| 31 #include "chromeos/chromeos_switches.h" |
| 24 #include "components/arc/arc_util.h" | 32 #include "components/arc/arc_util.h" |
| 25 #include "components/prefs/pref_service.h" | 33 #include "components/prefs/pref_service.h" |
| 26 #include "components/user_manager/known_user.h" | 34 #include "components/user_manager/known_user.h" |
| 27 #include "components/user_manager/user.h" | 35 #include "components/user_manager/user.h" |
| 28 #include "components/user_manager/user_manager.h" | 36 #include "components/user_manager/user_manager.h" |
| 29 | 37 |
| 38 using DeviceEcryptfsMigrationStrategyProto = |
| 39 enterprise_management::DeviceEcryptfsMigrationStrategyProto; |
| 40 |
| 30 namespace arc { | 41 namespace arc { |
| 31 | 42 |
| 32 namespace { | 43 namespace { |
| 33 | 44 |
| 34 constexpr char kLsbReleaseArcVersionKey[] = "CHROMEOS_ARC_ANDROID_SDK_VERSION"; | 45 constexpr char kLsbReleaseArcVersionKey[] = "CHROMEOS_ARC_ANDROID_SDK_VERSION"; |
| 35 constexpr char kAndroidMSdkVersion[] = "23"; | 46 constexpr char kAndroidMSdkVersion[] = "23"; |
| 36 | 47 |
| 37 // Let IsAllowedForProfile() return "false" for any profile. | 48 // Let IsAllowedForProfile() return "false" for any profile. |
| 38 bool g_disallow_for_testing = false; | 49 bool g_disallow_for_testing = false; |
| 39 | 50 |
| 40 // Let IsArcBlockedDueToIncompatibleFileSystem() return the specified value | 51 // Let IsArcBlockedDueToIncompatibleFileSystem() return the specified value |
| 41 // during test runs. | 52 // during test runs. |
| 42 bool g_arc_blocked_due_to_incomaptible_filesystem_for_testing = false; | 53 bool g_arc_blocked_due_to_incomaptible_filesystem_for_testing = false; |
| 43 | 54 |
| 44 // TODO(kinaba): Temporary workaround for crbug.com/729034. | 55 // TODO(kinaba): Temporary workaround for crbug.com/729034. |
| 45 // | 56 // |
| 46 // Some type of accounts don't have user prefs. As a short-term workaround, | 57 // Some type of accounts don't have user prefs. As a short-term workaround, |
| 47 // store the compatibility info from them on memory, ignoring the defect that | 58 // store the compatibility info from them on memory, ignoring the defect that |
| 48 // it cannot survive browser crash and restart. | 59 // it cannot survive browser crash and restart. |
| 49 // | 60 // |
| 50 // This will be removed once the forced migration for ARC Kiosk user is | 61 // This will be removed once the forced migration for ARC Kiosk user is |
| 51 // implemented. After it's done such types of accounts cannot even sign-in | 62 // implemented. After it's done such types of accounts cannot even sign-in |
| 52 // with incompatible filesystem. Hence it'll be safe to always regard compatible | 63 // with incompatible filesystem. Hence it'll be safe to always regard compatible |
| 53 // for them then. | 64 // for them then. |
| 54 base::LazyInstance<std::set<AccountId>>::DestructorAtExit | 65 base::LazyInstance<std::set<AccountId>>::DestructorAtExit |
| 55 g_known_compatible_users = LAZY_INSTANCE_INITIALIZER; | 66 g_known_compatible_users = LAZY_INSTANCE_INITIALIZER; |
| 56 | 67 |
| 68 // This flag is set the first time the check if migration to ext4 is allowed, |
| 69 // and remains unchanged after that. |
| 70 // TODO(igorcov): Remove this after migration. crbug.com/725493 |
| 71 base::Optional<bool> g_is_arc_migration_allowed; |
| 72 |
| 57 // Returns whether ARC can run on the filesystem mounted at |path|. | 73 // Returns whether ARC can run on the filesystem mounted at |path|. |
| 58 // This function should run only on threads where IO operations are allowed. | 74 // This function should run only on threads where IO operations are allowed. |
| 59 bool IsArcCompatibleFilesystem(const base::FilePath& path) { | 75 bool IsArcCompatibleFilesystem(const base::FilePath& path) { |
| 60 base::ThreadRestrictions::AssertIOAllowed(); | 76 base::ThreadRestrictions::AssertIOAllowed(); |
| 61 | 77 |
| 62 // If it can be verified it is not on ecryptfs, then it is ok. | 78 // If it can be verified it is not on ecryptfs, then it is ok. |
| 63 struct statfs statfs_buf; | 79 struct statfs statfs_buf; |
| 64 if (statfs(path.value().c_str(), &statfs_buf) < 0) | 80 if (statfs(path.value().c_str(), &statfs_buf) < 0) |
| 65 return false; | 81 return false; |
| 66 return statfs_buf.f_type != ECRYPTFS_SUPER_MAGIC; | 82 return statfs_buf.f_type != ECRYPTFS_SUPER_MAGIC; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 87 // TODO(kinaba): Remove this code for accounts without user prefs. | 103 // TODO(kinaba): Remove this code for accounts without user prefs. |
| 88 // See the comment for |g_known_compatible_users| for the detail. | 104 // See the comment for |g_known_compatible_users| for the detail. |
| 89 if (GetFileSystemCompatibilityPref(account_id) != | 105 if (GetFileSystemCompatibilityPref(account_id) != |
| 90 arc::kFileSystemCompatible) { | 106 arc::kFileSystemCompatible) { |
| 91 g_known_compatible_users.Get().insert(account_id); | 107 g_known_compatible_users.Get().insert(account_id); |
| 92 } | 108 } |
| 93 } | 109 } |
| 94 callback.Run(); | 110 callback.Run(); |
| 95 } | 111 } |
| 96 | 112 |
| 113 bool IsArcMigrationAllowedInternal() { |
| 114 // If the device is not managed, then the migration allowed. |
| 115 if (!g_browser_process->platform_part() |
| 116 ->browser_policy_connector_chromeos() |
| 117 ->IsEnterpriseManaged()) { |
| 118 return true; |
| 119 } |
| 120 |
| 121 const auto* const command_line = base::CommandLine::ForCurrentProcess(); |
| 122 // If the command line flag is missing, the migration for this type of |
| 123 // device is allowed regardless of the policy data. |
| 124 if (!command_line->HasSwitch( |
| 125 chromeos::switches::kNeedArcMigrationPolicyCheck)) { |
| 126 return true; |
| 127 } |
| 128 |
| 129 const auto* policy = |
| 130 chromeos::DeviceSettingsService::Get()->device_settings(); |
| 131 if (policy && policy->has_device_ecryptfs_migration_strategy()) { |
| 132 const DeviceEcryptfsMigrationStrategyProto& container( |
| 133 policy->device_ecryptfs_migration_strategy()); |
| 134 return container.has_migration_strategy() && |
| 135 container.migration_strategy() == |
| 136 DeviceEcryptfsMigrationStrategyProto::ALLOW_MIGRATION; |
| 137 } |
| 138 |
| 139 return false; |
| 140 } |
| 141 |
| 97 } // namespace | 142 } // namespace |
| 98 | 143 |
| 99 bool IsArcAllowedForProfile(const Profile* profile) { | 144 bool IsArcAllowedForProfile(const Profile* profile) { |
| 100 if (g_disallow_for_testing) { | 145 if (g_disallow_for_testing) { |
| 101 VLOG(1) << "ARC is disallowed for testing."; | 146 VLOG(1) << "ARC is disallowed for testing."; |
| 102 return false; | 147 return false; |
| 103 } | 148 } |
| 104 | 149 |
| 105 // ARC Kiosk can be enabled even if ARC is not yet supported on the device. | 150 // ARC Kiosk can be enabled even if ARC is not yet supported on the device. |
| 106 // In that case IsArcKioskMode() should return true as profile is already | 151 // In that case IsArcKioskMode() should return true as profile is already |
| (...skipping 29 matching lines...) Expand all Loading... |
| 136 // users do this through GAIA, but Kiosk and Active Directory users use | 181 // users do this through GAIA, but Kiosk and Active Directory users use |
| 137 // different application install mechanism. ARC is not allowed otherwise | 182 // different application install mechanism. ARC is not allowed otherwise |
| 138 // (e.g. in public sessions). cf) crbug.com/605545 | 183 // (e.g. in public sessions). cf) crbug.com/605545 |
| 139 const user_manager::User* user = | 184 const user_manager::User* user = |
| 140 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | 185 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); |
| 141 if (!IsArcAllowedForUser(user)) { | 186 if (!IsArcAllowedForUser(user)) { |
| 142 VLOG(1) << "ARC is not allowed for the user."; | 187 VLOG(1) << "ARC is not allowed for the user."; |
| 143 return false; | 188 return false; |
| 144 } | 189 } |
| 145 | 190 |
| 191 // If migration policy check is needed (specified by commandline flag), check |
| 192 // the policy, which should be already available here. If policy says |
| 193 // migration is not allowed, do not run ARC, regardless whether file system |
| 194 // migration is actually needed. For example, even if file system is still |
| 195 // ecryptfs and ARC version is M, or file system is already migrated into ext4 |
| 196 // crypt and ARC version is N or later, if policy says migration is not |
| 197 // allowed, ARC will never run. Practically, in the former example case, |
| 198 // --need-arc-migration-policy-check is not set, so this check passes and user |
| 199 // can use ARC. In latter case, policy should say migration is allowed, so |
| 200 // also user can use ARC then. |
| 201 // TODO(igorcov): Remove this after migration. crbug.com/725493 |
| 202 if (!IsArcMigrationAllowed()) { |
| 203 VLOG(1) << "ARC migration is not allowed by policy."; |
| 204 return false; |
| 205 } |
| 206 |
| 146 // Do not run ARC instance when supervised user is being created. | 207 // Do not run ARC instance when supervised user is being created. |
| 147 // Otherwise noisy notification may be displayed. | 208 // Otherwise noisy notification may be displayed. |
| 148 chromeos::UserFlow* user_flow = | 209 chromeos::UserFlow* user_flow = |
| 149 chromeos::ChromeUserManager::Get()->GetUserFlow(user->GetAccountId()); | 210 chromeos::ChromeUserManager::Get()->GetUserFlow(user->GetAccountId()); |
| 150 if (!user_flow || !user_flow->CanStartArc()) { | 211 if (!user_flow || !user_flow->CanStartArc()) { |
| 151 VLOG(1) << "ARC is not allowed in the current user flow."; | 212 VLOG(1) << "ARC is not allowed in the current user flow."; |
| 152 return false; | 213 return false; |
| 153 } | 214 } |
| 154 | 215 |
| 155 return true; | 216 return true; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 | 344 |
| 284 // Otherwise, check the underlying filesystem. | 345 // Otherwise, check the underlying filesystem. |
| 285 base::PostTaskWithTraitsAndReplyWithResult( | 346 base::PostTaskWithTraitsAndReplyWithResult( |
| 286 FROM_HERE, | 347 FROM_HERE, |
| 287 {base::MayBlock(), base::TaskPriority::USER_BLOCKING, | 348 {base::MayBlock(), base::TaskPriority::USER_BLOCKING, |
| 288 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, | 349 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, |
| 289 base::Bind(&IsArcCompatibleFilesystem, profile_path), | 350 base::Bind(&IsArcCompatibleFilesystem, profile_path), |
| 290 base::Bind(&StoreCompatibilityCheckResult, account_id, callback)); | 351 base::Bind(&StoreCompatibilityCheckResult, account_id, callback)); |
| 291 } | 352 } |
| 292 | 353 |
| 354 bool IsArcMigrationAllowed() { |
| 355 if (!g_is_arc_migration_allowed.has_value()) |
| 356 g_is_arc_migration_allowed = IsArcMigrationAllowedInternal(); |
| 357 return g_is_arc_migration_allowed.value(); |
| 358 } |
| 359 |
| 360 void ResetArcMigrationAllowedForTesting() { |
| 361 g_is_arc_migration_allowed.reset(); |
| 362 } |
| 363 |
| 293 } // namespace arc | 364 } // namespace arc |
| OLD | NEW |