From 00ac93ce4d1e3363a52846faedf3879bd9e6199e Mon Sep 17 00:00:00 2001 From: seolheui kim Date: Mon, 2 Jul 2018 15:20:59 +0900 Subject: [PATCH] Apply lazy-umount and kill processes to unmount user partition Change-Id: If6164ea25259877a88604c935fb4488765584872 Signed-off-by: seolheui kim --- server/engine/encryption/dmcrypt-engine.cpp | 6 +- server/internal-encryption.cpp | 98 +++++++++++++-------- 2 files changed, 63 insertions(+), 41 deletions(-) diff --git a/server/engine/encryption/dmcrypt-engine.cpp b/server/engine/encryption/dmcrypt-engine.cpp index 6c1121f..60c217a 100644 --- a/server/engine/encryption/dmcrypt-engine.cpp +++ b/server/engine/encryption/dmcrypt-engine.cpp @@ -286,11 +286,7 @@ void DMCryptEngine::mount(const BinaryData &key, unsigned int options) void DMCryptEngine::umount() { - //TODO umount("/opt/usr/"apps") will be removed - if (::umount("/opt/usr/apps") && errno != EINVAL) - ERROR(SINK, runtime::GetSystemErrorMessage()); - - if (::umount(destination.c_str()) && errno != EINVAL) + if (::umount(destination.c_str()) && errno != EINVAL && errno != ENOENT) throw runtime::Exception(runtime::GetSystemErrorMessage()); destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME); diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index 3fc0cd7..bf7cc99 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -52,6 +52,9 @@ namespace ode { namespace { const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform"; +const std::vector blackListSystemdUnits = { + "samsung-log-mgr.service", +}; // watches systemd jobs class JobWatch { @@ -210,7 +213,6 @@ void stopDependedSystemdUnits() { dbus::Connection& systemDBus = dbus::Connection::getSystem(); std::set unitsToStop; - pid_t p = -1; for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) { try { @@ -223,10 +225,7 @@ void stopDependedSystemdUnits() .get("(o)", &unit); auto unescapedName = getDecodedPath(unit, "/org/freedesktop/systemd1/unit/"); - if (unescapedName == "samsung-log-mgr.service") - p = pid; - else - unitsToStop.insert(unescapedName); + unitsToStop.insert(unescapedName); } catch (runtime::Exception &e) { INFO(SINK, "Killing process: " + std::to_string(pid)); ::kill(pid, SIGKILL); @@ -234,6 +233,9 @@ void stopDependedSystemdUnits() } JobWatch watch(systemDBus); + for (auto unit : blackListSystemdUnits) { + unitsToStop.erase(unitsToStop.find(unit)); + } for (const std::string& unit : unitsToStop) { INFO(SINK, "Stopping unit: " + unit); @@ -247,12 +249,6 @@ void stopDependedSystemdUnits() if (!watch.waitForJob(job)) throw runtime::Exception("Stopping unit: " + unit + " failed"); } - - if (::umount2("/sys/fs/cgroup", MNT_FORCE | MNT_DETACH) != 0) - INFO(SINK, "Failed to unmount cgroup"); - - if (p != -1) - ::kill(p, SIGKILL); } void showProgressUI(const std::string type) @@ -301,27 +297,61 @@ void setOptions(unsigned int options) ::vconf_set_bool(VCONFKEY_ODE_FAST_ENCRYPTION, value); } -void unmountInternalStorage(const std::string& source) +void execAndWait(const std::string &path, std::vector &args) { - while(true) { - auto mntPaths = findMountPointsByDevice(source); - if(mntPaths.empty()) - break; + runtime::Process proc(path, args); + int ret = proc.execute(); + if (ret < 0) + ERROR(SINK, path + " failed for " + args.back()); + + ret = proc.waitForFinished(); + if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) + ERROR(SINK, path + " failed for " + args.back()); +} - bool unmounted = true; - for(const auto& path : mntPaths) { - INFO(SINK, "Unmounting " + path); - if (::umount(path.c_str()) == -1) { - // If it's busy or was already unmounted ignore the error - if (errno != EBUSY && errno != EINVAL) { - throw runtime::Exception("umount() error: " + runtime::GetSystemErrorMessage()); - } - unmounted = false; - } +bool isPartitionTerminated(const std::string &partition) +{ + bool ret = true; + const std::string cmd("fuser -m " + partition + " | grep -o '[0-9]*'"); + char *line = nullptr; + size_t len = 0; + + FILE *fp = ::popen(cmd.c_str(), "r"); + if (fp == nullptr) { + ERROR(SINK, "Failed to get processes on partition"); + return false; + } + + if (::getline(&line, &len, fp) != -1) + ret = false; + + ::free(line); + ::pclose(fp); + + return ret; +} + +void unmountInternalStorage(const std::string& source) +{ + if (::umount2("/opt/usr", MNT_DETACH) == -1) { + if (errno != EBUSY && errno != EINVAL) { + throw runtime::Exception("umount() error : " + runtime::GetSystemErrorMessage()); } - if (!unmounted) - stopDependedSystemdUnits(); } + + do { + ::sync(); + static const char *fuserPath = "/usr/bin/fuser"; + std::vector args = { + fuserPath, "-m", "-k", "-s", "-SIGTERM", source, + }; + execAndWait(fuserPath, args); + ::usleep((useconds_t)((unsigned int)(500)*1000)); + + args[4] = "-SIGKILL"; + execAndWait(fuserPath, args); + ::usleep((useconds_t)((unsigned int)(200)*1000)); + } while (!isPartitionTerminated(source)); } } @@ -418,8 +448,10 @@ int InternalEncryptionServer::umount() INFO(SINK, "Closing all processes using internal storage."); try { + stopKnownSystemdUnits(); stopDependedSystemdUnits(); INFO(SINK, "Umounting internal storage."); + unmountInternalStorage("/dev/mapper/userdata"); engine->umount(); } catch (runtime::Exception &e) { ERROR(SINK, "Umount failed: " + std::string(e.what())); @@ -515,14 +547,8 @@ int InternalEncryptionServer::decrypt(const std::string& password) stopDependedSystemdUnits(); INFO(SINK, "Umounting internal storage."); - while (1) { - try { - engine->umount(); - break; - } catch (runtime::Exception& e) { - stopDependedSystemdUnits(); - } - } + unmountInternalStorage("/dev/mapper/userdata"); + engine->umount(); } INFO(SINK, "Decryption started."); -- 2.34.1