From af33bcce7f9788be9545175dd41340e10b376dbd Mon Sep 17 00:00:00 2001 From: Jan Cybulski Date: Fri, 23 May 2014 07:39:36 +0200 Subject: [PATCH] security manager: function for labeling dirs Security manager used libprivilege-control's perm_app_setup_path. This commit removes this dependency by reimplementing the code that labels directories as internal function of installer service in security-manager. Change-Id: I57738ef310afddda235fe2bb45d95ee54d2ed587 Signed-off-by: Jan Cybulski --- src/server/service/installer.cpp | 243 ++++++++++++++++++++++++++++++++++----- src/server/service/installer.h | 2 + 2 files changed, 216 insertions(+), 29 deletions(-) diff --git a/src/server/service/installer.cpp b/src/server/service/installer.cpp index b02e22d..92d98ad 100644 --- a/src/server/service/installer.cpp +++ b/src/server/service/installer.cpp @@ -26,11 +26,21 @@ #include #include + +#include +#include +#include +#include +#include +#include +#include + #include "installer.h" #include "protocols.h" #include "security-server.h" #include "security-manager.h" #include "smack-rules.h" +#include "security-manager-common.h" namespace SecurityServer { @@ -38,31 +48,216 @@ 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"; + /** - * Convert Security Mangager's API path type to libprivilege-control's API path type. - * @return true on success + * Return values + * -1 - error + * 0 - skip + * 1 - label */ -bool TranslateAppPathType(const app_install_path_type path_type, - app_path_type_t& lpc_path_type) +enum class FileDecision { + SKIP = 0, + LABEL = 1, + ERROR = -1 +}; + +typedef std::function LabelDecisionFn; + + +FileDecision labelAll(const FTSENT *ftsent __attribute__((unused))) +{ + LogSecureDebug("Entering function: " << __func__); + + return FileDecision::LABEL; +} + +FileDecision labelDirs(const FTSENT *ftsent) +{ + LogSecureDebug("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) +{ + LogSecureDebug("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) { - switch (path_type) { - case SECURITY_MANAGER_PATH_PRIVATE: - lpc_path_type = APP_PATH_PRIVATE; - break; - case SECURITY_MANAGER_PATH_PUBLIC: - lpc_path_type = APP_PATH_PUBLIC; - break; - case SECURITY_MANAGER_PATH_PUBLIC_RO: - lpc_path_type = APP_PATH_FLOOR; - break; - default: + LogSecureDebug("Entering function: " << __func__); + + struct stat buf; + char *target; + + // check if it's a link + if ( !S_ISLNK(ftsent->fts_statp->st_mode)) + return FileDecision::SKIP; + + target = realpath(ftsent->fts_path, NULL); + if (!target) { + LogSecureError("Getting link target for " << ftsent->fts_path << " failed (Error = " << strerror(errno) << ")"); + return FileDecision::ERROR; + } + if (-1 == stat(target, &buf)) { + LogSecureError("stat failed for " << target << " (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)) { + LogSecureDebug(target << "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) +{ + LogSecureDebug("Entering function: "<< __func__ <<". Params:" + " path=" << path << ", label=" << label << ", xattr=" << xattr_name); + + + char *const path_argv[] = {const_cast(path.c_str()), NULL}; + FTSENT *ftsent; + FileDecision ret; + + std::unique_ptr > 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) +{ + LogSecureDebug("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 &appPath) +{ + using namespace SecurityManager; + + app_install_path_type pathType = static_cast(appPath.second); + 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(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() { @@ -222,19 +417,9 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s // register paths for (const auto& appPath : req.appPaths) { - app_path_type_t path_type; - if (!TranslateAppPathType((app_install_path_type)appPath.second, - path_type)) { - LogError("Unrecognized path type: " << appPath.second); - goto error_label; - } - LogDebug("Adding path: " << appPath.first << " (type " << path_type << ")"); - - // TODO: use pkgId. - result = perm_app_setup_path(req.appId.c_str(), appPath.first.c_str(), path_type); - if (PC_OPERATION_SUCCESS != result) { - // libprivilege error - LogDebug("perm_app_setup_path() returned " << result); + result = setupPath(req.pkgId, appPath); + if (!result) { + LogDebug("setupPath() failed "); goto error_label; } } diff --git a/src/server/service/installer.h b/src/server/service/installer.h index 843dca8..45c95f6 100644 --- a/src/server/service/installer.h +++ b/src/server/service/installer.h @@ -56,6 +56,8 @@ public: void process(const ReadEvent &event); void close(const CloseEvent &event); + static const char *const LABEL_FOR_PUBLIC_APP_PATH; + private: ConnectionInfoMap m_connectionInfoMap; -- 2.7.4