cryptohome: move install attributes to mount thread

Let all install attributes operation happen on mount thread to prevent
race condition.
And let install attributes initialize after D-Bus initialized.

BUG=chromium:879797
TEST=FEATURES=test emerge-soraka cryptohome
TEST=tast run $DUT hwsec.Cryptohome*
TEST=Manually enroll, login, logout on soraka

Change-Id: I8615bc6cc6f1857e8516b9ec316965d85e3b27cd
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2498164
Tested-by: joe Chou <yich@google.com>
Commit-Queue: joe Chou <yich@google.com>
Reviewed-by: Leo Lai <cylai@google.com>
diff --git a/cryptohome/service_userdataauth.cc b/cryptohome/service_userdataauth.cc
index 6105081..0b9c333 100644
--- a/cryptohome/service_userdataauth.cc
+++ b/cryptohome/service_userdataauth.cc
@@ -623,6 +623,20 @@
     std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
         user_data_auth::InstallAttributesGetReply>> response,
     const user_data_auth::InstallAttributesGetRequest& in_request) {
+  service_->PostTaskToMountThread(
+      FROM_HERE,
+      base::BindOnce(&InstallAttributesAdaptor::DoInstallAttributesGet,
+                     base::Unretained(this),
+                     ThreadSafeDBusMethodResponse<
+                         user_data_auth::InstallAttributesGetReply>::
+                         MakeThreadSafe(std::move(response)),
+                     in_request));
+}
+
+void InstallAttributesAdaptor::DoInstallAttributesGet(
+    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+        user_data_auth::InstallAttributesGetReply>> response,
+    const user_data_auth::InstallAttributesGetRequest& in_request) {
   user_data_auth::InstallAttributesGetReply reply;
   std::vector<uint8_t> data;
   bool result = service_->InstallAttributesGet(in_request.name(), &data);
@@ -639,6 +653,20 @@
     std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
         user_data_auth::InstallAttributesSetReply>> response,
     const user_data_auth::InstallAttributesSetRequest& in_request) {
+  service_->PostTaskToMountThread(
+      FROM_HERE,
+      base::BindOnce(&InstallAttributesAdaptor::DoInstallAttributesSet,
+                     base::Unretained(this),
+                     ThreadSafeDBusMethodResponse<
+                         user_data_auth::InstallAttributesSetReply>::
+                         MakeThreadSafe(std::move(response)),
+                     in_request));
+}
+
+void InstallAttributesAdaptor::DoInstallAttributesSet(
+    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+        user_data_auth::InstallAttributesSetReply>> response,
+    const user_data_auth::InstallAttributesSetRequest& in_request) {
   user_data_auth::InstallAttributesSetReply reply;
   std::vector<uint8_t> data(in_request.value().begin(),
                             in_request.value().end());
@@ -654,6 +682,20 @@
     std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
         user_data_auth::InstallAttributesFinalizeReply>> response,
     const user_data_auth::InstallAttributesFinalizeRequest& in_request) {
+  service_->PostTaskToMountThread(
+      FROM_HERE,
+      base::BindOnce(&InstallAttributesAdaptor::DoInstallAttributesFinalize,
+                     base::Unretained(this),
+                     ThreadSafeDBusMethodResponse<
+                         user_data_auth::InstallAttributesFinalizeReply>::
+                         MakeThreadSafe(std::move(response)),
+                     in_request));
+}
+
+void InstallAttributesAdaptor::DoInstallAttributesFinalize(
+    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+        user_data_auth::InstallAttributesFinalizeReply>> response,
+    const user_data_auth::InstallAttributesFinalizeRequest& in_request) {
   user_data_auth::InstallAttributesFinalizeReply reply;
   if (!service_->InstallAttributesFinalize()) {
     reply.set_error(
@@ -666,6 +708,20 @@
     std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
         user_data_auth::InstallAttributesGetStatusReply>> response,
     const user_data_auth::InstallAttributesGetStatusRequest& in_request) {
+  service_->PostTaskToMountThread(
+      FROM_HERE,
+      base::BindOnce(&InstallAttributesAdaptor::DoInstallAttributesGetStatus,
+                     base::Unretained(this),
+                     ThreadSafeDBusMethodResponse<
+                         user_data_auth::InstallAttributesGetStatusReply>::
+                         MakeThreadSafe(std::move(response)),
+                     in_request));
+}
+
+void InstallAttributesAdaptor::DoInstallAttributesGetStatus(
+    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+        user_data_auth::InstallAttributesGetStatusReply>> response,
+    const user_data_auth::InstallAttributesGetStatusRequest& in_request) {
   user_data_auth::InstallAttributesGetStatusReply reply;
   reply.set_count(service_->InstallAttributesCount());
   reply.set_is_secure(service_->InstallAttributesIsSecure());
diff --git a/cryptohome/service_userdataauth.h b/cryptohome/service_userdataauth.h
index a7b9675..02556ca 100644
--- a/cryptohome/service_userdataauth.h
+++ b/cryptohome/service_userdataauth.h
@@ -334,20 +334,36 @@
       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
           user_data_auth::InstallAttributesGetReply>> response,
       const user_data_auth::InstallAttributesGetRequest& in_request) override;
+  void DoInstallAttributesGet(
+      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+          user_data_auth::InstallAttributesGetReply>> response,
+      const user_data_auth::InstallAttributesGetRequest& in_request);
   void InstallAttributesSet(
       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
           user_data_auth::InstallAttributesSetReply>> response,
       const user_data_auth::InstallAttributesSetRequest& in_request) override;
+  void DoInstallAttributesSet(
+      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+          user_data_auth::InstallAttributesSetReply>> response,
+      const user_data_auth::InstallAttributesSetRequest& in_request);
   void InstallAttributesFinalize(
       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
           user_data_auth::InstallAttributesFinalizeReply>> response,
       const user_data_auth::InstallAttributesFinalizeRequest& in_request)
       override;
+  void DoInstallAttributesFinalize(
+      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+          user_data_auth::InstallAttributesFinalizeReply>> response,
+      const user_data_auth::InstallAttributesFinalizeRequest& in_request);
   void InstallAttributesGetStatus(
       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
           user_data_auth::InstallAttributesGetStatusReply>> response,
       const user_data_auth::InstallAttributesGetStatusRequest& in_request)
       override;
+  void DoInstallAttributesGetStatus(
+      std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
+          user_data_auth::InstallAttributesGetStatusReply>> response,
+      const user_data_auth::InstallAttributesGetStatusRequest& in_request);
   void GetFirmwareManagementParameters(
       std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<
           user_data_auth::GetFirmwareManagementParametersReply>> response,
diff --git a/cryptohome/userdataauth.cc b/cryptohome/userdataauth.cc
index 55b4fa0..813b3cc 100644
--- a/cryptohome/userdataauth.cc
+++ b/cryptohome/userdataauth.cc
@@ -44,7 +44,7 @@
 
 namespace cryptohome {
 
-const char kMountThreadName[] = "MountThread";
+constexpr char kMountThreadName[] = "MountThread";
 
 namespace {
 // Some utility functions used by UserDataAuth.
@@ -270,11 +270,6 @@
     mount_thread_.StartWithOptions(options);
   }
 
-  // If the TPM is unowned or doesn't exist, it's safe for
-  // this function to be called again. However, it shouldn't
-  // be called across multiple threads in parallel.
-  InitializeInstallAttributes();
-
   // Clean up any unreferenced mountpoints at startup.
   PostTaskToMountThread(FROM_HERE,
                         base::BindOnce(
@@ -434,6 +429,15 @@
   } else {
     LOG(ERROR) << __func__ << ": Failed to get TpmManagerUtility singleton!";
   }
+
+  // If the TPM is unowned or doesn't exist, it's safe for
+  // this function to be called again. However, it shouldn't
+  // be called across multiple threads in parallel.
+
+  PostTaskToMountThread(FROM_HERE,
+                        base::Bind(&UserDataAuth::InitializeInstallAttributes,
+                                   base::Unretained(this)));
+
   PostTaskToMountThread(FROM_HERE,
                         base::Bind(&UserDataAuth::CreateFingerprintManager,
                                    base::Unretained(this)));
@@ -442,15 +446,15 @@
 }
 
 void UserDataAuth::CreateFingerprintManager() {
-  if (!default_fingerprint_manager_) {
-    default_fingerprint_manager_ = FingerprintManager::Create(
-        mount_thread_bus_,
-        dbus::ObjectPath(std::string(biod::kBiodServicePath)
-                             .append(kCrosFpBiometricsManagerRelativePath)));
-  }
-
-  if (!fingerprint_manager_)
+  if (!fingerprint_manager_) {
+    if (!default_fingerprint_manager_) {
+      default_fingerprint_manager_ = FingerprintManager::Create(
+          mount_thread_bus_,
+          dbus::ObjectPath(std::string(biod::kBiodServicePath)
+                               .append(kCrosFpBiometricsManagerRelativePath)));
+    }
     fingerprint_manager_ = default_fingerprint_manager_.get();
+  }
 }
 
 void UserDataAuth::OnOwnershipTakenSignal() {
@@ -988,7 +992,7 @@
 
     // Initialize the install-time locked attributes since we can't do it prior
     // to ownership.
-    PostTaskToOriginThread(
+    PostTaskToMountThread(
         FROM_HERE, base::BindOnce(&UserDataAuth::InitializeInstallAttributes,
                                   base::Unretained(this)));
 
@@ -1013,7 +1017,7 @@
 }
 
 void UserDataAuth::DetectEnterpriseOwnership() {
-  AssertOnOriginThread();
+  AssertOnMountThread();
 
   static const std::string true_str = "true";
   brillo::Blob true_value(true_str.begin(), true_str.end());
@@ -1022,9 +1026,7 @@
   brillo::Blob value;
   if (install_attrs_->Get("enterprise.owned", &value) && value == true_value) {
     // Update any active mounts with the state, have to be done on mount thread.
-    PostTaskToMountThread(FROM_HERE,
-                          base::BindOnce(&UserDataAuth::SetEnterpriseOwned,
-                                         base::Unretained(this), true));
+    SetEnterpriseOwned(true);
   }
   // Note: Right now there's no way to convert an enterprise owned machine to a
   // non-enterprise owned machine without clearing the TPM, so we don't try
@@ -1032,7 +1034,7 @@
 }
 
 void UserDataAuth::InitializeInstallAttributes() {
-  AssertOnOriginThread();
+  AssertOnMountThread();
 
   // Don't reinitialize when install attributes are valid.
   if (install_attrs_->status() == InstallAttributes::Status::kValid) {
@@ -2712,27 +2714,33 @@
 
 bool UserDataAuth::InstallAttributesGet(const std::string& name,
                                         std::vector<uint8_t>* data_out) {
+  AssertOnMountThread();
   return install_attrs_->Get(name, data_out);
 }
 
 bool UserDataAuth::InstallAttributesSet(const std::string& name,
                                         const std::vector<uint8_t>& data) {
+  AssertOnMountThread();
   return install_attrs_->Set(name, data);
 }
 
 bool UserDataAuth::InstallAttributesFinalize() {
+  AssertOnMountThread();
   return install_attrs_->Finalize();
 }
 
 int UserDataAuth::InstallAttributesCount() {
+  AssertOnMountThread();
   return install_attrs_->Count();
 }
 
 bool UserDataAuth::InstallAttributesIsSecure() {
+  AssertOnMountThread();
   return install_attrs_->is_secure();
 }
 
 InstallAttributes::Status UserDataAuth::InstallAttributesGetStatus() {
+  AssertOnMountThread();
   return install_attrs_->status();
 }
 
diff --git a/cryptohome/userdataauth_unittest.cc b/cryptohome/userdataauth_unittest.cc
index c7c528f..5d11caa 100644
--- a/cryptohome/userdataauth_unittest.cc
+++ b/cryptohome/userdataauth_unittest.cc
@@ -807,6 +807,8 @@
   EXPECT_CALL(attrs_, Get("enterprise.owned", _))
       .WillOnce(DoAll(SetArgPointee<1>(blob_true), Return(true)));
   userdataauth_->Initialize();
+  userdataauth_->set_dbus(bus_);
+  userdataauth_->PostDBusInitialize();
 
   EXPECT_TRUE(userdataauth_->IsEnterpriseOwned());
 }
@@ -821,6 +823,8 @@
   EXPECT_CALL(attrs_, Get("enterprise.owned", _))
       .WillOnce(DoAll(SetArgPointee<1>(blob_true), Return(true)));
   userdataauth_->Initialize();
+  userdataauth_->set_dbus(bus_);
+  userdataauth_->PostDBusInitialize();
 
   EXPECT_FALSE(userdataauth_->IsEnterpriseOwned());
 }
@@ -3048,6 +3052,12 @@
           ASSERT_TRUE(userdataauth->Initialize());
         },
         base::Unretained(userdataauth_.get())));
+    userdataauth_->set_dbus(bus_);
+    PostToOriginAndBlock(base::BindOnce(
+        [](UserDataAuth* userdataauth) {
+          ASSERT_TRUE(userdataauth->PostDBusInitialize());
+        },
+        base::Unretained(userdataauth_.get())));
   }
 
  protected: