From 7e5b02e7c33b65a344701be182516fc448920bc5 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Wed, 12 Sep 2018 17:28:02 +0900 Subject: [PATCH] Add krate-mount service which does mount after wait-mount.service in each namespace of krate. and also this requires krate-mount to have cap_sysadmin Change-Id: I6d0729d617d2d7aa610ec1a2e832688d50797ff2 Signed-off-by: Sungbae Yoo --- module/CMakeLists.txt | 32 ++++++++++++------ module/krate-builder.cpp | 55 +++++++++++++++++++++++++----- module/krate-builder.h | 17 ++++++---- module/krate-mount.cpp | 33 ++++++++++++++++++ module/krate.cpp | 63 ++++++++++------------------------- module/systemd/krate-mount.service.in | 11 ++++++ packaging/krate.spec | 9 ++++- 7 files changed, 149 insertions(+), 71 deletions(-) create mode 100644 module/krate-mount.cpp create mode 100644 module/systemd/krate-mount.service.in diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index fa353f9..0fd43f6 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -13,15 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FILE(GLOB PAM_SRCS krate.cpp - krate-builder.cpp +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") + +FILE(GLOB BUILDER_SRCS krate-builder.cpp) + +PKG_CHECK_MODULES(BUILDER_DEPS REQUIRED + klay + libxml-2.0 ) -SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") +FILE(GLOB PAM_SRCS krate.cpp) SET(PAM_NAME pam_${PROJECT_NAME}) +ADD_LIBRARY(${PAM_NAME} MODULE ${PAM_SRCS} ${BUILDER_SRCS}) -ADD_LIBRARY(${PAM_NAME} MODULE ${PAM_SRCS}) SET_TARGET_PROPERTIES(${PAM_NAME} PROPERTIES PREFIX "" COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_INSTALL_DIR}/krate" COMPILE_FLAGS "-fvisibility=hidden" @@ -35,12 +40,19 @@ MARK_AS_ADVANCED(PAM_INCLUDE_DIR PAM_LIBRARY) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) -PKG_CHECK_MODULES(PAM_DEPS REQUIRED - klay - libxml-2.0 -) +INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${BUILDER_DEPS_INCLUDE_DIRS}) + +TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${BUILDER_DEPS_LIBRARIES}) + +FILE(GLOB MOUNT_SRCS krate-mount.cpp) + +SET(MOUNT_NAME ${PROJECT_NAME}-mount) +ADD_EXECUTABLE(${MOUNT_NAME} ${MOUNT_SRCS} ${BUILDER_SRCS}) + +TARGET_LINK_LIBRARIES(${MOUNT_NAME} ${MOUNT_SRC} ${BUILDER_DEPS_LIBRARIES}) -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${PAM_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${PAM_DEPS_LIBRARIES} pthread) +CONFIGURE_FILE(systemd/${MOUNT_NAME}.service.in systemd/${MOUNT_NAME}.service) INSTALL(TARGETS ${PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) +INSTALL(TARGETS ${MOUNT_NAME} DESTINATION ${BIN_DIR}) +INSTALL(FILES systemd/${MOUNT_NAME}.service DESTINATION ${SYSTEMD_USER_UNIT_DIR}) diff --git a/module/krate-builder.cpp b/module/krate-builder.cpp index 07fee11..3e13cc7 100644 --- a/module/krate-builder.cpp +++ b/module/krate-builder.cpp @@ -22,14 +22,17 @@ #include "krate-builder.h" #include +#include #include -KrateBuilder::KrateBuilder(const runtime::User& user, const std::string& manifestPath) : - name(user.getName()), uid(user.getUid()), gid(user.getGid()) +#define CGROUP_SUBSYSTEM "krate" + +KrateBuilder::KrateBuilder(const runtime::User& user) : + user(user) { - runtime::File data(manifestPath); + runtime::File data(getManifestPath()); if (data.exists()) { - manifest.reset(xml::Parser::parseFile(manifestPath)); + manifest.reset(xml::Parser::parseFile(data.getPath())); } } @@ -37,6 +40,11 @@ KrateBuilder::~KrateBuilder() { } +std::string KrateBuilder::getManifestPath() +{ + return "/home/" + user.getName() + "/.config/krate/krate.xml"; +} + void KrateBuilder::bindFilesystemNode(const std::string& source, const std::string& target, const std::string& type, const std::string& options, bool create) @@ -44,7 +52,7 @@ void KrateBuilder::bindFilesystemNode(const std::string& source, const std::stri if (create) { runtime::File dir(target); if (!dir.exists()) { - dir.makeDirectory(true, uid, gid); + dir.makeDirectory(true, user.getUid(), user.getGid()); } } @@ -61,10 +69,41 @@ void KrateBuilder::mountOwnFilesystem() } } - bindFilesystemNode("/home/" + name, - "/home/" + name + "/.krate/" + name, + bindFilesystemNode("/home/" + user.getName(), + "/home/" + user.getName() + "/.krate/" + user.getName(), "none", "rw,bind"); - bindFilesystemNode("/home/" + name + "/.krate", "/home", + bindFilesystemNode("/home/" + user.getName() + "/.krate", "/home", "none", "rw,rbind"); } + +void KrateBuilder::enterKrate() +{ + std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); + pid_t pid = 0; + + if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) { + auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (pids.size() > 0) { + pid = pids[0]; + } + } else { + runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); + } + + if (pid == 0) { + runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); + runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); + } else { + runtime::Namespace::attach(pid); + } +} + +void KrateBuilder::exitKrate() +{ + std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); + auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (pids.size() <= 1) { + runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); + } +} diff --git a/module/krate-builder.h b/module/krate-builder.h index 7947c6b..1563c3e 100644 --- a/module/krate-builder.h +++ b/module/krate-builder.h @@ -20,26 +20,29 @@ #include #include +#include #include #include #include class KrateBuilder final { public: - KrateBuilder(const runtime::User& user, const std::string& manifestPath); + KrateBuilder(const runtime::User& user); virtual ~KrateBuilder(); void mountOwnFilesystem(); -protected: + void enterKrate(); + void exitKrate(); + +private: + runtime::User user; + std::unique_ptr manifest; + + std::string getManifestPath(); void bindFilesystemNode(const std::string& source, const std::string& target, const std::string& type, const std::string& options, bool create = true); -private: - std::string name; - uid_t uid; - gid_t gid; - std::unique_ptr manifest; }; #endif //!__KRATE_BUILDER_H__ diff --git a/module/krate-mount.cpp b/module/krate-mount.cpp new file mode 100644 index 0000000..7595c0a --- /dev/null +++ b/module/krate-mount.cpp @@ -0,0 +1,33 @@ +/* + * 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 +#include + +#include "krate-builder.h" + +int main(int argc, char *argv[]) +{ + try { + runtime::User user; + KrateBuilder builder(user); + builder.mountOwnFilesystem(); + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return EXIT_SUCCESS; +} diff --git a/module/krate.cpp b/module/krate.cpp index dda52c8..8c9a320 100644 --- a/module/krate.cpp +++ b/module/krate.cpp @@ -26,26 +26,20 @@ #include "krate-builder.h" -#include -#include #include #include -#include -#include - -#define CGROUP_SUBSYSTEM "krate" #define KRATE_UID_MIN 6000 #define KRATE_UID_MAX 6999 -#define LAZYMOUNT_EXTERN extern -#define LAZYMOUNT_LIB "/usr/lib/liblazymount.so.0" +namespace { -std::string buildKrateManifestPath(const std::string& name) -{ - return "/home/" + name + "/.config/krate/krate.xml"; +static std::string getFlagFilePath(runtime::User &user) { + return "/run/user/" + std::to_string(user.getUid()) + "/.container"; } +} // namespace + std::string getKrateName(pam_handle_t* handle) { const void* retItem; @@ -57,37 +51,18 @@ std::string getKrateName(pam_handle_t* handle) return static_cast(retItem); } -void enterKrate(const std::string& name) -{ - 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 (pids.size() > 0) { - pid = pids[0]; - } - } else { - runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); - } - - if (pid == 0) { - runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); - runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); - } else { - runtime::Namespace::attach(pid); - } -} - extern "C" { PAM_EXTERN __attribute__((visibility("default"))) int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) { try { runtime::User user(getKrateName(pamh)); - enterKrate(user.getName()); + + KrateBuilder builder(user); + builder.enterKrate(); + if (user.getUid() >= KRATE_UID_MIN && user.getUid() <= KRATE_UID_MAX ) { - runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); + runtime::File flag(getFlagFilePath(user)); if (!flag.exists()) flag.create(0644); } @@ -103,16 +78,14 @@ PAM_EXTERN __attribute__((visibility("default"))) int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) { try { - std::string name = getKrateName(pamh); - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, name); - if (pids.size() <= 1) { - std::string path = CGROUP_SUBSYSTEM "/" + name; - runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); - runtime::User user(name); - runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); - if (flag.exists()) - flag.remove(false); - } + runtime::User user(getKrateName(pamh)); + + KrateBuilder builder(user); + builder.exitKrate(); + + runtime::File flag(getFlagFilePath(user)); + if (flag.exists()) + flag.remove(false); } catch (runtime::Exception& e) { ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); return PAM_SESSION_ERR; diff --git a/module/systemd/krate-mount.service.in b/module/systemd/krate-mount.service.in new file mode 100644 index 0000000..e13a194 --- /dev/null +++ b/module/systemd/krate-mount.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=@PROJECT_NAME@ mount manager for UID %U +DefaultDependencies=no +Wants=wait-mount@opt-usr.service +After=wait-mount@opt-usr.service +Before=session-bind.service basic.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=@BIN_DIR@/@PROJECT_NAME@-mount diff --git a/packaging/krate.spec b/packaging/krate.spec index 0ac2d13..a22e09a 100644 --- a/packaging/krate.spec +++ b/packaging/krate.spec @@ -35,9 +35,12 @@ krates. %manifest krate.manifest %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/krated +%attr(755,root,root) %{_bindir}/krate-mount %attr(700,root,root) %{_sbindir}/krate-volume-manager %{_unitdir}/krate.service %{_unitdir}/multi-user.target.wants/krate.service +%{_unitdir_user}/krate-mount.service +%{_unitdir_user}/basic.target.wants/krate-mount.service %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/default_icon.png %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/shortcut_icon.png %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/indicator_icon.png @@ -61,6 +64,7 @@ krates. -DBIN_DIR=%{TZ_SYS_BIN} \ -DHOME_DIR=%{TZ_SYS_HOME} \ -DSYSTEMD_UNIT_DIR=%{_unitdir} \ + -DSYSTEMD_USER_UNIT_DIR=%{_unitdir_user} \ -DPAMD_DIR=/etc/pam.d \ -DICON_DIR="%{TZ_SYS_RO_ICONS}/krate" \ @@ -68,8 +72,11 @@ make %{?jobs:-j%jobs} %install %make_install +mkdir -p %{buildroot}/%{_unitdir_user}/basic.target.wants +ln -s ../krate-mount.service %{buildroot}/%{_unitdir_user}/basic.target.wants/. + mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants -ln -s ../krate.service %{buildroot}/%{_unitdir}/multi-user.target.wants/krate.service +ln -s ../krate.service %{buildroot}/%{_unitdir}/multi-user.target.wants/. %post echo "session required pam_krate.so" >> /etc/pam.d/systemd-user -- 2.7.4