diff options
author | Sungbae Yoo <sungbae.yoo@samsung.com> | 2019-01-17 12:25:51 +0900 |
---|---|---|
committer | Sungbae Yoo <sungbae.yoo@samsung.com> | 2019-01-29 11:56:38 +0900 |
commit | 2515a6ccc00a3714f1b550ba07d2a0d2cc63c808 (patch) | |
tree | ae8baef8c56250a4050858102906ab7096c3a35a | |
parent | 6da10ac6e17527f08099c7667749b6bd400c5b05 (diff) | |
download | libkrate-accepted/tizen_unified.tar.gz libkrate-accepted/tizen_unified.tar.bz2 libkrate-accepted/tizen_unified.zip |
Add klay-legacy classes into this repositorysubmit/tizen_5.0/20190222.075859submit/tizen/20190225.022013submit/tizen/20190222.075321accepted/tizen/unified/20190307.230809accepted/tizen/5.0/unified/20190304.054840tizen_5.0tizenaccepted/tizen_unifiedaccepted/tizen_5.0_unified
It moves several classes such as Cgroup, Namespace.
Change-Id: I27a13b19b216ad0d1bd818808166951ca1f57806
Signed-off-by: Sungbae Yoo <sungbae.yoo@samsung.com>
-rwxr-xr-x | CMakeLists.txt | 5 | ||||
-rw-r--r-- | common/cgroup.cpp | 215 | ||||
-rw-r--r-- | common/cgroup.h | 43 | ||||
-rw-r--r-- | common/namespace.cpp | 77 | ||||
-rw-r--r-- | common/namespace.h | 30 | ||||
-rw-r--r-- | tools/cli/CMakeLists.txt | 7 | ||||
-rw-r--r-- | tools/cli/krate-admin-cli.cpp | 17 |
7 files changed, 380 insertions, 14 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cddac1..4699294 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ SET(KRATE_API ${PROJECT_SOURCE_DIR}/api) SET(KRATE_LIB ${PROJECT_SOURCE_DIR}/lib) SET(KRATE_TOOLS ${PROJECT_SOURCE_DIR}/tools) SET(KRATE_MODULE ${PROJECT_SOURCE_DIR}/module) +SET(KRATE_COMMON ${PROJECT_SOURCE_DIR}/common) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) SET(CXX_STD "c++0x") @@ -69,10 +70,6 @@ IF(NOT DEFINED HOME_DIR) SET(HOME_DIR "/home") ENDIF(NOT DEFINED HOME_DIR) -IF(NOT DEFINED PAMD_DIR) - SET(PAMD_DIR "${SYSCONF_INSTALL_DIR}/pam.d") -ENDIF(NOT DEFINED PAMD_DIR) - IF(NOT DEFINED SYSTEMD_UNIT_DIR) SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") ENDIF(NOT DEFINED SYSTEMD_UNIT_DIR) diff --git a/common/cgroup.cpp b/common/cgroup.cpp new file mode 100644 index 0000000..8276f46 --- /dev/null +++ b/common/cgroup.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mount.h> + +#include <regex> +#include <fstream> + +#include <klay/exception.h> +#include <klay/filesystem.h> + +#include "cgroup.h" + +#define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_-]*" +#define PATH_PATTERN "(/*[A-Za-z_][A-Za-z0-9_-]*)*" + +bool Cgroup::existSubsystem(const std::string& name) +{ + try { + if (!std::regex_match(name, std::regex(NAME_PATTERN))) { + return false; + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + klay::File dir("/sys/fs/cgroup/" + name); + if (dir.exists()) { + if (dir.isDirectory()) { + return true; + } + throw klay::Exception("Invalid subsystem name"); + } + + return false; +} + +void Cgroup::createSubsystem(const std::string& name) +{ + try { + if (!std::regex_match(name, std::regex(NAME_PATTERN))) { + throw klay::Exception("Invalid subsystem name"); + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + if (existSubsystem(name)) { + return; + } + + klay::File subsystem("/sys/fs/cgroup/" + name); + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the writable"); + } + + if (!subsystem.exists()) { + subsystem.makeDirectory(true); + } + + if (::mount(name.c_str(), subsystem.getPath().c_str(), + "cgroup", MS_NODEV | MS_NOSUID | MS_NOEXEC, + ("none,name=" + name).c_str())) { + subsystem.remove(false); + throw klay::Exception("Failed to mount cgroup subsystem"); + } + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | MS_RDONLY | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the read-only"); + } +} + +void Cgroup::destroySubsystem(const std::string& name) +{ + if (!existSubsystem(name)) { + throw klay::Exception("No such subsystem"); + } + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the writable"); + } + + klay::File subsystem("/sys/fs/cgroup/" + name); + ::umount2(subsystem.getPath().c_str(), MNT_EXPIRE); + + subsystem.remove(false); + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | MS_RDONLY | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the read-only"); + } +} + +bool Cgroup::exist(const std::string& subsystem, const std::string& path) +{ + try { + if (!std::regex_match(path, std::regex(PATH_PATTERN))) { + return false; + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + if (dir.exists()) { + if (dir.isDirectory()) { + return true; + } + throw klay::Exception("Invalid path"); + } + + return false; +} + +void Cgroup::create(const std::string& subsystem, const std::string& path) +{ + try { + if (!std::regex_match(path, std::regex(PATH_PATTERN))) { + throw klay::Exception("Invalid path"); + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + if (exist(subsystem, path)) { + return; + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + dir.makeDirectory(true); +} + +void Cgroup::destroy(const std::string& subsystem, const std::string& path) +{ + if (!exist(subsystem, path)) { + throw klay::Exception("No such path in subsystem"); + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + dir.remove(false); +} + +void Cgroup::addProcess(const std::string& subsystem, const std::string& path, const pid_t pid) +{ + if (!exist(subsystem, path)) { + throw klay::Exception("No such path in subsystem"); + } + + std::ofstream ofs("/sys/fs/cgroup/" + subsystem + "/" + path + + "/tasks"); + + ofs << pid << std::endl; +} + +std::vector<pid_t> Cgroup::getProcessList(const std::string& subsystem, const std::string& path) +{ + std::vector<pid_t> ret; + std::ifstream ifs("/sys/fs/cgroup/" + subsystem + "/" + path + + "/tasks"); + + pid_t pid; + + ifs >> pid; + + while (ifs.good()) { + ret.push_back(pid); + ifs >> pid; + } + + return ret; +} + +const std::string Cgroup::getPath(const std::string& subsystem, const pid_t pid) +{ + std::ifstream ifs("/proc/" + std::to_string(pid) + "/cgroup"); + std::string ret = "/", line; + + while (std::getline(ifs, line)) { + std::stringstream lineStream(line); + std::string name; + + //the first getline is for removing the first argument + std::getline(lineStream, name, ':'); + std::getline(lineStream, name, ':'); + + if (name == subsystem || name == "name=" + subsystem) { + ret = line.substr(line.find('/')); + } + } + return ret; +} diff --git a/common/cgroup.h b/common/cgroup.h new file mode 100644 index 0000000..63994cd --- /dev/null +++ b/common/cgroup.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __COMMON_CGROUP_H__ +#define __COMMON_CGROUP_H__ + +#include <string> +#include <vector> + +class Cgroup final { +public: + Cgroup() = delete; + + static bool existSubsystem(const std::string& name); + static void createSubsystem(const std::string& name); + static void destroySubsystem(const std::string& name); + + static bool exist(const std::string& subsystem, const std::string& path); + static void create(const std::string& subsystem, const std::string& path); + static void destroy(const std::string& subsystem, const std::string& path); + + static void addProcess(const std::string& subsystem, + const std::string& path, const pid_t pid); + static std::vector<pid_t> getProcessList(const std::string& subsystem, + const std::string& path); + + static const std::string getPath(const std::string& subsystem, const pid_t pid); +}; + +#endif //!__RUNTIME_CGROUP_H__ diff --git a/common/namespace.cpp b/common/namespace.cpp new file mode 100644 index 0000000..fdcd1b5 --- /dev/null +++ b/common/namespace.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ +#include <vector> + +#include <fcntl.h> +#include <unistd.h> +#include <sys/mount.h> + +#include <klay/exception.h> + +#include "namespace.h" + +namespace { + +typedef std::pair<std::string, int> NamespacePair; +std::vector<NamespacePair> namespaces = { + {"mnt", CLONE_NEWNS}, + {"net", CLONE_NEWNET}, + {"ipc", CLONE_NEWIPC}, + {"pid", CLONE_NEWPID}, + {"uts", CLONE_NEWUTS}, + {"user", CLONE_NEWUSER}, +#ifdef CLONE_NEWCGROUP + {"cgroup", CLONE_NEWCGROUP}, +#endif +}; + +} // namespace + +void Namespace::attach(const pid_t pid) +{ + for (const NamespacePair& ns : namespaces) { + std::string nspath = "/proc/" + std::to_string(pid) + "/ns/" + ns.first; + + int fd; + do { + fd = ::open(nspath.c_str(), O_RDONLY); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) { + if (errno != ENOENT) { + throw klay::Exception("Failed to open namesapce: " + nspath); + } + } else { + if (::setns(fd, ns.second)) { + ::close(fd); + throw klay::Exception("Failed to set namespace: " + nspath); + } + ::close(fd); + } + } +} + +void Namespace::unshare(int flags) +{ + if (::unshare(flags)) { + throw klay::Exception("Failed to unshare namespace"); + } + + if (flags & CLONE_NEWNS && + ::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) == -1) { + throw klay::Exception("Failed to mount root filesystem"); + } +} diff --git a/common/namespace.h b/common/namespace.h new file mode 100644 index 0000000..bc9368c --- /dev/null +++ b/common/namespace.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __RUNTIME_NAMESPACE_H__ +#define __RUNTIME_NAMESPACE_H__ + +#include <sched.h> + +class Namespace final { +public: + Namespace() = delete; + + static void unshare(int flags); + static void attach(const pid_t pid); +}; + +#endif //!__RUNTIME_NAMESPACE_H__ diff --git a/tools/cli/CMakeLists.txt b/tools/cli/CMakeLists.txt index d688ce0..a1cdb51 100644 --- a/tools/cli/CMakeLists.txt +++ b/tools/cli/CMakeLists.txt @@ -14,7 +14,10 @@ # limitations under the License. # -FILE(GLOB CLI_SRCS krate-admin-cli.cpp) +FILE(GLOB CLI_SRCS krate-admin-cli.cpp + ${KRATE_COMMON}/cgroup.cpp + ${KRATE_COMMON}/namespace.cpp +) SET(CLI_NAME ${PROJECT_NAME}-admin-cli) @@ -33,7 +36,7 @@ PKG_CHECK_MODULES(CLI_DEPS REQUIRED capi-appfw-package-manager ) -INCLUDE_DIRECTORIES(SYSTEM ${CLI_DEPS_INCLUDE_DIRS} ${KRATE_MODULE} ${KRATE_LIB}) +INCLUDE_DIRECTORIES(SYSTEM ${CLI_DEPS_INCLUDE_DIRS} ${KRATE_MODULE} ${KRATE_LIB} ${PROJECT_SOURCE_DIR}) TARGET_LINK_LIBRARIES(${CLI_NAME} ${CLI_DEPS_LIBRARIES} krate) INSTALL(TARGETS ${CLI_NAME} DESTINATION sbin) diff --git a/tools/cli/krate-admin-cli.cpp b/tools/cli/krate-admin-cli.cpp index 29496d6..6620417 100644 --- a/tools/cli/krate-admin-cli.cpp +++ b/tools/cli/krate-admin-cli.cpp @@ -42,8 +42,6 @@ #include <iostream> #include <functional> -#include <klay/cgroup.h> -#include <klay/namespace.h> #include <klay/exception.h> #include <klay/filesystem.h> #include <klay/auth/user.h> @@ -51,6 +49,9 @@ #include <krate/app-proxy.h> #include <krate/package-proxy.h> +#include "common/cgroup.h" +#include "common/namespace.h" + #define DEFAULT_SETUP_WIZARD "org.tizen.krate-setup-wizard" #define DEFAULT_SHELL "/bin/bash" #define DEFAULT_MANIFEST "<?xml version='1.0' encoding='utf-8'?><manifest version='0.1.0' />" @@ -321,20 +322,20 @@ int attachToKrate(const std::string& name, char* args[]) std::string path = CGROUP_SUBSYSTEM "/" + name; pid_t pid = 0; - if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) { - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (Cgroup::exist(CGROUP_SUBSYSTEM, path)) { + auto pids = Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); if (pids.size() > 0) { pid = pids[0]; } } else { - runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); + Cgroup::create(CGROUP_SUBSYSTEM, path); } if (pid == 0) { - runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); - runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); + Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); + Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); } else { - runtime::Namespace::attach(pid); + Namespace::attach(pid); } launchProcess(user, args); |