cryptohome: Fix GetAccountDiskUsage() count file size twice.
/home/.shadow/$hash, which contains /home/.shadow/$hash/mount/user (bind
mounted to /home/user/$hash), and /home/.shadow/$hash/mount/root (bind
mounted to /home/root/$hash), is counted together with /home/root/$hash
and /home/user/$hash, thus causing the final calculated size to be off
by a factor of 2.
BUG=b:151092607
TEST=tast run $dut hwsec.AccountDiskUsage && unit tests
Change-Id: I0f70914ac078fcbeb150a2e794a749ddaaa3bcad
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2095053
Tested-by: John L Chen <zuan@chromium.org>
Commit-Queue: John L Chen <zuan@chromium.org>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
diff --git a/cryptohome/homedirs.cc b/cryptohome/homedirs.cc
index d148552..2f790b3 100644
--- a/cryptohome/homedirs.cc
+++ b/cryptohome/homedirs.cc
@@ -1559,24 +1559,41 @@
return 0;
}
+ // Note that for ephemeral mounts, there could be a vault that's not
+ // ephemeral, but the current mount is ephemeral. In this case, ComputeSize()
+ // return the non ephemeral on disk vault's size.
std::string obfuscated = BuildObfuscatedUsername(account_id, system_salt_);
FilePath user_dir = FilePath(shadow_root_).Append(obfuscated);
- FilePath user_path = brillo::cryptohome::home::GetUserPath(account_id);
- FilePath root_path = brillo::cryptohome::home::GetRootPath(account_id);
- int64_t total_size = 0;
- int64_t size = platform_->ComputeDirectorySize(user_dir);
- if (size > 0) {
- total_size += size;
+
+ int64_t size = 0;
+ if (!platform_->DirectoryExists(user_dir)) {
+ // It's either ephemeral or the user doesn't exist. In either case, we check
+ // /home/user/$hash.
+ FilePath user_home_dir = brillo::cryptohome::home::GetUserPath(account_id);
+ size = platform_->ComputeDirectorySize(user_home_dir);
+ } else {
+ // Note that we'll need to handle both ecryptfs and dircrypto.
+ // dircrypto:
+ // /home/.shadow/$hash/mount: Always equal to the size occupied.
+ // ecryptfs:
+ // /home/.shadow/$hash/vault: Always equal to the size occupied.
+ // /home/.shadow/$hash/mount: Equal to the size occupied only when mounted.
+ // Therefore, we check to see if vault exists, if it exists, we compute
+ // vault's size, otherwise, we check mount's size.
+ FilePath mount_dir = user_dir.Append(kMountDir);
+ FilePath vault_dir = user_dir.Append(kEcryptfsVaultDir);
+ if (platform_->DirectoryExists(vault_dir)) {
+ // ecryptfs
+ size = platform_->ComputeDirectorySize(vault_dir);
+ } else {
+ // dircrypto
+ size = platform_->ComputeDirectorySize(mount_dir);
+ }
}
- size = platform_->ComputeDirectorySize(user_path);
if (size > 0) {
- total_size += size;
+ return size;
}
- size = platform_->ComputeDirectorySize(root_path);
- if (size > 0) {
- total_size += size;
- }
- return total_size;
+ return 0;
}
bool HomeDirs::Migrate(const Credentials& newcreds,
diff --git a/cryptohome/homedirs_unittest.cc b/cryptohome/homedirs_unittest.cc
index 4ce94a7..b7f4e03 100644
--- a/cryptohome/homedirs_unittest.cc
+++ b/cryptohome/homedirs_unittest.cc
@@ -276,38 +276,89 @@
EXPECT_TRUE(homedirs_.Rename(kNewUserId, kDefaultUsers[0].username));
}
-TEST_P(HomeDirsTest, ComputeSize) {
+TEST_P(HomeDirsTest, ComputeSizeDircrypto) {
FilePath base_path(test_helper_.users[0].base_path);
- FilePath user_path = brillo::cryptohome::home::GetUserPathPrefix()
- .Append(test_helper_.users[0].obfuscated_username);
- FilePath root_path = brillo::cryptohome::home::GetRootPathPrefix()
- .Append(test_helper_.users[0].obfuscated_username);
+ // /home/.shadow in production code.
+ FilePath shadow_home =
+ homedirs_.shadow_root().Append(base_path.BaseName().value());
+ // /home/.shadow/$hash/mount in production code.
+ FilePath mount_dir = shadow_home.Append(kMountDir);
+ // /home/.shadow/$hash/vault in production code.
+ FilePath vault_dir = shadow_home.Append(kEcryptfsVaultDir);
+ // /home/user/$hash in production code and here in unit test.
+ FilePath user_dir = brillo::cryptohome::home::GetUserPathPrefix().Append(
+ test_helper_.users[0].obfuscated_username);
- ASSERT_TRUE(base::CreateDirectory(base_path));
+ // If anyone asks, shadow_home, mount_dir and user_dir exists but not
+ // vault_dir.
+ ON_CALL(platform_, DirectoryExists(shadow_home)).WillByDefault(Return(true));
+ ON_CALL(platform_, DirectoryExists(mount_dir)).WillByDefault(Return(true));
+ ON_CALL(platform_, DirectoryExists(vault_dir)).WillByDefault(Return(false));
+ ON_CALL(platform_, DirectoryExists(user_dir)).WillByDefault(Return(true));
- // Put test files under base_path and user_path.
- const char kTestFileName0[] = "test.txt";
- const char kExpectedData0[] = "file content";
- int expected_bytes_0 = base::size(kExpectedData0);
- ASSERT_EQ(expected_bytes_0,
- base::WriteFile(base_path.Append(kTestFileName0),
- kExpectedData0, expected_bytes_0));
- const char kTestFileName1[] = "test1.txt";
- const char kExpectedData1[] = "file content";
- int expected_bytes_1 = base::size(kExpectedData1);
- ASSERT_EQ(expected_bytes_1,
- base::WriteFile(base_path.Append(kTestFileName1),
- kExpectedData1, expected_bytes_1));
+ constexpr int64_t expected_bytes = 123456789012345;
+ constexpr int64_t unexpected_bytes = 98765432154321;
+ EXPECT_CALL(platform_, ComputeDirectorySize(mount_dir))
+ .WillOnce(Return(expected_bytes));
+ ON_CALL(platform_, ComputeDirectorySize(vault_dir))
+ .WillByDefault(Return(unexpected_bytes));
- EXPECT_CALL(platform_, ComputeDirectorySize(base_path))
- .WillOnce(Return(expected_bytes_0));
- EXPECT_CALL(platform_, ComputeDirectorySize(user_path))
- .WillOnce(Return(expected_bytes_1));
- EXPECT_CALL(platform_, ComputeDirectorySize(root_path))
- .WillOnce(Return(0));
+ EXPECT_EQ(expected_bytes, homedirs_.ComputeSize(kDefaultUsers[0].username));
+}
- EXPECT_EQ(expected_bytes_0 + expected_bytes_1,
- homedirs_.ComputeSize(kDefaultUsers[0].username));
+TEST_P(HomeDirsTest, ComputeSizeEcryptfs) {
+ FilePath base_path(test_helper_.users[0].base_path);
+ FilePath shadow_home =
+ homedirs_.shadow_root().Append(base_path.BaseName().value());
+ FilePath mount_dir = shadow_home.Append(kMountDir);
+ FilePath vault_dir = shadow_home.Append(kEcryptfsVaultDir);
+ FilePath user_dir = brillo::cryptohome::home::GetUserPathPrefix().Append(
+ test_helper_.users[0].obfuscated_username);
+
+ // If anyone asks, shadow_home, mount_dir, vault_dir and user_dir all exists.
+ ON_CALL(platform_, DirectoryExists(shadow_home)).WillByDefault(Return(true));
+ ON_CALL(platform_, DirectoryExists(mount_dir)).WillByDefault(Return(true));
+ ON_CALL(platform_, DirectoryExists(vault_dir)).WillByDefault(Return(true));
+ ON_CALL(platform_, DirectoryExists(user_dir)).WillByDefault(Return(true));
+
+ constexpr int64_t expected_bytes = 123456789012345;
+ constexpr int64_t unexpected_bytes = 98765432154321;
+ EXPECT_CALL(platform_, ComputeDirectorySize(vault_dir))
+ .WillOnce(Return(expected_bytes));
+ ON_CALL(platform_, ComputeDirectorySize(mount_dir))
+ .WillByDefault(Return(unexpected_bytes));
+
+ EXPECT_EQ(expected_bytes, homedirs_.ComputeSize(kDefaultUsers[0].username));
+}
+
+TEST_P(HomeDirsTest, ComputeSizeEphemeral) {
+ FilePath base_path(test_helper_.users[0].base_path);
+ FilePath shadow_home =
+ homedirs_.shadow_root().Append(base_path.BaseName().value());
+ FilePath mount_dir = shadow_home.Append(kMountDir);
+ FilePath vault_dir = shadow_home.Append(kEcryptfsVaultDir);
+ FilePath user_dir = brillo::cryptohome::home::GetUserPathPrefix().Append(
+ test_helper_.users[0].obfuscated_username);
+
+ // If anyone asks, shadow_home, mount_dir and vault_dir doesn't exist, but
+ // user_dir exists.
+ ON_CALL(platform_, DirectoryExists(shadow_home)).WillByDefault(Return(false));
+ ON_CALL(platform_, DirectoryExists(mount_dir)).WillByDefault(Return(false));
+ ON_CALL(platform_, DirectoryExists(vault_dir)).WillByDefault(Return(false));
+ ON_CALL(platform_, DirectoryExists(user_dir)).WillByDefault(Return(true));
+
+ constexpr int64_t expected_bytes = 123456789012345;
+ constexpr int64_t unexpected_bytes = 98765432154321;
+ EXPECT_CALL(platform_, ComputeDirectorySize(user_dir))
+ .WillOnce(Return(expected_bytes));
+ ON_CALL(platform_, ComputeDirectorySize(mount_dir))
+ .WillByDefault(Return(unexpected_bytes));
+ ON_CALL(platform_, ComputeDirectorySize(vault_dir))
+ .WillByDefault(Return(unexpected_bytes));
+ ON_CALL(platform_, ComputeDirectorySize(shadow_home))
+ .WillByDefault(Return(unexpected_bytes));
+
+ EXPECT_EQ(expected_bytes, homedirs_.ComputeSize(kDefaultUsers[0].username));
}
TEST_P(HomeDirsTest, ComputeSizeWithNonexistentUser) {