diff options
author | Rafał Krypa <rafal@krypa.net> | 2014-07-11 21:28:21 +0200 |
---|---|---|
committer | Rafał Krypa <rafal@krypa.net> | 2014-07-13 23:11:10 +0200 |
commit | ff65c427acfcb6d445ee6ae8cbeb570dc744edae (patch) | |
tree | 7964c3b620834aa07066d8333ba58a1624ab5343 | |
parent | 2b9788436113767c3c31b5d0b6d5b8c7303babc5 (diff) | |
download | security-manager-ff65c427acfcb6d445ee6ae8cbeb570dc744edae.tar.gz security-manager-ff65c427acfcb6d445ee6ae8cbeb570dc744edae.tar.bz2 security-manager-ff65c427acfcb6d445ee6ae8cbeb570dc744edae.zip |
Refactoring: put code operating on Smack labels in a separate file
Create smack-labels.cpp, containing code for label assignment and file
labeling. Avoid clutter in installer.cpp.
Change-Id: I97f5251e1bfcd53e242cd0117d48539a378fefde
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
-rw-r--r-- | src/server/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/server/service/include/installer.h | 2 | ||||
-rw-r--r-- | src/server/service/include/smack-labels.h | 61 | ||||
-rw-r--r-- | src/server/service/include/smack-rules.h | 9 | ||||
-rw-r--r-- | src/server/service/installer.cpp | 233 | ||||
-rw-r--r-- | src/server/service/smack-labels.cpp | 249 | ||||
-rw-r--r-- | src/server/service/smack-rules.cpp | 8 |
7 files changed, 320 insertions, 243 deletions
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 5fc4c399..38948881 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -38,6 +38,7 @@ SET(SERVER_SOURCES ${SERVER_PATH}/main/socket-manager.cpp ${SERVER_PATH}/main/server-main.cpp ${SERVER_PATH}/service/smack-rules.cpp + ${SERVER_PATH}/service/smack-labels.cpp ${SERVER_PATH}/service/installer.cpp ${SERVER_PATH}/db/privilege_db.cpp ${DPL_PATH}/core/src/errno_string.cpp diff --git a/src/server/service/include/installer.h b/src/server/service/include/installer.h index 8e240aef..c73f93ac 100644 --- a/src/server/service/include/installer.h +++ b/src/server/service/include/installer.h @@ -58,8 +58,6 @@ public: void process(const ReadEvent &event); void close(const CloseEvent &event); - static const char *const LABEL_FOR_PUBLIC_APP_PATH; - private: ConnectionInfoMap m_connectionInfoMap; PrivilegeDb m_privilegeDb; diff --git a/src/server/service/include/smack-labels.h b/src/server/service/include/smack-labels.h new file mode 100644 index 00000000..a017991d --- /dev/null +++ b/src/server/service/include/smack-labels.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa <r.krypa@samsung.com> + * + * 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 + */ +/** + * @file smack-labels.h + * @author Jan Cybulski <j.cybulski@samsung.com> + * @author Rafal Krypa <r.krypa@samsung.com> + * @version 1.0 + * @brief Header file of functions managing smack labels + * + */ +#ifndef _SMACK_LABELS_H_ +#define _SMACK_LABELS_H_ + +#include <string> +#include <utility> + +#include "security-manager.h" + +namespace SecurityManager { + +/** + * Generates label for application with package identifier + * read from @ref pkgId and assigns it to @ref label. + * @param[in] pkgId application's package identifier. + * @param[out] label string into which application's label will be stored into. + * + * @return true on success, false on error. +*/ +bool generateAppLabel(const std::string &pkgId, std::string &label); + +/** + * Sets Smack labels on a directory and its contents, recursively. + * + * @param pkgId[in] application's package identifier + * @param path[in] path to a file or directory to setup + * @param pathType[in] type of path to setup. See description of + * app_install_path_type in security-manager.h for details + * + * @return true on success, false on error. + */ +bool setupPath(const std::string &pkgId, const std::string &path, + app_install_path_type pathType); + +} // namespace SecurityManager + +#endif /* _SMACK_LABELS_H_ */ diff --git a/src/server/service/include/smack-rules.h b/src/server/service/include/smack-rules.h index 6aa6775d..db816311 100644 --- a/src/server/service/include/smack-rules.h +++ b/src/server/service/include/smack-rules.h @@ -70,15 +70,6 @@ public: */ static bool uninstallPackageRules(const std::string &pkgId); - /** - * Generates label for application with package identifier - * read from @ref appPkgId and assigns it to @ref label. - * @param[in] appPkgId application's package identifier. - * @param[out] label string into which application's label will be stored into. - * @return true on success, false on error. - */ - static bool generateAppLabel(const std::string &appPkgId, std::string &label); - private: static std::string getPackageRulesFilePath(const std::string &pkgId); diff --git a/src/server/service/installer.cpp b/src/server/service/installer.cpp index fc993e0d..d7810a9b 100644 --- a/src/server/service/installer.cpp +++ b/src/server/service/installer.cpp @@ -28,237 +28,17 @@ #include <privilege-control.h> -#include <sys/stat.h> -#include <sys/smack.h> -#include <sys/xattr.h> -#include <linux/xattr.h> -#include <memory> -#include <fts.h> -#include <cstring> - #include "installer.h" #include "protocols.h" #include "security-manager.h" #include "smack-rules.h" +#include "smack-labels.h" #include "privilege_db.h" namespace SecurityManager { -namespace { - const InterfaceID INSTALLER_IFACE = 0; -/* Const defined below is used to label links to executables */ -const char *const XATTR_NAME_TIZENEXEC = XATTR_SECURITY_PREFIX "TIZEN_EXEC_LABEL"; - -/** - * Return values - * -1 - error - * 0 - skip - * 1 - label - */ -enum class FileDecision { - SKIP = 0, - LABEL = 1, - ERROR = -1 -}; - -typedef std::function<FileDecision(const FTSENT*)> LabelDecisionFn; - - -FileDecision labelAll(const FTSENT *ftsent __attribute__((unused))) -{ - LogDebug("Entering function: " << __func__); - - return FileDecision::LABEL; -} - -FileDecision labelDirs(const FTSENT *ftsent) -{ - LogDebug("Entering function: " << __func__); - - // label only directories - if (S_ISDIR(ftsent->fts_statp->st_mode)) - return FileDecision::LABEL; - return FileDecision::SKIP; -} - -FileDecision labelExecs(const FTSENT *ftsent) -{ - LogDebug("Entering function: " << __func__); - - LogDebug("Mode = " << ftsent->fts_statp->st_mode); - // label only regular executable files - if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR)) - return FileDecision::LABEL; - return FileDecision::SKIP; -} - - -FileDecision labelLinksToExecs(const FTSENT *ftsent) -{ - LogDebug("Entering function: " << __func__); - - struct stat buf; - - // check if it's a link - if ( !S_ISLNK(ftsent->fts_statp->st_mode)) - return FileDecision::SKIP; - - std::unique_ptr<char, std::function<void(void*)>> target(realpath(ftsent->fts_path, NULL), free); - - if (!target.get()) { - LogError("Getting link target for " << ftsent->fts_path << " failed (Error = " << strerror(errno) << ")"); - return FileDecision::ERROR; - } - - if (-1 == stat(target.get(), &buf)) { - LogError("stat failed for " << target.get() << " (Error = " << strerror(errno) << ")"); - return FileDecision::ERROR; - } - // skip if link target is not a regular executable file - if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) { - LogDebug(target.get() << "is not a regular executable file. Skipping."); - return FileDecision::SKIP; - } - - return FileDecision::LABEL; -} - -bool dirSetSmack(const std::string &path, const std::string &label, - const char *xattr_name, LabelDecisionFn fn) -{ - LogDebug("Entering function: "<< __func__ <<". Params:" - " path=" << path << ", label=" << label << ", xattr=" << xattr_name); - - - char *const path_argv[] = {const_cast<char *>(path.c_str()), NULL}; - FTSENT *ftsent; - FileDecision ret; - - std::unique_ptr<FTS, std::function<void(FTS*)> > fts( - fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL), - fts_close); - - if (fts.get() == NULL) { - LogError("fts_open failed."); - return false; - } - - while ((ftsent = fts_read(fts.get())) != NULL) { - /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */ - if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) { - LogError("FTS_ERR error or failed stat(2) (FTS_NS)"); - return false; - } - - ret = fn(ftsent); - if (ret == FileDecision::ERROR) { - LogError("fn(ftsent) failed."); - return false; - } - - if (ret == FileDecision::LABEL) { - if (lsetxattr(ftsent->fts_path, xattr_name, label.c_str(), label.length(), 0) != 0) { - LogError("lsetxattr failed."); - return false; - } - } - - } - - /* If last call to fts_read() set errno, we need to return error. */ - if ((errno != 0) && (ftsent == NULL)) { - LogError("Last errno from fts_read: " << strerror(errno)); - return false; - } - return true; -} - - -bool labelDir(const std::string &path, const std::string &label, - bool set_transmutable, bool set_executables) -{ - LogDebug("Entering function: "<< __func__ <<". Params:" - " path=" << path << " label= " << label - << " set_transmutable= " << set_transmutable - << " set_executables= " << set_executables); - bool ret = true; - - // setting access label on everything in given directory and below - ret = dirSetSmack(path, label, XATTR_NAME_SMACK, labelAll); - if (!ret) { - LogError("dirSetSmack failed (access label)"); - return ret; - } - - if (set_transmutable) { - // setting transmute on dirs - ret = dirSetSmack(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, labelDirs); - if (!ret) { - LogError("dirSetSmack failed (transmute)"); - return ret; - } - } - - if (set_executables) { - ret = dirSetSmack(path, label, XATTR_NAME_SMACKEXEC, &labelExecs); - if (!ret) - { - LogError("dirSetSmack failed (execs)."); - return ret; - } - - //setting execute label for everything with permission to execute - ret = dirSetSmack(path, label, XATTR_NAME_TIZENEXEC, &labelLinksToExecs); - if (!ret) - { - LogError("dirSetSmack failed (link to execs)."); - return ret; - } - } - - return ret; -} - - -bool setupPath(const std::string &pkgId, const std::pair<std::string, int> &appPath) -{ - using namespace SecurityManager; - - app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second); - std::string label; - bool label_executables, label_transmute; - - - switch (pathType) { - case SECURITY_MANAGER_PATH_PRIVATE: - if (!SmackRules::generateAppLabel(pkgId, label)) - return false; - label_executables = true; - label_transmute = false; - break; - case SECURITY_MANAGER_PATH_PUBLIC: - label.assign(InstallerService::LABEL_FOR_PUBLIC_APP_PATH); - label_executables = false; - label_transmute = true; - break; - case SECURITY_MANAGER_PATH_PUBLIC_RO: - label.assign("_"); - label_executables = false; - label_transmute = false; - break; - default: - LogError("Path type not known."); - return false; - } - return labelDir(appPath.first, label, label_transmute, label_executables); -} - -} // namespace anonymous - -/* Const defined below is used to label links to executables */ -const char *const InstallerService::LABEL_FOR_PUBLIC_APP_PATH = "User"; InstallerService::InstallerService() { @@ -383,7 +163,7 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s LogDebug("pkgId: " << req.pkgId); std::string smackLabel; - if (!SmackRules::generateAppLabel(req.pkgId, smackLabel)) { + if (!generateAppLabel(req.pkgId, smackLabel)) { LogError("Cannot generate Smack label for package"); Serialization::Serialize(send, SECURITY_MANAGER_API_ERROR_SERVER_ERROR); return false; @@ -440,8 +220,11 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s } // register paths - for (const auto& appPath : req.appPaths) { - result = setupPath(req.pkgId, appPath); + for (const auto &appPath : req.appPaths) { + const std::string &path = appPath.first; + app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second); + result = setupPath(req.pkgId, path, pathType); + if (!result) { LogDebug("setupPath() failed "); goto error_label; @@ -512,7 +295,7 @@ bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer } else { LogDebug("pkgId: " << pkgId); - if (!SmackRules::generateAppLabel(pkgId, smackLabel)) { + if (!generateAppLabel(pkgId, smackLabel)) { LogError("Cannot generate Smack label for package"); goto error_label; } diff --git a/src/server/service/smack-labels.cpp b/src/server/service/smack-labels.cpp new file mode 100644 index 00000000..3b88c738 --- /dev/null +++ b/src/server/service/smack-labels.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa <r.krypa@samsung.com> + * + * 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 + */ +/** + * @file smack-labels.cpp + * @author Jan Cybulski <j.cybulski@samsung.com> + * @author Rafal Krypa <r.krypa@samsung.com> + * @version 1.0 + * @brief Implementation of functions managing smack labels + * + */ + +#include <sys/stat.h> +#include <sys/smack.h> +#include <sys/xattr.h> +#include <linux/xattr.h> +#include <memory> +#include <fts.h> +#include <cstring> +#include <string> + +#include <dpl/log/log.h> + +#include "security-manager.h" +#include "smack-labels.h" + +namespace SecurityManager { + +/* Const defined below is used to label links to executables */ +const char *const XATTR_NAME_TIZENEXEC = XATTR_SECURITY_PREFIX "TIZEN_EXEC_LABEL"; + +/* Const defined below is used to label links to executables */ +const char *const LABEL_FOR_PUBLIC_APP_PATH = "User"; + +enum class FileDecision { + SKIP = 0, + LABEL = 1, + ERROR = -1 +}; + +typedef std::function<FileDecision(const FTSENT*)> LabelDecisionFn; + + +bool generateAppLabel(const std::string &appPkgId, std::string &label) +{ + (void) appPkgId; // TODO use pkgId to generate label + label = "User"; + return true; +} + +static FileDecision labelAll(const FTSENT *ftsent __attribute__((unused))) +{ + LogDebug("Entering function: " << __func__); + + return FileDecision::LABEL; +} + +static FileDecision labelDirs(const FTSENT *ftsent) +{ + LogDebug("Entering function: " << __func__); + + // label only directories + if (S_ISDIR(ftsent->fts_statp->st_mode)) + return FileDecision::LABEL; + return FileDecision::SKIP; +} + +static FileDecision labelExecs(const FTSENT *ftsent) +{ + LogDebug("Entering function: " << __func__); + + LogDebug("Mode = " << ftsent->fts_statp->st_mode); + // label only regular executable files + if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR)) + return FileDecision::LABEL; + return FileDecision::SKIP; +} + +static FileDecision labelLinksToExecs(const FTSENT *ftsent) +{ + LogDebug("Entering function: " << __func__); + + struct stat buf; + + // check if it's a link + if ( !S_ISLNK(ftsent->fts_statp->st_mode)) + return FileDecision::SKIP; + + std::unique_ptr<char, std::function<void(void*)>> target(realpath(ftsent->fts_path, NULL), free); + + if (!target.get()) { + LogError("Getting link target for " << ftsent->fts_path << " failed (Error = " << strerror(errno) << ")"); + return FileDecision::ERROR; + } + + if (-1 == stat(target.get(), &buf)) { + LogError("stat failed for " << target.get() << " (Error = " << strerror(errno) << ")"); + return FileDecision::ERROR; + } + // skip if link target is not a regular executable file + if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) { + LogDebug(target.get() << "is not a regular executable file. Skipping."); + return FileDecision::SKIP; + } + + return FileDecision::LABEL; +} + +static bool dirSetSmack(const std::string &path, const std::string &label, + const char *xattr_name, LabelDecisionFn fn) +{ + LogDebug("Entering function: "<< __func__ <<". Params:" + " path=" << path << ", label=" << label << ", xattr=" << xattr_name); + + + char *const path_argv[] = {const_cast<char *>(path.c_str()), NULL}; + FTSENT *ftsent; + FileDecision ret; + + std::unique_ptr<FTS, std::function<void(FTS*)> > fts( + fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL), + fts_close); + + if (fts.get() == NULL) { + LogError("fts_open failed."); + return false; + } + + while ((ftsent = fts_read(fts.get())) != NULL) { + /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */ + if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) { + LogError("FTS_ERR error or failed stat(2) (FTS_NS)"); + return false; + } + + ret = fn(ftsent); + if (ret == FileDecision::ERROR) { + LogError("fn(ftsent) failed."); + return false; + } + + if (ret == FileDecision::LABEL) { + if (lsetxattr(ftsent->fts_path, xattr_name, label.c_str(), label.length(), 0) != 0) { + LogError("lsetxattr failed."); + return false; + } + } + + } + + /* If last call to fts_read() set errno, we need to return error. */ + if ((errno != 0) && (ftsent == NULL)) { + LogError("Last errno from fts_read: " << strerror(errno)); + return false; + } + return true; +} + + +static bool labelDir(const std::string &path, const std::string &label, + bool set_transmutable, bool set_executables) +{ + LogDebug("Entering function: "<< __func__ <<". Params:" + " path=" << path << " label= " << label + << " set_transmutable= " << set_transmutable + << " set_executables= " << set_executables); + bool ret = true; + + // setting access label on everything in given directory and below + ret = dirSetSmack(path, label, XATTR_NAME_SMACK, labelAll); + if (!ret) { + LogError("dirSetSmack failed (access label)"); + return ret; + } + + if (set_transmutable) { + // setting transmute on dirs + ret = dirSetSmack(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, labelDirs); + if (!ret) { + LogError("dirSetSmack failed (transmute)"); + return ret; + } + } + + if (set_executables) { + ret = dirSetSmack(path, label, XATTR_NAME_SMACKEXEC, &labelExecs); + if (!ret) + { + LogError("dirSetSmack failed (execs)."); + return ret; + } + + //setting execute label for everything with permission to execute + ret = dirSetSmack(path, label, XATTR_NAME_TIZENEXEC, &labelLinksToExecs); + if (!ret) + { + LogError("dirSetSmack failed (link to execs)."); + return ret; + } + } + + return ret; +} + +bool setupPath(const std::string &pkgId, const std::string &path, + app_install_path_type pathType) +{ + std::string label; + bool label_executables, label_transmute; + + switch (pathType) { + case SECURITY_MANAGER_PATH_PRIVATE: + if (!generateAppLabel(pkgId, label)) + return false; + label_executables = true; + label_transmute = false; + break; + case SECURITY_MANAGER_PATH_PUBLIC: + label.assign(LABEL_FOR_PUBLIC_APP_PATH); + label_executables = false; + label_transmute = true; + break; + case SECURITY_MANAGER_PATH_PUBLIC_RO: + label.assign("_"); + label_executables = false; + label_transmute = false; + break; + default: + LogError("Path type not known."); + return false; + } + return labelDir(path, label, label_transmute, label_executables); +} + +} // namespace SecurityManager diff --git a/src/server/service/smack-rules.cpp b/src/server/service/smack-rules.cpp index 32b83c93..f8d4f09d 100644 --- a/src/server/service/smack-rules.cpp +++ b/src/server/service/smack-rules.cpp @@ -35,6 +35,7 @@ #include <dpl/log/log.h> #include <tzplatform_config.h> +#include "smack-labels.h" #include "smack-rules.h" namespace SecurityManager { @@ -42,13 +43,6 @@ namespace SecurityManager { const char *const SMACK_APP_LABEL_TEMPLATE = "~APP~"; const char *const APP_RULES_TEMPLATE_FILE_PATH = tzplatform_mkpath(TZ_SYS_SMACK, "app-rules-template.smack"); -bool SmackRules::generateAppLabel(const std::string &appPkgId, std::string &label) -{ - (void) appPkgId; //todo use pkgId to generate label - label = "User"; - return true; -} - SmackRules::SmackRules() { if (smack_accesses_new(&m_handle) < 0) { |