Merge changes Ida831e19,I3b74e343,I966c76b0
* changes:
Rename SupplementalProcess to SdkSandbox
Stop creating sdk data directories due to boot time regression
Create supplemental data directories when app data is created
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 4e3aae4..b6ebfca 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -18,13 +18,9 @@
#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER
-#include <algorithm>
#include <errno.h>
-#include <fstream>
#include <fts.h>
-#include <functional>
#include <inttypes.h>
-#include <regex>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,6 +36,11 @@
#include <sys/wait.h>
#include <sys/xattr.h>
#include <unistd.h>
+#include <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <functional>
+#include <regex>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -720,6 +721,76 @@
return error("Failed to prepare profiles for " + packageName);
}
}
+
+ // TODO(b/220095381): Due to boot time regression, we have omitted call to
+ // createSdkSandboxDataDirectory from here temporarily (unless it's for testing)
+ if (uuid_ != nullptr && strcmp(uuid_, "TEST") == 0) {
+ auto status = createSdkSandboxDataDirectory(uuid, packageName, userId, appId, previousAppId,
+ seInfo, flags);
+ if (!status.isOk()) {
+ return status;
+ }
+ }
+
+ return ok();
+}
+
+/**
+ * Responsible for creating /data/misc_{ce|de}/user/0/sdksandbox/<app-name> directory and other
+ * app level sub directories, such as ./shared
+ */
+binder::Status InstalldNativeService::createSdkSandboxDataDirectory(
+ const std::optional<std::string>& uuid, const std::string& packageName, int32_t userId,
+ int32_t appId, int32_t previousAppId, const std::string& seInfo, int32_t flags) {
+ int32_t sdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, appId);
+ if (sdkSandboxUid == -1) {
+ // There no valid sdk sandbox process for this app. Skip creation of data directory
+ return ok();
+ }
+
+ // TODO(b/211763739): what if uuid is not nullptr or TEST?
+ const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+
+ constexpr int storageFlags[2] = {FLAG_STORAGE_CE, FLAG_STORAGE_DE};
+ for (int i = 0; i < 2; i++) {
+ int currentFlag = storageFlags[i];
+ if ((flags & currentFlag) == 0) {
+ continue;
+ }
+ bool isCeData = (currentFlag == FLAG_STORAGE_CE);
+
+ // /data/misc_{ce,de}/<user-id>/sdksandbox directory gets created by vold
+ // during user creation
+
+ // Prepare the app directory
+ auto appPath = create_data_misc_sdk_sandbox_package_path(uuid_, isCeData, userId,
+ packageName.c_str());
+ if (prepare_app_dir(appPath, 0751, AID_SYSTEM)) {
+ return error("Failed to prepare " + appPath);
+ }
+
+ // Now prepare the shared directory which will be accessible by all codes
+ auto sharedPath = create_data_misc_sdk_sandbox_shared_path(uuid_, isCeData, userId,
+ packageName.c_str());
+
+ int32_t previousSdkSandboxUid = multiuser_get_sdk_sandbox_uid(userId, previousAppId);
+ int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
+ if (cacheGid == -1) {
+ return exception(binder::Status::EX_ILLEGAL_STATE,
+ StringPrintf("cacheGid cannot be -1 for sdksandbox data"));
+ }
+ auto status = createAppDataDirs(sharedPath, sdkSandboxUid, &previousSdkSandboxUid, cacheGid,
+ seInfo, 0700);
+ if (!status.isOk()) {
+ return status;
+ }
+
+ // TODO(b/211763739): We also need to handle art profile creations
+
+ // TODO(b/211763739): And return the CE inode of the sdksandbox root directory and
+ // app directory under it so we can clear contents while CE storage is locked
+ }
+
return ok();
}
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 96783c3..b2bad1d 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -47,14 +47,9 @@
int32_t flags);
binder::Status createAppData(const std::optional<std::string>& uuid,
- const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
- int32_t previousAppId, const std::string& seInfo, int32_t targetSdkVersion,
- int64_t* _aidl_return);
- binder::Status createAppDataLocked(const std::optional<std::string>& uuid,
- const std::string& packageName, int32_t userId,
- int32_t flags, int32_t appId, int32_t previousAppId,
- const std::string& seInfo, int32_t targetSdkVersion,
- int64_t* _aidl_return);
+ const std::string& packageName, int32_t userId, int32_t flags,
+ int32_t appId, int32_t previousAppId, const std::string& seInfo,
+ int32_t targetSdkVersion, int64_t* _aidl_return);
binder::Status createAppData(
const android::os::CreateAppDataArgs& args,
@@ -202,6 +197,17 @@
std::unordered_map<uid_t, int64_t> mCacheQuotas;
std::string findDataMediaPath(const std::optional<std::string>& uuid, userid_t userid);
+
+ binder::Status createAppDataLocked(const std::optional<std::string>& uuid,
+ const std::string& packageName, int32_t userId,
+ int32_t flags, int32_t appId, int32_t previousAppId,
+ const std::string& seInfo, int32_t targetSdkVersion,
+ int64_t* _aidl_return);
+
+ binder::Status createSdkSandboxDataDirectory(const std::optional<std::string>& uuid,
+ const std::string& packageName, int32_t userId,
+ int32_t appId, int32_t previousAppId,
+ const std::string& seInfo, int32_t flags);
};
} // namespace installd
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 9702d42..21ab5b8 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -74,8 +74,14 @@
}
namespace installd {
-constexpr const char* kTestUuid = "TEST";
-constexpr const char* kTestPath = "/data/local/tmp/user/0";
+static constexpr const char* kTestUuid = "TEST";
+static constexpr const char* kTestPath = "/data/local/tmp/user/0";
+static constexpr const uid_t kSystemUid = 1000;
+static constexpr const int32_t kTestUserId = 0;
+static constexpr const uid_t kTestAppId = 19999;
+
+const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId);
+const uid_t kTestSdkSandboxUid = multiuser_get_sdk_sandbox_uid(kTestUserId, kTestAppId);
#define FLAG_FORCE InstalldNativeService::FLAG_FORCE
@@ -943,5 +949,118 @@
"com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
}
+class SdkSandboxDataTest : public testing::Test {
+public:
+ void CheckFileAccess(const std::string& path, uid_t uid, mode_t mode) {
+ const auto fullPath = "/data/local/tmp/" + path;
+ ASSERT_TRUE(exists(fullPath.c_str())) << "For path: " << fullPath;
+ struct stat st;
+ ASSERT_EQ(0, stat(fullPath.c_str(), &st));
+ ASSERT_EQ(uid, st.st_uid) << "For path: " << fullPath;
+ ASSERT_EQ(uid, st.st_gid) << "For path: " << fullPath;
+ ASSERT_EQ(mode, st.st_mode) << "For path: " << fullPath;
+ }
+
+ bool exists(const char* path) { return ::access(path, F_OK) == 0; }
+
+ // Creates a default CreateAppDataArgs object
+ android::os::CreateAppDataArgs createAppDataArgs() {
+ android::os::CreateAppDataArgs args;
+ args.uuid = kTestUuid;
+ args.packageName = "com.foo";
+ args.userId = kTestUserId;
+ args.appId = kTestAppId;
+ args.seInfo = "default";
+ args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
+ return args;
+ }
+
+protected:
+ InstalldNativeService* service;
+
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
+
+ service = new InstalldNativeService();
+ clearAppData();
+ ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
+ ASSERT_TRUE(mkdirs("/data/local/tmp/user_de/0", 0700));
+ ASSERT_TRUE(mkdirs("/data/local/tmp/misc_ce/0/sdksandbox", 0700));
+ ASSERT_TRUE(mkdirs("/data/local/tmp/misc_de/0/sdksandbox", 0700));
+
+ init_globals_from_data_and_root();
+ }
+
+ virtual void TearDown() {
+ delete service;
+ clearAppData();
+ }
+
+private:
+ void clearAppData() {
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user_de", true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/misc_ce", true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/misc_de", true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user_de", true));
+ }
+};
+
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData) {
+ android::os::CreateAppDataResult result;
+ android::os::CreateAppDataArgs args = createAppDataArgs();
+ args.packageName = "com.foo";
+ args.flags = FLAG_STORAGE_CE | FLAG_STORAGE_DE;
+
+ // Create the app user data.
+ ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
+
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared", kTestSdkSandboxUid, S_IFDIR | 0700);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared/cache", kTestSdkSandboxUid,
+ S_IFDIR | S_ISGID | 0771);
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo/shared/code_cache", kTestSdkSandboxUid,
+ S_IFDIR | S_ISGID | 0771);
+
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared", kTestSdkSandboxUid, S_IFDIR | 0700);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared/cache", kTestSdkSandboxUid,
+ S_IFDIR | S_ISGID | 0771);
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo/shared/code_cache", kTestSdkSandboxUid,
+ S_IFDIR | S_ISGID | 0771);
+}
+
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData_WithoutDeFlag) {
+ android::os::CreateAppDataResult result;
+ android::os::CreateAppDataArgs args = createAppDataArgs();
+ args.packageName = "com.foo";
+ args.flags = FLAG_STORAGE_CE;
+
+ // Create the app user data.
+ ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
+
+ // Only CE paths should exist
+ CheckFileAccess("misc_ce/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+
+ // DE paths should not exist
+ ASSERT_FALSE(exists("/data/local/tmp/misc_de/0/sdksandbox/com.foo"));
+}
+
+TEST_F(SdkSandboxDataTest, CreateAppData_CreatesSupplementalAppData_WithoutCeFlag) {
+ android::os::CreateAppDataResult result;
+ android::os::CreateAppDataArgs args = createAppDataArgs();
+ args.packageName = "com.foo";
+ args.flags = FLAG_STORAGE_DE;
+
+ // Create the app user data.
+ ASSERT_BINDER_SUCCESS(service->createAppData(args, &result));
+
+ // CE paths should not exist
+ ASSERT_FALSE(exists("/data/local/tmp/misc_ce/0/sdksandbox/com.foo"));
+
+ // Only DE paths should exist
+ CheckFileAccess("misc_de/0/sdksandbox/com.foo", kSystemUid, S_IFDIR | 0751);
+}
+
} // namespace installd
} // namespace android
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 514b881..17802a3 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -658,6 +658,38 @@
ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700));
}
+TEST_F(UtilsTest, TestSdkSandboxDataPaths) {
+ // Ce data paths
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox",
+ create_data_misc_sdk_sandbox_path(nullptr, /*isCeData=*/true, 0));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox", create_data_misc_sdk_sandbox_path(nullptr, true, 10));
+
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, true, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, true, 10, "com.foo"));
+
+ EXPECT_EQ("/data/misc_ce/0/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, true, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, true, 10, "com.foo"));
+
+ // De data paths
+ EXPECT_EQ("/data/misc_de/0/sdksandbox",
+ create_data_misc_sdk_sandbox_path(nullptr, /*isCeData=*/false, 0));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox", create_data_misc_sdk_sandbox_path(nullptr, false, 10));
+
+ EXPECT_EQ("/data/misc_de/0/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, false, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo",
+ create_data_misc_sdk_sandbox_package_path(nullptr, false, 10, "com.foo"));
+
+ EXPECT_EQ("/data/misc_de/0/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, false, 0, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/sdksandbox/com.foo/shared",
+ create_data_misc_sdk_sandbox_shared_path(nullptr, false, 10, "com.foo"));
+}
+
TEST_F(UtilsTest, WaitChild) {
pid_t pid = fork();
if (pid == 0) {
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index f04ee33..992425d 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -197,6 +197,43 @@
return StringPrintf("%s/user_de/%u", data.c_str(), userid);
}
+/**
+ * Create the path name where sdk_sandbox data for all apps will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox
+ */
+std::string create_data_misc_sdk_sandbox_path(const char* uuid, bool isCeData, userid_t user) {
+ std::string data(create_data_path(uuid));
+ if (isCeData) {
+ return StringPrintf("%s/misc_ce/%d/sdksandbox", data.c_str(), user);
+ } else {
+ return StringPrintf("%s/misc_de/%d/sdksandbox", data.c_str(), user);
+ }
+}
+
+/**
+ * Create the path name where code data for all codes in a particular app will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox/<app-name>
+ */
+std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
+ userid_t user, const char* package_name) {
+ check_package_name(package_name);
+ return StringPrintf("%s/%s",
+ create_data_misc_sdk_sandbox_path(volume_uuid, isCeData, user).c_str(),
+ package_name);
+}
+
+/**
+ * Create the path name where shared code data for a particular app will be stored.
+ * E.g. /data/misc_ce/0/sdksandbox/<app-name>/shared
+ */
+std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
+ userid_t user, const char* package_name) {
+ return StringPrintf("%s/shared",
+ create_data_misc_sdk_sandbox_package_path(volume_uuid, isCeData, user,
+ package_name)
+ .c_str());
+}
+
std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 3973894..4b56f99 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -60,6 +60,13 @@
std::string create_data_user_ce_package_path_as_user_link(
const char* volume_uuid, userid_t userid, const char* package_name);
+std::string create_data_misc_sdk_sandbox_path(const char* volume_uuid, bool isCeData,
+ userid_t userid);
+std::string create_data_misc_sdk_sandbox_package_path(const char* volume_uuid, bool isCeData,
+ userid_t userid, const char* package_name);
+std::string create_data_misc_sdk_sandbox_shared_path(const char* volume_uuid, bool isCeData,
+ userid_t userid, const char* package_name);
+
std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user);
std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user);
std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,