Index: chrome/browser/chromeos/policy/enterprise_install_attributes.cc |
diff --git a/chrome/browser/chromeos/policy/enterprise_install_attributes.cc b/chrome/browser/chromeos/policy/enterprise_install_attributes.cc |
index 3fbbc8d00d2e38def39a61379e44f1b2625da2e1..4db35008310069fc7153eb8a75b3ab447f4d550a 100644 |
--- a/chrome/browser/chromeos/policy/enterprise_install_attributes.cc |
+++ b/chrome/browser/chromeos/policy/enterprise_install_attributes.cc |
@@ -55,7 +55,7 @@ EnterpriseInstallAttributes::GetEnterpriseOwnedInstallAttributesBlobForTesting( |
EnterpriseInstallAttributes::EnterpriseInstallAttributes( |
chromeos::CryptohomeClient* cryptohome_client) |
- : device_locked_(false), |
+ : lock_state_(STATE_UNKNOWN), |
registration_mode_(DEVICE_MODE_PENDING), |
cryptohome_client_(cryptohome_client), |
weak_ptr_factory_(this) { |
@@ -65,21 +65,25 @@ EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {} |
void EnterpriseInstallAttributes::ReadCacheFile( |
const base::FilePath& cache_file) { |
- if (device_locked_ || !base::PathExists(cache_file)) |
- return; |
+ DCHECK(lock_state_ == STATE_UNKNOWN); |
- device_locked_ = true; |
Mattias Nissler (ping if slow)
2015/06/19 07:32:45
You're changing semantics here. If the file is pre
Thiemo Nagel
2015/06/19 17:47:04
That was intentional, but I forgot the intention b
|
+ if (!base::PathExists(cache_file)) { |
+ lock_state_ = STATE_NOT_LOCKED; |
+ return; |
+ } |
char buf[16384]; |
int len = base::ReadFile(cache_file, buf, sizeof(buf)); |
if (len == -1 || len >= static_cast<int>(sizeof(buf))) { |
PLOG(ERROR) << "Failed to read " << cache_file.value(); |
+ lock_state_ = STATE_NOT_LOCKED; |
return; |
} |
cryptohome::SerializedInstallAttributes install_attrs_proto; |
if (!install_attrs_proto.ParseFromArray(buf, len)) { |
LOG(ERROR) << "Failed to parse install attributes cache"; |
+ lock_state_ = STATE_NOT_LOCKED; |
return; |
} |
@@ -96,11 +100,12 @@ void EnterpriseInstallAttributes::ReadCacheFile( |
} |
DecodeInstallAttributes(attr_map); |
+ lock_state_ = STATE_LOCKED; |
} |
void EnterpriseInstallAttributes::ReadImmutableAttributes( |
const base::Closure& callback) { |
- if (device_locked_) { |
+ if (lock_state_ == STATE_LOCKED) { |
callback.Run(); |
return; |
} |
@@ -119,7 +124,7 @@ void EnterpriseInstallAttributes::ReadAttributesIfReady( |
registration_mode_ = DEVICE_MODE_NOT_SET; |
if (!cryptohome_util::InstallAttributesIsInvalid() && |
!cryptohome_util::InstallAttributesIsFirstInstall()) { |
- device_locked_ = true; |
+ lock_state_ = STATE_LOCKED; |
static const char* const kEnterpriseAttributes[] = { |
kAttrEnterpriseDeviceId, |
@@ -149,11 +154,12 @@ void EnterpriseInstallAttributes::LockDevice( |
const std::string& device_id, |
const LockResultCallback& callback) { |
DCHECK(!callback.is_null()); |
+ CHECK_NE(lock_state_, STATE_LOCKING); |
CHECK_NE(device_mode, DEVICE_MODE_PENDING); |
CHECK_NE(device_mode, DEVICE_MODE_NOT_SET); |
// Check for existing lock first. |
- if (device_locked_) { |
+ if (lock_state_ == STATE_LOCKED) { |
if (device_mode != registration_mode_) { |
callback.Run(LOCK_WRONG_MODE); |
return; |
@@ -186,6 +192,7 @@ void EnterpriseInstallAttributes::LockDevice( |
return; |
} |
+ lock_state_ = STATE_LOCKING; |
cryptohome_client_->InstallAttributesIsReady( |
base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady, |
weak_ptr_factory_.GetWeakPtr(), |
@@ -203,6 +210,7 @@ void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( |
chromeos::DBusMethodCallStatus call_status, |
bool result) { |
if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_NOT_READY); |
return; |
} |
@@ -217,12 +225,14 @@ void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( |
// Make sure we really have a working InstallAttrs. |
if (cryptohome_util::InstallAttributesIsInvalid()) { |
LOG(ERROR) << "Install attributes invalid."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_BACKEND_INVALID); |
return; |
} |
if (!cryptohome_util::InstallAttributesIsFirstInstall()) { |
LOG(ERROR) << "Install attributes already installed."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_ALREADY_LOCKED); |
return; |
} |
@@ -237,6 +247,7 @@ void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( |
if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled, |
"true")) { |
LOG(ERROR) << "Failed writing attributes."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_SET_ERROR); |
return; |
} |
@@ -252,6 +263,7 @@ void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( |
!cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId, |
device_id)) { |
LOG(ERROR) << "Failed writing attributes."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_SET_ERROR); |
return; |
} |
@@ -260,6 +272,7 @@ void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( |
if (!cryptohome_util::InstallAttributesFinalize() || |
cryptohome_util::InstallAttributesIsFirstInstall()) { |
LOG(ERROR) << "Failed locking."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_FINALIZE_ERROR); |
return; |
} |
@@ -277,24 +290,26 @@ void EnterpriseInstallAttributes::OnReadImmutableAttributes( |
if (GetRegistrationUser() != registration_user) { |
LOG(ERROR) << "Locked data doesn't match."; |
+ lock_state_ = STATE_NOT_LOCKED; |
callback.Run(LOCK_READBACK_ERROR); |
return; |
} |
+ lock_state_ = STATE_LOCKED; |
callback.Run(LOCK_SUCCESS); |
} |
bool EnterpriseInstallAttributes::IsEnterpriseDevice() { |
- return device_locked_ && !registration_user_.empty(); |
+ return lock_state_ == STATE_LOCKED && !registration_user_.empty(); |
} |
bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() { |
- return device_locked_ && |
+ return lock_state_ == STATE_LOCKED && |
registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; |
} |
std::string EnterpriseInstallAttributes::GetRegistrationUser() { |
- if (!device_locked_) |
+ if (lock_state_ != STATE_LOCKED) |
return std::string(); |
return registration_user_; |
@@ -318,6 +333,31 @@ DeviceMode EnterpriseInstallAttributes::GetMode() { |
return registration_mode_; |
} |
+void EnterpriseInstallAttributes::CheckConsistency() { |
Mattias Nissler (ping if slow)
2015/06/19 07:32:45
The code you have here purely tests whether the cr
Thiemo Nagel
2015/06/19 17:47:03
As far as I can see, TpmIsOwned() calls through to
Mattias Nissler (ping if slow)
2015/06/22 07:24:50
I'm sure you can actually observe this situation.
Thiemo Nagel
2015/06/24 10:43:35
Quoting Mattias:
"For posterity: Offline discussi
|
+ LOG(ERROR) << "CheckConsistency()"; |
+ |
+ // LockDeviceIfAttributesIsReady() is not atomic between locking TPM and |
+ // reading back install attributes. |
+ cryptohome_client_->TpmIsOwned(base::Bind( |
+ &EnterpriseInstallAttributes::CheckConsistencyAgainstTpmOwnershipState, |
+ weak_ptr_factory_.GetWeakPtr())); |
+} |
+ |
+void EnterpriseInstallAttributes::CheckConsistencyAgainstTpmOwnershipState( |
+ chromeos::DBusMethodCallStatus call_status, |
+ bool result) { |
+ unsigned state = lock_state_; |
+ state |= 0x4 * (registration_mode_ != DEVICE_MODE_ENTERPRISE); |
+ if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS) { |
+ state |= 0x8 * result; |
+ } else { |
+ state |= 0x10; |
+ } |
+ UMA_HISTOGRAM_ENUMERATION("Enterprise.AttributesTPMConsistency", state, 24); |
+ LOG(ERROR) << "lock_state_: " << lock_state_; |
+ LOG(ERROR) << "State: " << state; |
+} |
+ |
// Warning: The values for these keys (but not the keys themselves) are stored |
// in the protobuf with a trailing zero. Also note that some of these constants |
// have been copied to login_manager/device_policy_service.cc. Please make sure |