diff options
Diffstat (limited to 'cmds')
26 files changed, 665 insertions, 184 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index 53b3a00453..bd3d2d89d9 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -99,30 +99,31 @@ struct TracingCategory { /* Tracing categories */ static const TracingCategory k_categories[] = { - { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } }, - { "input", "Input", ATRACE_TAG_INPUT, { } }, - { "view", "View System", ATRACE_TAG_VIEW, { } }, - { "webview", "WebView", ATRACE_TAG_WEBVIEW, { } }, - { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } }, - { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } }, - { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } }, - { "audio", "Audio", ATRACE_TAG_AUDIO, { } }, - { "video", "Video", ATRACE_TAG_VIDEO, { } }, - { "camera", "Camera", ATRACE_TAG_CAMERA, { } }, - { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } }, - { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } }, - { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } }, - { "rs", "RenderScript", ATRACE_TAG_RS, { } }, - { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } }, - { "power", "Power Management", ATRACE_TAG_POWER, { } }, - { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } }, - { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } }, - { "database", "Database", ATRACE_TAG_DATABASE, { } }, - { "network", "Network", ATRACE_TAG_NETWORK, { } }, - { "adb", "ADB", ATRACE_TAG_ADB, { } }, - { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } }, - { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } }, - { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } }, + { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } }, + { "input", "Input", ATRACE_TAG_INPUT, { } }, + { "view", "View System", ATRACE_TAG_VIEW, { } }, + { "webview", "WebView", ATRACE_TAG_WEBVIEW, { } }, + { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } }, + { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } }, + { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } }, + { "audio", "Audio", ATRACE_TAG_AUDIO, { } }, + { "video", "Video", ATRACE_TAG_VIDEO, { } }, + { "camera", "Camera", ATRACE_TAG_CAMERA, { } }, + { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } }, + { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } }, + { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } }, + { "rs", "RenderScript", ATRACE_TAG_RS, { } }, + { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } }, + { "power", "Power Management", ATRACE_TAG_POWER, { } }, + { "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } }, + { "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } }, + { "database", "Database", ATRACE_TAG_DATABASE, { } }, + { "network", "Network", ATRACE_TAG_NETWORK, { } }, + { "adb", "ADB", ATRACE_TAG_ADB, { } }, + { "vibrator", "Vibrator", ATRACE_TAG_VIBRATOR, { } }, + { "aidl", "AIDL calls", ATRACE_TAG_AIDL, { } }, + { "nnapi", "NNAPI", ATRACE_TAG_NNAPI, { } }, + { "rro", "Runtime Resource Overlay", ATRACE_TAG_RRO, { } }, { k_coreServiceCategory, "Core services", 0, { } }, { k_pdxServiceCategory, "PDX services", 0, { } }, { "sched", "CPU Scheduling", 0, { diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc index fb005089bb..99f37399cf 100644 --- a/cmds/atrace/atrace.rc +++ b/cmds/atrace/atrace.rc @@ -105,6 +105,8 @@ on late-init chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill/enable chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable + chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable + chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc index acc62c0fe0..6c86c21387 100644 --- a/cmds/atrace/atrace_userdebug.rc +++ b/cmds/atrace/atrace_userdebug.rc @@ -15,8 +15,8 @@ on post-fs chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable chmod 0666 /sys/kernel/tracing/events/regulator/enable chmod 0666 /sys/kernel/debug/tracing/events/regulator/enable - chmod 0666 /sys/kernel/tracing/events/pagecache/enable - chmod 0666 /sys/kernel/debug/tracing/events/pagecache/enable + chmod 0666 /sys/kernel/tracing/events/filemap/enable + chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable # irq chmod 0666 /sys/kernel/tracing/events/irq/enable diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp index 75855cfee1..ded0ed35cb 100644 --- a/cmds/bugreportz/bugreportz.cpp +++ b/cmds/bugreportz/bugreportz.cpp @@ -55,7 +55,7 @@ int bugreportz(int s, bool show_progress) { errno = ETIMEDOUT; } printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno)); - break; + return EXIT_FAILURE; } // Writes line by line. @@ -71,8 +71,5 @@ int bugreportz(int s, bool show_progress) { // Process final line, in case it didn't finish with newline write_line(line, show_progress); - if (close(s) == -1) { - fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno)); - } return EXIT_SUCCESS; } diff --git a/cmds/bugreportz/bugreportz.h b/cmds/bugreportz/bugreportz.h index 304e4b3dc3..7af289b2be 100644 --- a/cmds/bugreportz/bugreportz.h +++ b/cmds/bugreportz/bugreportz.h @@ -16,6 +16,7 @@ #define BUGREPORTZ_H // Calls dumpstate using the given socket and output its result to stdout. +// Ownership of the socket is not transferred. int bugreportz(int s, bool show_progress); #endif // BUGREPORTZ_H diff --git a/cmds/bugreportz/main.cpp b/cmds/bugreportz/main.cpp index a3ae1ffa4d..74a95b0b57 100644 --- a/cmds/bugreportz/main.cpp +++ b/cmds/bugreportz/main.cpp @@ -82,7 +82,7 @@ int main(int argc, char* argv[]) { if (s == -1) { printf("FAIL:Failed to connect to dumpstatez service: %s\n", strerror(errno)); - return EXIT_SUCCESS; + return EXIT_FAILURE; } // Set a timeout so that if nothing is read in 10 minutes, we'll stop @@ -92,8 +92,16 @@ int main(int argc, char* argv[]) { tv.tv_sec = 10 * 60; tv.tv_usec = 0; if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { - fprintf(stderr, "WARNING: Cannot set socket timeout: %s\n", strerror(errno)); + fprintf(stderr, + "WARNING: Cannot set socket timeout, bugreportz might hang indefinitely: %s\n", + strerror(errno)); } - bugreportz(s, show_progress); + int ret = bugreportz(s, show_progress); + + if (close(s) == -1) { + fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno)); + ret = EXIT_FAILURE; + } + return ret; } diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index c0050845a0..7958865178 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1380,6 +1380,12 @@ static void dumpstate() { printf("========================================================\n"); printf("== dumpstate: done (id %d)\n", ds.id_); printf("========================================================\n"); + + printf("========================================================\n"); + printf("== Obtaining statsd metadata\n"); + printf("========================================================\n"); + // This differs from the usual dumpsys stats, which is the stats report data. + RunDumpsys("STATSDSTATS", {"stats", "--metadata"}); } /* Dumps state for the default case. Returns true if everything went fine. */ diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index 8fbea8a163..4811927106 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -65,7 +65,7 @@ static void usage() { " -l: only list services, do not dump them\n" " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n" " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n" - " --proto: filter services that support dumping data in proto format. Dumps" + " --proto: filter services that support dumping data in proto format. Dumps\n" " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" " LEVEL must be one of CRITICAL | HIGH | NORMAL\n" diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 8f60881bfe..3ada15398c 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -371,8 +371,8 @@ TEST_F(DumpsysTest, PassAllFlagsToNormalServices) { IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); - ExpectDumpWithArgs("Locksmith", {"-a", "--dump-priority", "NORMAL"}, "dump1"); - ExpectDumpWithArgs("Valet", {"-a", "--dump-priority", "NORMAL"}, "dump2"); + ExpectDumpWithArgs("Locksmith", {"--dump-priority", "NORMAL", "-a"}, "dump1"); + ExpectDumpWithArgs("Valet", {"--dump-priority", "NORMAL", "-a"}, "dump2"); CallMain({"--priority", "NORMAL"}); diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 8a036a5c1c..51f30da9c4 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -41,6 +41,7 @@ #include <android-base/logging.h> #include <android-base/properties.h> +#include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> @@ -95,15 +96,6 @@ static constexpr int kVerityPageSize = 4096; static constexpr size_t kSha256Size = 32; static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode"; -// NOTE: keep in sync with Installer -static constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8; -static constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; -static constexpr int FLAG_USE_QUOTA = 1 << 12; -static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13; -static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14; -static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15; -static constexpr int FLAG_FORCE = 1 << 16; - namespace { constexpr const char* kDump = "android.permission.DUMP"; @@ -555,6 +547,35 @@ binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::st remove_path_xattr(path, kXattrInodeCodeCache); } } + + auto extPath = findDataMediaPath(uuid, userId); + if (flags & FLAG_CLEAR_CACHE_ONLY) { + // Clear only cached data from shared storage + path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { + // No code cache on shared storage + } else { + // Clear everything on shared storage + path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + } } if (flags & FLAG_STORAGE_DE) { std::string suffix = ""; @@ -623,6 +644,24 @@ binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std:: if (delete_dir_contents_and_dir(path) != 0) { res = error("Failed to delete " + path); } + + auto extPath = findDataMediaPath(uuid, userId); + path = StringPrintf("%s/Android/sandbox/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete " + path); + } + path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete " + path); + } + path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete " + path); + } + path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete " + path); + } } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid_, userId, pkgname); @@ -746,6 +785,162 @@ binder::Status InstalldNativeService::fixupAppData(const std::unique_ptr<std::st return ok(); } +static int32_t copy_directory_recursive(const char* from, const char* to) { + char *argv[] = { + (char*) kCpPath, + (char*) "-F", /* delete any existing destination file first (--remove-destination) */ + (char*) "-p", /* preserve timestamps, ownership, and permissions */ + (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ + (char*) "-P", /* Do not follow symlinks [default] */ + (char*) "-d", /* don't dereference symlinks */ + (char*) from, + (char*) to + }; + + LOG(DEBUG) << "Copying " << from << " to " << to; + return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); +} + +// TODO(narayan): We should pass through the ceDataInode so that we can call +// clearAppData(FLAG_CLEAR_CACHE_ONLY | FLAG_CLEAR_CODE_CACHE before we commence +// the copy. +// +// TODO(narayan): For snapshotAppData as well as restoreAppDataSnapshot, we +// should validate that volumeUuid is either nullptr or TEST, we won't support +// anything else. +// +// TODO(narayan): We need to be clearer about the expected behaviour for the +// case where a snapshot already exists. We either need to clear the contents +// of the snapshot directory before we make a copy, or we need to ensure that +// the caller always clears it before requesting a snapshot. +binder::Status InstalldNativeService::snapshotAppData( + const std::unique_ptr<std::string>& volumeUuid, + const std::string& packageName, int32_t user, int32_t storageFlags) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(volumeUuid); + CHECK_ARGUMENT_PACKAGE_NAME(packageName); + std::lock_guard<std::recursive_mutex> lock(mLock); + + const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr; + const char* package_name = packageName.c_str(); + + binder::Status res = ok(); + bool clear_ce_on_exit = false; + bool clear_de_on_exit = false; + + auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] { + if (clear_de_on_exit) { + auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name); + if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { + LOG(WARNING) << "Failed to delete app data snapshot: " << to; + } + } + + if (clear_ce_on_exit) { + auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name); + if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) { + LOG(WARNING) << "Failed to delete app data snapshot: " << to; + } + } + }; + + auto scope_guard = android::base::make_scope_guard(deleter); + + // The app may not have any data at all, in which case it's OK to skip here. + auto from_ce = create_data_user_ce_package_path(volume_uuid, user, package_name); + if (access(from_ce.c_str(), F_OK) != 0) { + LOG(INFO) << "Missing source " << from_ce; + return ok(); + } + + if (storageFlags & FLAG_STORAGE_DE) { + auto from = create_data_user_de_package_path(volume_uuid, user, package_name); + auto to = create_data_misc_de_rollback_path(volume_uuid, user); + + int rc = copy_directory_recursive(from.c_str(), to.c_str()); + if (rc != 0) { + res = error(rc, "Failed copying " + from + " to " + to); + clear_de_on_exit = true; + return res; + } + } + + if (storageFlags & FLAG_STORAGE_CE) { + auto from = create_data_user_ce_package_path(volume_uuid, user, package_name); + auto to = create_data_misc_ce_rollback_path(volume_uuid, user); + int rc = copy_directory_recursive(from.c_str(), to.c_str()); + if (rc != 0) { + res = error(rc, "Failed copying " + from + " to " + to); + clear_ce_on_exit = true; + return res; + } + } + + return res; +} + +binder::Status InstalldNativeService::restoreAppDataSnapshot( + const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName, + const int32_t appId, const int64_t ceDataInode, const std::string& seInfo, + const int32_t user, int32_t storageFlags) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID(volumeUuid); + CHECK_ARGUMENT_PACKAGE_NAME(packageName); + std::lock_guard<std::recursive_mutex> lock(mLock); + + const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr; + const char* package_name = packageName.c_str(); + + auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid, + user, package_name); + auto from_de = create_data_misc_de_rollback_package_path(volume_uuid, + user, package_name); + + const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) && + (access(from_ce.c_str(), F_OK) == 0); + const bool needs_de_rollback = (storageFlags & FLAG_STORAGE_DE) && + (access(from_de.c_str(), F_OK) == 0); + + if (!needs_ce_rollback && !needs_de_rollback) { + return ok(); + } + + // We know we're going to rollback one of the CE or DE data, so we clear + // application data first. Note that it's possible that we're asked to + // restore both CE & DE data but that one of the restores fail. Leaving the + // app with no data in those cases is arguably better than leaving the app + // with mismatched / stale data. + LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot."; + binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode); + if (!res.isOk()) { + return res; + } + + if (needs_ce_rollback) { + auto to_ce = create_data_user_ce_path(volume_uuid, user); + int rc = copy_directory_recursive(from_ce.c_str(), to_ce.c_str()); + if (rc != 0) { + res = error(rc, "Failed copying " + from_ce + " to " + to_ce); + return res; + } + } + + if (needs_de_rollback) { + auto to_de = create_data_user_de_path(volume_uuid, user); + int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str()); + if (rc != 0) { + // TODO(narayan): Should we clear clear the rolled back CE data if + // something goes wrong here ? We're choosing between leaving the + // app devoid of all its data or with just its ce data installed. + res = error(rc, "Failed copying " + from_de + " to " + to_de); + return res; + } + } + + // Finally, restore the SELinux label on the app data. + return restoreconAppData(volumeUuid, packageName, user, storageFlags, appId, seInfo); +} + binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, const std::unique_ptr<std::string>& toUuid, const std::string& packageName, const std::string& dataAppName, int32_t appId, const std::string& seInfo, @@ -770,19 +965,7 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: auto to = create_data_app_package_path(to_uuid, data_app_name); auto to_parent = create_data_app_path(to_uuid); - char *argv[] = { - (char*) kCpPath, - (char*) "-F", /* delete any existing destination file first (--remove-destination) */ - (char*) "-p", /* preserve timestamps, ownership, and permissions */ - (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ - (char*) "-P", /* Do not follow symlinks [default] */ - (char*) "-d", /* don't dereference symlinks */ - (char*) from.c_str(), - (char*) to_parent.c_str() - }; - - LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); + int rc = copy_directory_recursive(from.c_str(), to_parent.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -810,25 +993,11 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: goto fail; } - char *argv[] = { - (char*) kCpPath, - (char*) "-F", /* delete any existing destination file first (--remove-destination) */ - (char*) "-p", /* preserve timestamps, ownership, and permissions */ - (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ - (char*) "-P", /* Do not follow symlinks [default] */ - (char*) "-d", /* don't dereference symlinks */ - nullptr, - nullptr - }; - { auto from = create_data_user_de_package_path(from_uuid, user, package_name); auto to = create_data_user_de_path(to_uuid, user); - argv[6] = (char*) from.c_str(); - argv[7] = (char*) to.c_str(); - LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); + int rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -837,11 +1006,8 @@ binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std: { auto from = create_data_user_ce_package_path(from_uuid, user, package_name); auto to = create_data_user_ce_path(to_uuid, user); - argv[6] = (char*) from.c_str(); - argv[7] = (char*) to.c_str(); - LOG(DEBUG) << "Copying " << from << " to " << to; - int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true); + int rc = copy_directory_recursive(from.c_str(), to.c_str()); if (rc != 0) { res = error(rc, "Failed copying " + from + " to " + to); goto fail; @@ -1414,6 +1580,8 @@ binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::stri } ATRACE_BEGIN("external"); + auto sandboxPath = create_data_media_package_path(uuid_, userId, "sandbox", pkgname); + calculate_tree_size(sandboxPath, &extStats.dataSize); auto extPath = create_data_media_package_path(uuid_, userId, "data", pkgname); collectManualStats(extPath, &extStats); auto mediaPath = create_data_media_package_path(uuid_, userId, "media", pkgname); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index d482472605..098a0c2985 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -60,6 +60,12 @@ public: binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags); + binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid, + const std::string& packageName, const int32_t user, int32_t storageFlags); + binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid, + const std::string& packageName, const int32_t appId, const int64_t ceDataInode, + const std::string& seInfo, const int32_t user, int32_t storageFlags); + binder::Status getAppSize(const std::unique_ptr<std::string>& uuid, const std::vector<std::string>& packageNames, int32_t userId, int32_t flags, int32_t appId, const std::vector<int64_t>& ceDataInodes, diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index caa0b67a4c..3d093b8883 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -104,4 +104,26 @@ interface IInstalld { boolean prepareAppProfile(@utf8InCpp String packageName, int userId, int appId, @utf8InCpp String profileName, @utf8InCpp String codePath, @nullable @utf8InCpp String dexMetadata); + + void snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, + int userId, int storageFlags); + void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName, + int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags); + + // TODO(narayan) we need an API to delete the app data snapshot as well. + // void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, + // in @utf8InCpp String packageName, int userId, int storageFlags); + + const int FLAG_STORAGE_DE = 0x1; + const int FLAG_STORAGE_CE = 0x2; + + const int FLAG_CLEAR_CACHE_ONLY = 0x10; + const int FLAG_CLEAR_CODE_CACHE_ONLY = 0x20; + + const int FLAG_FREE_CACHE_V2 = 0x100; + const int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 0x200; + const int FLAG_FREE_CACHE_NOOP = 0x400; + + const int FLAG_USE_QUOTA = 0x1000; + const int FLAG_FORCE = 0x2000; } diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp index 2d58515b11..db0907017c 100644 --- a/cmds/installd/tests/installd_cache_test.cpp +++ b/cmds/installd/tests/installd_cache_test.cpp @@ -40,8 +40,8 @@ constexpr int64_t kMbInBytes = 1024 * kKbInBytes; constexpr int64_t kGbInBytes = 1024 * kMbInBytes; constexpr int64_t kTbInBytes = 1024 * kGbInBytes; -static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13; -static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14; +#define FLAG_FREE_CACHE_V2 InstalldNativeService::FLAG_FREE_CACHE_V2 +#define FLAG_FREE_CACHE_V2_DEFY_QUOTA InstalldNativeService::FLAG_FREE_CACHE_V2_DEFY_QUOTA int get_property(const char *key, char *value, const char *default_value) { return property_get(key, value, default_value); diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp index a5af5d740e..e6017cb761 100644 --- a/cmds/installd/tests/installd_service_test.cpp +++ b/cmds/installd/tests/installd_service_test.cpp @@ -21,6 +21,8 @@ #include <sys/xattr.h> #include <android-base/logging.h> +#include <android-base/file.h> +#include <android-base/scopeguard.h> #include <android-base/stringprintf.h> #include <cutils/properties.h> #include <gtest/gtest.h> @@ -37,7 +39,7 @@ namespace installd { constexpr const char* kTestUuid = "TEST"; -static constexpr int FLAG_FORCE = 1 << 16; +#define FLAG_FORCE InstalldNativeService::FLAG_FORCE int get_property(const char *key, char *value, const char *default_value) { return property_get(key, value, default_value); @@ -240,5 +242,180 @@ TEST_F(ServiceTest, CalculateCache) { EXPECT_EQ("/data/dalvik-cache/isa/path@to@file.apk@classes.dex", std::string(buf)); } +static bool mkdirs(const std::string& path, mode_t mode) { + struct stat sb; + if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) { + return true; + } + + if (!mkdirs(android::base::Dirname(path), mode)) { + return false; + } + + return (::mkdir(path.c_str(), mode) != -1); +} + +TEST_F(ServiceTest, CreateAppDataSnapshot) { + auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0); + auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0); + + ASSERT_TRUE(mkdirs(rollback_ce_dir, 700)); + ASSERT_TRUE(mkdirs(rollback_de_dir, 700)); + + auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo"); + auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo"); + + ASSERT_TRUE(mkdirs(fake_package_ce_path, 700)); + ASSERT_TRUE(mkdirs(fake_package_de_path, 700)); + + auto deleter = [&rollback_ce_dir, &rollback_de_dir, + &fake_package_ce_path, &fake_package_de_path]() { + delete_dir_contents(rollback_ce_dir, true); + delete_dir_contents(rollback_de_dir, true); + delete_dir_contents(fake_package_ce_path, true); + delete_dir_contents(fake_package_de_path, true); + rmdir(rollback_ce_dir.c_str()); + rmdir(rollback_de_dir.c_str()); + }; + auto scope_guard = android::base::make_scope_guard(deleter); + + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_CE", fake_package_ce_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_DE", fake_package_de_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + // Request a snapshot of the CE content but not the DE content. + ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"), + "com.foo", 0, FLAG_STORAGE_CE).isOk()); + + std::string ce_content, de_content; + // At this point, we should have the CE content but not the DE content. + ASSERT_TRUE(android::base::ReadFileToString( + rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */)); + ASSERT_FALSE(android::base::ReadFileToString( + rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */)); + ASSERT_EQ("TEST_CONTENT_CE", ce_content); + + // Modify the CE content, so we can assert later that it's reflected + // in the snapshot. + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_CE_MODIFIED", fake_package_ce_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + // Request a snapshot of the DE content but not the CE content. + ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"), + "com.foo", 0, FLAG_STORAGE_DE).isOk()); + + // At this point, both the CE as well as the DE content should be fully + // populated. + ASSERT_TRUE(android::base::ReadFileToString( + rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::ReadFileToString( + rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */)); + ASSERT_EQ("TEST_CONTENT_CE", ce_content); + ASSERT_EQ("TEST_CONTENT_DE", de_content); + + // Modify the DE content, so we can assert later that it's reflected + // in our final snapshot. + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_DE_MODIFIED", fake_package_de_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + // Request a snapshot of both the CE as well as the DE content. + ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"), + "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk()); + + ASSERT_TRUE(android::base::ReadFileToString( + rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::ReadFileToString( + rollback_de_dir + "/com.foo/file1", &de_content, false /* follow_symlinks */)); + ASSERT_EQ("TEST_CONTENT_CE_MODIFIED", ce_content); + ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content); +} + +TEST_F(ServiceTest, CreateAppDataSnapshot_AppDataAbsent) { + auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0); + auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0); + + ASSERT_TRUE(mkdirs(rollback_ce_dir, 700)); + ASSERT_TRUE(mkdirs(rollback_de_dir, 700)); + + auto deleter = [&rollback_ce_dir, &rollback_de_dir]() { + delete_dir_contents(rollback_ce_dir, true); + delete_dir_contents(rollback_de_dir, true); + rmdir(rollback_ce_dir.c_str()); + rmdir(rollback_de_dir.c_str()); + }; + + auto scope_guard = android::base::make_scope_guard(deleter); + + ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"), + "com.foo", 0, FLAG_STORAGE_CE).isOk()); + ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"), + "com.foo", 0, FLAG_STORAGE_DE).isOk()); + + // The snapshot calls must succeed but there should be no snapshot + // created. + struct stat sb; + ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb)); + ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb)); +} + +TEST_F(ServiceTest, RestoreAppDataSnapshot) { + auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0); + auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0); + + ASSERT_TRUE(mkdirs(rollback_ce_dir, 700)); + ASSERT_TRUE(mkdirs(rollback_de_dir, 700)); + + auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo"); + auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo"); + + ASSERT_TRUE(mkdirs(fake_package_ce_path, 700)); + ASSERT_TRUE(mkdirs(fake_package_de_path, 700)); + + auto deleter = [&rollback_ce_dir, &rollback_de_dir, + &fake_package_ce_path, &fake_package_de_path]() { + delete_dir_contents(rollback_ce_dir, true); + delete_dir_contents(rollback_de_dir, true); + delete_dir_contents(fake_package_ce_path, true); + delete_dir_contents(fake_package_de_path, true); + rmdir(rollback_ce_dir.c_str()); + rmdir(rollback_de_dir.c_str()); + }; + auto scope_guard = android::base::make_scope_guard(deleter); + + // Write contents to the rollback location. We'll write the same files to the + // app data location and make sure the restore has overwritten them. + ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700)); + ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700)); + ASSERT_TRUE(android::base::WriteStringToFile( + "CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::WriteStringToFile( + "DE_RESTORE_CONTENT", rollback_de_dir + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_CE", fake_package_ce_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::WriteStringToFile( + "TEST_CONTENT_DE", fake_package_de_path + "/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + ASSERT_TRUE(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"), + "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk()); + + std::string ce_content, de_content; + ASSERT_TRUE(android::base::ReadFileToString( + fake_package_ce_path + "/file1", &ce_content, false /* follow_symlinks */)); + ASSERT_TRUE(android::base::ReadFileToString( + fake_package_de_path + "/file1", &de_content, false /* follow_symlinks */)); + ASSERT_EQ("CE_RESTORE_CONTENT", ce_content); + ASSERT_EQ("DE_RESTORE_CONTENT", de_content); +} + + } // namespace installd } // namespace android diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index ad7a5ae6a2..ce99fff27a 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -544,5 +544,35 @@ TEST_F(UtilsTest, MatchExtension_Invalid) { EXPECT_EQ(0, MatchExtension("docx")); } +TEST_F(UtilsTest, TestRollbackPaths) { + EXPECT_EQ("/data/misc_ce/0/rollback/com.foo", + create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo")); + EXPECT_EQ("/data/misc_ce/10/rollback/com.foo", + create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo")); + + EXPECT_EQ("/data/misc_de/0/rollback/com.foo", + create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo")); + EXPECT_EQ("/data/misc_de/10/rollback/com.foo", + create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo")); + + EXPECT_EQ("/data/misc_ce/0/rollback", + create_data_misc_ce_rollback_path(nullptr, 0)); + EXPECT_EQ("/data/misc_ce/10/rollback", + create_data_misc_ce_rollback_path(nullptr, 10)); + + EXPECT_EQ("/data/misc_de/0/rollback", + create_data_misc_de_rollback_path(nullptr, 0)); + EXPECT_EQ("/data/misc_de/10/rollback", + create_data_misc_de_rollback_path(nullptr, 10)); + + // These last couple of cases are never exercised in production because we + // only snapshot apps in the primary data partition. Exercise them here for + // the sake of completeness. + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example", + create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example", + create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example")); +} + } // namespace installd } // namespace android diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index bbf14cb5f7..24f5eab132 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -194,6 +194,27 @@ std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) { return StringPrintf("%s/user_de/%u", data.c_str(), userid); } + +std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user) { + return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user); +} + +std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user) { + return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user); +} + +std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid, + userid_t user, const char* package_name) { + return StringPrintf("%s/%s", + create_data_misc_ce_rollback_path(volume_uuid, user).c_str(), package_name); +} + +std::string create_data_misc_de_rollback_package_path(const char* volume_uuid, + userid_t user, const char* package_name) { + return StringPrintf("%s/%s", + create_data_misc_de_rollback_path(volume_uuid, user).c_str(), package_name); +} + /** * Create the path name for media for a certain userid. */ diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index 206ad4158a..430f515980 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -61,6 +61,13 @@ std::string create_data_user_de_package_path(const char* volume_uuid, 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_ce_rollback_path(const char* volume_uuid, userid_t user); +std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user); +std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid, + userid_t user, const char* package_name); +std::string create_data_misc_de_rollback_package_path(const char* volume_uuid, + userid_t user, const char* package_name); + std::string create_data_media_path(const char* volume_uuid, userid_t userid); std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name); std::string create_data_media_package_path(const char* volume_uuid, userid_t userid, diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c index fade8cfb72..cf3b1728b6 100644 --- a/cmds/servicemanager/binder.c +++ b/cmds/servicemanager/binder.c @@ -146,7 +146,19 @@ void binder_close(struct binder_state *bs) int binder_become_context_manager(struct binder_state *bs) { - return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); + struct flat_binder_object obj; + memset(&obj, 0, sizeof(obj)); + obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX; + + int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj); + + // fallback to original method + if (result != 0) { + android_errorWriteLog(0x534e4554, "121035042"); + + result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); + } + return result; } int binder_write(struct binder_state *bs, void *data, size_t len) @@ -240,13 +252,28 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio, #endif ptr += sizeof(struct binder_ptr_cookie); break; + case BR_TRANSACTION_SEC_CTX: case BR_TRANSACTION: { - struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; - if ((end - ptr) < sizeof(*txn)) { - ALOGE("parse: txn too small!\n"); - return -1; + struct binder_transaction_data_secctx txn; + if (cmd == BR_TRANSACTION_SEC_CTX) { + if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) { + ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n"); + return -1; + } + memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx)); + ptr += sizeof(struct binder_transaction_data_secctx); + } else /* BR_TRANSACTION */ { + if ((end - ptr) < sizeof(struct binder_transaction_data)) { + ALOGE("parse: txn too small (binder_transaction_data)!\n"); + return -1; + } + memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data)); + ptr += sizeof(struct binder_transaction_data); + + txn.secctx = 0; } - binder_dump_txn(txn); + + binder_dump_txn(&txn.transaction_data); if (func) { unsigned rdata[256/4]; struct binder_io msg; @@ -254,15 +281,14 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio, int res; bio_init(&reply, rdata, sizeof(rdata), 4); - bio_init_from_txn(&msg, txn); - res = func(bs, txn, &msg, &reply); - if (txn->flags & TF_ONE_WAY) { - binder_free_buffer(bs, txn->data.ptr.buffer); + bio_init_from_txn(&msg, &txn.transaction_data); + res = func(bs, &txn, &msg, &reply); + if (txn.transaction_data.flags & TF_ONE_WAY) { + binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer); } else { - binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); + binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res); } } - ptr += sizeof(*txn); break; } case BR_REPLY: { diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h index c95b33f1b8..70be3b4687 100644 --- a/cmds/servicemanager/binder.h +++ b/cmds/servicemanager/binder.h @@ -5,7 +5,8 @@ #define _BINDER_H_ #include <sys/ioctl.h> -#include <linux/android/binder.h> + +#include "binder_kernel.h" struct binder_state; @@ -42,7 +43,7 @@ enum { }; typedef int (*binder_handler)(struct binder_state *bs, - struct binder_transaction_data *txn, + struct binder_transaction_data_secctx *txn, struct binder_io *msg, struct binder_io *reply); diff --git a/cmds/servicemanager/binder_kernel.h b/cmds/servicemanager/binder_kernel.h new file mode 100644 index 0000000000..19fd773887 --- /dev/null +++ b/cmds/servicemanager/binder_kernel.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BINDER_KERNEL_H +#define ANDROID_BINDER_KERNEL_H + +#include <linux/android/binder.h> + +/** + * This file exists because the uapi kernel headers in bionic are built + * from upstream kernel headers only, and not all of the hwbinder kernel changes + * have made it upstream yet. Therefore, the modifications to the + * binder header are added locally in this file. + */ + +enum { + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, +}; + +#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) + +struct binder_transaction_data_secctx { + struct binder_transaction_data transaction_data; + binder_uintptr_t secctx; +}; + +enum { + BR_TRANSACTION_SEC_CTX = _IOR('r', 2, + struct binder_transaction_data_secctx), +}; + + +#endif // ANDROID_BINDER_KERNEL_H diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index d776682d74..ec3fac538d 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -61,14 +61,14 @@ int str16eq(const uint16_t *a, const char *b) static char *service_manager_context; static struct selabel_handle* sehandle; -static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name) +static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name) { - char *sctx = NULL; + char *lookup_sid = NULL; const char *class = "service_manager"; bool allowed; struct audit_data ad; - if (getpidcon(spid, &sctx) < 0) { + if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) { ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid); return false; } @@ -77,19 +77,23 @@ static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char ad.uid = uid; ad.name = name; - int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad); + if (sid == NULL) { + android_errorWriteLog(0x534e4554, "121035042"); + } + + int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad); allowed = (result == 0); - freecon(sctx); + freecon(lookup_sid); return allowed; } -static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm) +static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm) { - return check_mac_perms(spid, uid, service_manager_context, perm, NULL); + return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL); } -static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name) +static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name) { bool allowed; char *tctx = NULL; @@ -104,12 +108,12 @@ static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, return false; } - allowed = check_mac_perms(spid, uid, tctx, perm, name); + allowed = check_mac_perms(spid, sid, uid, tctx, perm, name); freecon(tctx); return allowed; } -static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) +static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) { const char *perm = "add"; @@ -117,19 +121,19 @@ static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, u return 0; /* Don't allow apps to register services */ } - return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; + return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; } -static int svc_can_list(pid_t spid, uid_t uid) +static int svc_can_list(pid_t spid, const char* sid, uid_t uid) { const char *perm = "list"; - return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0; + return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0; } -static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid) +static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid) { const char *perm = "find"; - return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0; + return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0; } struct svcinfo @@ -175,7 +179,7 @@ uint16_t svcmgr_id[] = { }; -uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) +uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid) { struct svcinfo *si = find_svc(s, len); @@ -192,7 +196,7 @@ uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) } } - if (!svc_can_find(s, len, spid, uid)) { + if (!svc_can_find(s, len, spid, sid, uid)) { return 0; } @@ -200,7 +204,7 @@ uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) } int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, - uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) { + uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) { struct svcinfo *si; //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle, @@ -209,7 +213,7 @@ int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint3 if (!handle || (len == 0) || (len > 127)) return -1; - if (!svc_can_register(s, len, spid, uid)) { + if (!svc_can_register(s, len, spid, sid, uid)) { ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n", str8(s, len), handle, uid); return -1; @@ -248,7 +252,7 @@ int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint3 } int svcmgr_handler(struct binder_state *bs, - struct binder_transaction_data *txn, + struct binder_transaction_data_secctx *txn_secctx, struct binder_io *msg, struct binder_io *reply) { @@ -260,6 +264,8 @@ int svcmgr_handler(struct binder_state *bs, int allow_isolated; uint32_t dumpsys_priority; + struct binder_transaction_data *txn = &txn_secctx->transaction_data; + //ALOGI("target=%p code=%d pid=%d uid=%d\n", // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); @@ -274,6 +280,7 @@ int svcmgr_handler(struct binder_state *bs, // Note that we ignore the strict_policy and don't propagate it // further (since we do no outbound RPCs anyway). strict_policy = bio_get_uint32(msg); + bio_get_uint32(msg); // Ignore worksource header. s = bio_get_string16(msg, &len); if (s == NULL) { return -1; @@ -304,7 +311,8 @@ int svcmgr_handler(struct binder_state *bs, if (s == NULL) { return -1; } - handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid); + handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid, + (const char*) txn_secctx->secctx); if (!handle) break; bio_put_ref(reply, handle); @@ -319,7 +327,7 @@ int svcmgr_handler(struct binder_state *bs, allow_isolated = bio_get_uint32(msg) ? 1 : 0; dumpsys_priority = bio_get_uint32(msg); if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority, - txn->sender_pid)) + txn->sender_pid, (const char*) txn_secctx->secctx)) return -1; break; @@ -327,7 +335,7 @@ int svcmgr_handler(struct binder_state *bs, uint32_t n = bio_get_uint32(msg); uint32_t req_dumpsys_priority = bio_get_uint32(msg); - if (!svc_can_list(txn->sender_pid, txn->sender_euid)) { + if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) { ALOGE("list_service() uid=%d - PERMISSION DENIED\n", txn->sender_euid); return -1; diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc index 4d93cb4c73..152ac28ba4 100644 --- a/cmds/servicemanager/servicemanager.rc +++ b/cmds/servicemanager/servicemanager.rc @@ -13,5 +13,6 @@ service servicemanager /system/bin/servicemanager onrestart restart cameraserver onrestart restart keystore onrestart restart gatekeeperd + onrestart restart thermalservice writepid /dev/cpuset/system-background/tasks shutdown critical diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 0bc08a91ab..c70bc3e5c1 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -30,14 +30,13 @@ message Transaction { message SurfaceChange { required int32 id = 1; - + reserved 7; oneof SurfaceChange { PositionChange position = 2; SizeChange size = 3; AlphaChange alpha = 4; LayerChange layer = 5; CropChange crop = 6; - FinalCropChange final_crop = 7; MatrixChange matrix = 8; OverrideScalingModeChange override_scaling_mode = 9; TransparentRegionHintChange transparent_region_hint = 10; @@ -46,6 +45,7 @@ message SurfaceChange { OpaqueFlagChange opaque_flag = 13; SecureFlagChange secure_flag = 14; DeferredTransactionChange deferred_transaction = 15; + CornerRadiusChange corner_radius = 16; } } @@ -63,6 +63,10 @@ message AlphaChange { required float alpha = 1; } +message CornerRadiusChange { + required float corner_radius = 1; +} + message LayerChange { required uint32 layer = 1; } @@ -71,10 +75,6 @@ message CropChange { required Rectangle rectangle = 1; } -message FinalCropChange { - required Rectangle rectangle = 1; -} - message MatrixChange { required float dsdx = 1; required float dtdx = 2; @@ -165,7 +165,7 @@ message VSyncEvent { message DisplayCreation { required int32 id = 1; required string name = 2; - required int32 type = 3; + optional uint64 display_id = 3; required bool is_secure = 4; } diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 4140f40888..34886a99e9 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -286,10 +286,6 @@ status_t Replayer::dispatchEvent(int index) { std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event) .detach(); } break; - case increment.kSurfaceDeletion: { - std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event) - .detach(); - } break; case increment.kBufferUpdate: { std::lock_guard<std::mutex> lock1(mLayerLock); std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock); @@ -385,12 +381,12 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kCrop: setCrop(transaction, change.id(), change.crop()); break; + case SurfaceChange::SurfaceChangeCase::kCornerRadius: + setCornerRadius(transaction, change.id(), change.corner_radius()); + break; case SurfaceChange::SurfaceChangeCase::kMatrix: setMatrix(transaction, change.id(), change.matrix()); break; - case SurfaceChange::SurfaceChangeCase::kFinalCrop: - setFinalCrop(transaction, change.id(), change.final_crop()); - break; case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: setOverrideScalingMode(transaction, change.id(), change.override_scaling_mode()); @@ -489,17 +485,14 @@ void Replayer::setCrop(SurfaceComposerClient::Transaction& t, Rect r = Rect(cc.rectangle().left(), cc.rectangle().top(), cc.rectangle().right(), cc.rectangle().bottom()); - t.setCrop(mLayers[id], r); + t.setCrop_legacy(mLayers[id], r); } -void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t, - layer_id id, const FinalCropChange& fcc) { - ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id, - fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), - fcc.rectangle().bottom()); - Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(), - fcc.rectangle().bottom()); - t.setFinalCrop(mLayers[id], r); +void Replayer::setCornerRadius(SurfaceComposerClient::Transaction& t, + layer_id id, const CornerRadiusChange& cc) { + ALOGV("Layer %d: Setting Corner Radius -- cornerRadius=%d", id, cc.corner_radius()); + + t.setCornerRadius(mLayers[id], cc.corner_radius()); } void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, @@ -570,7 +563,7 @@ void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, auto handle = mLayers[dtc.layer_id()]->getHandle(); - t.deferTransactionUntil(mLayers[id], handle, dtc.frame_number()); + t.deferTransactionUntil_legacy(mLayers[id], handle, dtc.frame_number()); } void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, @@ -631,47 +624,10 @@ status_t Replayer::createSurfaceControl( return NO_ERROR; } -status_t Replayer::deleteSurfaceControl( - const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) { - ALOGV("Deleting %d Surface Control", delete_.id()); - event->readyToExecute(); - - std::lock_guard<std::mutex> lock1(mPendingLayersLock); - - mLayersPendingRemoval.push_back(delete_.id()); - - const auto& iterator = mBufferQueueSchedulers.find(delete_.id()); - if (iterator != mBufferQueueSchedulers.end()) { - (*iterator).second->stopScheduling(); - } - - std::lock_guard<std::mutex> lock2(mLayerLock); - if (mLayers[delete_.id()] != nullptr) { - mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle()); - } - - return NO_ERROR; -} - -void Replayer::doDeleteSurfaceControls() { - std::lock_guard<std::mutex> lock1(mPendingLayersLock); - std::lock_guard<std::mutex> lock2(mLayerLock); - if (!mLayersPendingRemoval.empty()) { - for (int id : mLayersPendingRemoval) { - mLayers.erase(id); - mColors.erase(id); - mBufferQueueSchedulers.erase(id); - } - mLayersPendingRemoval.clear(); - } -} - status_t Replayer::injectVSyncEvent( const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) { ALOGV("Injecting VSync Event"); - doDeleteSurfaceControls(); - event->readyToExecute(); SurfaceComposerClient::injectVSync(vSyncEvent.when()); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 295403eace..ad807ee950 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -70,8 +70,6 @@ class Replayer { status_t doTransaction(const Transaction& transaction, const std::shared_ptr<Event>& event); status_t createSurfaceControl(const SurfaceCreation& create, const std::shared_ptr<Event>& event); - status_t deleteSurfaceControl(const SurfaceDeletion& delete_, - const std::shared_ptr<Event>& event); status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr<Event>& event); void createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event); void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event); @@ -92,8 +90,8 @@ class Replayer { layer_id id, const LayerChange& lc); void setCrop(SurfaceComposerClient::Transaction& t, layer_id id, const CropChange& cc); - void setFinalCrop(SurfaceComposerClient::Transaction& t, - layer_id id, const FinalCropChange& fcc); + void setCornerRadius(SurfaceComposerClient::Transaction& t, + layer_id id, const CornerRadiusChange& cc); void setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc); void setOverrideScalingMode(SurfaceComposerClient::Transaction& t, @@ -120,7 +118,6 @@ class Replayer { void setDisplayProjection(SurfaceComposerClient::Transaction& t, display_id id, const ProjectionChange& pc); - void doDeleteSurfaceControls(); void waitUntilTimestamp(int64_t timestamp); void waitUntilDeferredTransactionLayerExists( const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock); diff --git a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py index a892e46816..d63d97f6b4 100644 --- a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py +++ b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py @@ -172,7 +172,7 @@ def surface_delete(increment): def display_create(increment): increment.display_creation.id = int(input("Enter id: ")) increment.display_creation.name = str(raw_input("Enter name: ")) - increment.display_creation.type = int(input("Enter type: ")) + increment.display_creation.display_id = int(input("Enter display ID: ")) increment.display_creation.is_secure = bool(input("Enter if secure: ")) def display_delete(increment): |