summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadoslaw Bartosiak <r.bartosiak@samsung.com>2016-04-29 16:16:22 +0200
committerRadoslaw Bartosiak <r.bartosiak@samsung.com>2016-05-23 16:00:26 +0200
commit47647b392d78be429f765ec7f5c85e0968298710 (patch)
tree7f8737a6c605b5e560470a463b22cb8609961b4c
parenta1f04212d1db38d1e32ddcf9c045f5d09ec8ef50 (diff)
downloadsecurity-manager-47647b392d78be429f765ec7f5c85e0968298710.tar.gz
security-manager-47647b392d78be429f765ec7f5c85e0968298710.tar.bz2
security-manager-47647b392d78be429f765ec7f5c85e0968298710.zip
Implement API for managing list of permitted labels for launcher
Four new API functions: - security_manager_app_labels_monitor_init - security_manager_app_labels_monitor_finish - security_manager_app_labels_monitor_get_fd - security_manager_app_labels_monitor_process They provide functionality needed for the launcher to run without CAP_MAC_ADMIN. It will rely on new feature of Smack: relabel-self list of labels, that a process can change its label to without special capabilities. The new APIs will enable the launcher to wait for changes of apps labels list (when an app is installed or uninstalled) and to update its relabel-list with a separate, dedicated function. Change-Id: I1d8a7bce8c081ba27e7c388ee096c7c07005d92d Signed-off-by: Radoslaw Bartosiak <r.bartosiak@samsung.com>
-rwxr-xr-xpackaging/security-manager.spec8
-rw-r--r--src/client/CMakeLists.txt1
-rw-r--r--src/client/client-label-monitor.cpp266
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/config.cpp1
-rw-r--r--src/common/include/config.h3
-rw-r--r--src/common/include/permissible-set.h79
-rw-r--r--src/common/include/service_impl.h2
-rw-r--r--src/common/permissible-set.cpp143
-rwxr-xr-xsrc/common/service_impl.cpp9
-rw-r--r--src/include/CMakeLists.txt1
-rw-r--r--src/include/label-monitor.h118
-rw-r--r--src/include/security-manager-types.h9
-rw-r--r--src/include/security-manager.h1
14 files changed, 640 insertions, 2 deletions
diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec
index cf4f9217..ab7af8a3 100755
--- a/packaging/security-manager.spec
+++ b/packaging/security-manager.spec
@@ -100,6 +100,12 @@ ln -s ../security-manager-rules-loader.service %{buildroot}/%{_unitdir}/basic.ta
mkdir -p %{buildroot}/%{TZ_SYS_DB}
touch %{buildroot}/%{TZ_SYS_DB}/.security-manager.db
touch %{buildroot}/%{TZ_SYS_DB}/.security-manager.db-journal
+mkdir -p %{buildroot}%{_sysconfdir}/skel/apps_rw
+touch %{buildroot}%{_sysconfdir}/skel/apps_rw/apps-names
+chsmack -a _ %{buildroot}%{_sysconfdir}/skel/apps_rw/apps-names
+mkdir -p %{buildroot}%{TZ_SYS_RW_APP}
+touch %{buildroot}%{TZ_SYS_RW_APP}/apps-names
+chsmack -a _ %{buildroot}%{TZ_SYS_RW_APP}/apps-names
%clean
rm -rf %{buildroot}
@@ -151,6 +157,8 @@ fi
%attr(755,root,root) %{_bindir}/security-manager-cleanup
%attr(755,root,root) %{_sysconfdir}/gumd/useradd.d/50_security-manager-add.post
%attr(755,root,root) %{_sysconfdir}/gumd/userdel.d/50_security-manager-remove.pre
+%attr(444,root,root) %{_sysconfdir}/skel/apps_rw/apps-names
+%attr(444,root,root) %{TZ_SYS_RW_APP}/apps-names
%dir %attr(700,root,root) %{TZ_SYS_VAR}/security-manager/rules
%dir %attr(700,root,root) %{TZ_SYS_VAR}/security-manager/rules-merged
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
index 5399a554..f934617d 100644
--- a/src/client/CMakeLists.txt
+++ b/src/client/CMakeLists.txt
@@ -23,6 +23,7 @@ SET(CLIENT_SOURCES
${CLIENT_PATH}/client-security-manager.cpp
${CLIENT_PATH}/client-common.cpp
${CLIENT_PATH}/client-offline.cpp
+ ${CLIENT_PATH}/client-label-monitor.cpp
)
ADD_LIBRARY(${TARGET_CLIENT} SHARED ${CLIENT_SOURCES})
diff --git a/src/client/client-label-monitor.cpp b/src/client/client-label-monitor.cpp
new file mode 100644
index 00000000..96aa4e5a
--- /dev/null
+++ b/src/client/client-label-monitor.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2016 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 client-label-monitor.cpp
+ * @author Rafal Krypa <r.krypa@samsung.com>
+ * @author Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version 1.0
+ * @brief Implementation of API for managing list of permited labels for launcher
+ */
+
+#include <algorithm>
+#include <cstring>
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <vector>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <client-common.h>
+#include <config.h>
+#include <dpl/log/log.h>
+#include <dpl/errno_string.h>
+#include <label-monitor.h>
+#include <permissible-set.h>
+#include <protocols.h>
+#include <smack-labels.h>
+
+struct app_labels_monitor {
+ int inotify;
+ int global_labels_file_watch;
+ int user_labels_file_watch;
+ bool fresh;
+ std::string user_label_file_path;
+ app_labels_monitor() : inotify(-1), global_labels_file_watch(-1), user_labels_file_watch(-1),
+ fresh(true) {}
+};
+
+static lib_retcode apply_relabel_list(const std::string &global_label_file,
+ const std::string &user_label_file)
+{
+ std::vector<std::string> names;
+ try {
+ PermissibleSet::readNamesFromPermissibleFile(global_label_file, names);
+ PermissibleSet::readNamesFromPermissibleFile(user_label_file, names);
+ std::vector<const char*> temp;
+ std::transform(names.begin(), names.end(), std::back_inserter(temp),
+ [] (std::string &label) {label = SmackLabels::generateAppLabel(label);
+ return label.c_str();});
+ if (smack_set_relabel_self(const_cast<const char **>(temp.data()), temp.size()) != 0) {
+ LogError("smack_set_relabel_self failed");
+ return SECURITY_MANAGER_ERROR_SET_RELABEL_SELF_FAILED;
+ }
+ } catch (PermissibleSet::PermissibleSetException::FileOpenError &e) {
+ LogWarning("Invalid state of configuration files - smack_set_relabel_self not called");
+ return SECURITY_MANAGER_SUCCESS;
+ } catch (PermissibleSet::PermissibleSetException::FileReadError &e) {
+ LogError("Failed to read the configuration files");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ return SECURITY_MANAGER_SUCCESS;
+}
+
+static lib_retcode inotify_add_watch_full(int fd, const char* pathname, uint32_t mask, int *wd)
+{
+ int inotify_fd = inotify_add_watch(fd, pathname, mask);
+ if (inotify_fd == -1) {
+ LogError("Inotify watch failed on file " << pathname << ": " << GetErrnoString(errno));
+ return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
+ }
+ *wd = inotify_fd;
+ return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_app_labels_monitor_init(app_labels_monitor **monitor)
+{
+ typedef std::unique_ptr<app_labels_monitor, void (*)(app_labels_monitor *)> monitorPtr;
+ return try_catch([&] {
+ LogDebug("security_manager_app_labels_monitor_init() called");
+ if (monitor == nullptr) {
+ LogWarning("Error input param \"monitor\"");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+ int ret;
+ lib_retcode ret_lib;
+ const std::string globalFile =
+ PermissibleSet::getPerrmissibleFileLocation(SM_APP_INSTALL_GLOBAL);
+ const std::string userFile =
+ PermissibleSet::getPerrmissibleFileLocation(SM_APP_INSTALL_LOCAL);
+
+ *monitor = nullptr;
+
+ monitorPtr m(new app_labels_monitor, security_manager_app_labels_monitor_finish);
+ if (!m) {
+ LogError("Bad memory allocation for app_labels_monitor");
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ }
+ ret = inotify_init();
+ if (ret == -1) {
+ LogError("Inotify init failed: " << GetErrnoString(errno));
+ return SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED;
+ }
+ m.get()->inotify = ret;
+ ret_lib = inotify_add_watch_full(m.get()->inotify, globalFile.c_str(),
+ IN_CLOSE_WRITE, &(m.get()->global_labels_file_watch));
+ if (ret_lib != SECURITY_MANAGER_SUCCESS) {
+ return ret_lib;
+ }
+ ret_lib = inotify_add_watch_full(m.get()->inotify,
+ userFile.c_str(), IN_CLOSE_WRITE, &(m.get()->user_labels_file_watch));
+ if (ret_lib != SECURITY_MANAGER_SUCCESS) {
+ return ret_lib;
+ }
+ m->user_label_file_path = userFile;
+ *monitor = m.release();
+ return SECURITY_MANAGER_SUCCESS;
+ });
+}
+
+SECURITY_MANAGER_API
+void security_manager_app_labels_monitor_finish(app_labels_monitor *monitor)
+{
+ try_catch([&] {
+ LogDebug("security_manager_app_labels_monitor_finish() called");
+ if (monitor == nullptr) {
+ LogDebug("input param \"monitor\" is nullptr");
+ return 0;
+ }
+ std::unique_ptr<app_labels_monitor> m(monitor);
+ if (!m)
+ LogError("Bad memory allocation for app_labels_monitor");
+ if (monitor->inotify != -1) {
+ if (monitor->global_labels_file_watch != -1) {
+ int ret = inotify_rm_watch(monitor->inotify, monitor->global_labels_file_watch);
+ if (ret == -1) {
+ LogError("Inotify watch removal failed on file " <<
+ Config::APPS_NAME_FILE << ": " << GetErrnoString(errno));
+ }
+ }
+ if (monitor->user_labels_file_watch != -1) {
+ int ret = inotify_rm_watch(monitor->inotify, monitor->user_labels_file_watch);
+ if (ret == -1) {
+ LogError("Inotify watch removal failed on file "
+ << monitor->user_label_file_path << ": " << GetErrnoString(errno));
+ }
+ }
+ close(monitor->inotify);
+ }
+ return 0;
+ });
+}
+
+SECURITY_MANAGER_API
+int security_manager_app_labels_monitor_get_fd(app_labels_monitor const *monitor, int *fd)
+{
+ return try_catch([&] {
+ LogDebug("security_manager_app_labels_monitor_get_fd() called");
+
+ if (monitor == nullptr) {
+ LogWarning("Error input param \"monitor\"");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+
+ if (fd == nullptr) {
+ LogWarning("Error input param \"fd\"");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+
+ if (monitor->inotify == -1 || monitor->global_labels_file_watch == -1 ||
+ monitor->user_labels_file_watch == -1) {
+ LogWarning("Relabel list monitor was not initialized");
+ return SECURITY_MANAGER_ERROR_NOT_INITIALIZED;
+ }
+
+ *fd = monitor->inotify;
+ return SECURITY_MANAGER_SUCCESS;
+ });
+}
+
+SECURITY_MANAGER_API
+int security_manager_app_labels_monitor_process(app_labels_monitor *monitor)
+{
+ typedef std::unique_ptr<char, void (*)(void *)> bufPtr;
+ return try_catch([&] {
+ LogDebug("security_manager_app_labels_process() called");
+ if (monitor == nullptr) {
+ LogWarning("Error input param \"monitor\"");
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ }
+ const std::string globalFile =
+ PermissibleSet::getPerrmissibleFileLocation(SM_APP_INSTALL_GLOBAL);
+
+ if (monitor->inotify == -1 || monitor->global_labels_file_watch == -1 ||
+ monitor->user_labels_file_watch == -1) {
+ LogWarning("Relabel list monitor was not initialized");
+ return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+ }
+
+ if (monitor->fresh) {
+ monitor->fresh = false;
+ return apply_relabel_list(globalFile, monitor->user_label_file_path);
+ }
+
+ int avail;
+ int ret = ioctl(monitor->inotify, FIONREAD, &avail);
+ if (ret == -1) {
+ LogError("Ioctl on inotify descriptor failed: " << GetErrnoString(errno));
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+
+ bufPtr buffer(static_cast<char *>(malloc(avail)), free);
+ for (int pos = 0; pos < avail;) {
+ int ret = TEMP_FAILURE_RETRY(read(monitor->inotify, buffer.get() + pos, avail - pos));
+ if (ret == -1) {
+ LogError("Inotify read failed: " << GetErrnoString(errno));
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
+ }
+ pos += ret;
+ }
+
+ for (int pos = 0; pos < avail;) {
+ struct inotify_event event;
+
+ /* Event must be copied to avoid memory alignment issues */
+ memcpy(&event, buffer.get() + pos, sizeof(struct inotify_event));
+ pos += sizeof(struct inotify_event) + event.len;
+ if ((event.mask & IN_CLOSE_WRITE) &&
+ ((event.wd == monitor->global_labels_file_watch) ||
+ (event.wd == monitor->user_labels_file_watch))
+ ){
+ lib_retcode r = apply_relabel_list(globalFile, monitor->user_label_file_path);
+ if (r != SECURITY_MANAGER_SUCCESS)
+ return r;
+ break;
+ }
+ }
+ return SECURITY_MANAGER_SUCCESS;
+ });
+}
+
+
+
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 64c51e57..7c329186 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -51,6 +51,7 @@ SET(COMMON_SOURCES
${COMMON_PATH}/credentials.cpp
${COMMON_PATH}/cynara.cpp
${COMMON_PATH}/file-lock.cpp
+ ${COMMON_PATH}/permissible-set.cpp
${COMMON_PATH}/protocols.cpp
${COMMON_PATH}/message-buffer.cpp
${COMMON_PATH}/privilege_db.cpp
diff --git a/src/common/config.cpp b/src/common/config.cpp
index 8b15c21c..a5f3261a 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -43,6 +43,7 @@ const std::string PRIVILEGE_POLICY_USER = "http://tizen.org/privilege/notex
const std::string PRIVILEGE_POLICY_ADMIN = "http://tizen.org/privilege/internal/usermanagement";
const std::string PRIVILEGE_APPSHARING_ADMIN = "http://tizen.org/privilege/notexist";
+const std::string APPS_NAME_FILE = "apps-names";
};
} /* namespace SecurityManager */
diff --git a/src/common/include/config.h b/src/common/include/config.h
index 4bb655ff..b719a720 100644
--- a/src/common/include/config.h
+++ b/src/common/include/config.h
@@ -41,6 +41,9 @@ extern const std::string PRIVILEGE_POLICY_USER;
extern const std::string PRIVILEGE_POLICY_ADMIN;
extern const std::string PRIVILEGE_APPSHARING_ADMIN;
+/* Files used in permitted label managment*/
+extern const std::string APPS_NAME_FILE;
+
};
} /* namespace SecurityManager */
diff --git a/src/common/include/permissible-set.h b/src/common/include/permissible-set.h
new file mode 100644
index 00000000..83b69ec7
--- /dev/null
+++ b/src/common/include/permissible-set.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 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 permissible-set.h
+ * @author RafaƂ Krypa <r.krypa@samsung.com>
+ * @author Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version 1.0
+ * @brief Header with API for adding, deleting and reading permissible names
+ * @brief (names of installed applications)
+ */
+#ifndef _PERMISSIBLE_SET_H_
+#define _PERMISSIBLE_SET_H_
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+#include <dpl/exception.h>
+#include <security-manager-types.h>
+
+namespace SecurityManager {
+namespace PermissibleSet {
+
+class PermissibleSetException {
+public:
+ DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, FileLockError)
+ DECLARE_EXCEPTION_TYPE(Base, FileOpenError)
+ DECLARE_EXCEPTION_TYPE(Base, FileReadError)
+ DECLARE_EXCEPTION_TYPE(Base, FileWriteError)
+};
+/**
+ * Return path to file with current list of application names
+ * installed globally or locally for the user.
+ *
+ * @param[in] installationType type of installation (global or local)
+ * @return path to file with names
+ */
+std::string getPerrmissibleFileLocation(int installationType);
+/**
+ * Update permissable file with current content of database
+ * @throws FileLockError
+ * @throws FileOpenError
+ * @throws FileWriteError
+ *
+ * @param[in] uid user id
+ * @param[in] installationType type of installation (global or local)
+ * @return resulting true on success
+ */
+void updatePermissibleFile(const uid_t uid, const int installationType);
+/**
+ * Read names from a file into a vector
+ * @throws FileLockError
+ * @throws FileOpenError
+ * @throws FileReadError
+ *
+ * @param[in] nameFile contains application names
+ * @param[out] names vector to which application names are added
+ * @return SECURITY_MANAGER_SUCCESS or error code
+ */
+void readNamesFromPermissibleFile(const std::string &nameFile, std::vector<std::string> &names);
+} // PermissibleSet
+} // SecurityManager
+#endif /* _PERMISSIBLE_SET_H_ */
diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h
index 8c9129c6..903b735a 100644
--- a/src/common/include/service_impl.h
+++ b/src/common/include/service_impl.h
@@ -67,8 +67,6 @@ private:
static void getTizen2XApps(SmackRules::PkgsApps &pkgsApps);
- static bool getZoneId(std::string &zoneId);
-
int dropOnePrivateSharing(const std::string &ownerAppName,
const std::string &ownerPkgName,
const std::vector<std::string> &ownerPkgContents,
diff --git a/src/common/permissible-set.cpp b/src/common/permissible-set.cpp
new file mode 100644
index 00000000..09480bae
--- /dev/null
+++ b/src/common/permissible-set.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2016 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 permissible-set.cpp
+ * @author Rafal Krypa <r.krypa@samsung.com>
+ * @author Radoslaw Bartosiak <r.bartosiak@samsung.com>
+ * @version 1.0
+ * @brief Implementation of API for adding, deleting and reading permissible names
+ * @brief (names of installed applications)
+ */
+#ifndef _GNU_SOURCE //for TEMP_FAILURE_RETRY
+#define _GNU_SOURCE
+#endif
+
+#include <cstdio>
+#include <cstring>
+#include <memory>
+#include <pwd.h>
+#include <string>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <config.h>
+#include <dpl/errno_string.h>
+#include <dpl/exception.h>
+#include <dpl/log/log.h>
+#include <permissible-set.h>
+#include <privilege_db.h>
+#include <security-manager-types.h>
+#include <tzplatform_config.h>
+
+typedef std::unique_ptr<FILE, int (*)(FILE *)> filePtr;
+
+namespace SecurityManager {
+namespace PermissibleSet {
+
+static filePtr openAndLockNameFile(const std::string &nameFile, const char* mode)
+{
+ filePtr file(fopen(nameFile.c_str(), mode), fclose);
+ if (!file) {
+ LogError("Unable to open file" << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileOpenError, "Unable to open file ");
+ }
+
+ int ret = TEMP_FAILURE_RETRY(flock(fileno(file.get()), LOCK_EX));
+ if (ret == -1) {
+ LogError("Unable to lock file " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileLockError, "Unable to lock file");
+ }
+ return file;
+}
+
+std::string getPerrmissibleFileLocation(int installationType)
+{
+ if ((installationType == SM_APP_INSTALL_GLOBAL)
+ || (installationType == SM_APP_INSTALL_PRELOADED))
+ return tzplatform_mkpath(TZ_SYS_RW_APP, Config::APPS_NAME_FILE.c_str());
+ return tzplatform_mkpath(TZ_USER_APP, Config::APPS_NAME_FILE.c_str());
+
+}
+
+static void markPermissibleFileValid(int fd, const std::string &nameFile, bool valid)
+{
+ int ret;
+ if (valid)
+ ret = TEMP_FAILURE_RETRY(fchmod(fd, 00444));
+ else
+ ret = TEMP_FAILURE_RETRY(fchmod(fd, 00000));
+ if (ret == -1) {
+ LogError("Error at fchmod " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileWriteError, "Error at fchmod");
+ }
+}
+
+void updatePermissibleFile(uid_t uid, int installationType)
+{
+ std::string nameFile = getPerrmissibleFileLocation(installationType);
+ filePtr file = openAndLockNameFile(nameFile, "w");
+ markPermissibleFileValid(fileno(file.get()), nameFile, false);
+ std::vector<std::string> appNames;
+ PrivilegeDb::getInstance().GetUserApps(uid, appNames);
+ for (auto &name : appNames) {
+ if (fprintf(file.get(), "%s\n", name.c_str()) < 0) {
+ LogError("Unable to fprintf() to file " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::PermissibleSetException::FileWriteError,
+ "Unable to fprintf() to file");
+ }
+ }
+ if (fflush(file.get()) != 0) {
+ LogError("Error at fflush " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileWriteError, "Error at fflush");
+ }
+ if (fsync(fileno(file.get())) == -1) {
+ LogError("Error at fsync " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileWriteError, "Error at fsync");
+ }
+ markPermissibleFileValid(fileno(file.get()), nameFile, true);
+}
+
+void readNamesFromPermissibleFile(const std::string &nameFile, std::vector<std::string> &names)
+{
+ filePtr file = openAndLockNameFile(nameFile, "r");
+ int ret;
+ do {
+ char *buf = nullptr;
+ std::size_t bufSize = 0;
+ switch (ret = getline(&buf, &bufSize, file.get())) {
+ case 0:
+ continue;
+ case -1:
+ if (feof(file.get()))
+ break;
+ LogError("Failure while reading file " << nameFile << ": " << GetErrnoString(errno));
+ ThrowMsg(PermissibleSetException::FileReadError, "Failure while reading file");
+ default:
+ std::unique_ptr<char, decltype(free)*> buf_up(buf, free);
+ if (buf[ret - 1] == '\n')
+ buf[ret - 1] = '\0';
+ names.push_back(buf);
+ buf_up.release();
+ }
+ } while (ret != -1);
+}
+
+} // PermissibleSet
+} // SecurityManager
diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp
index 4ea0baa3..d389b8d4 100755
--- a/src/common/service_impl.cpp
+++ b/src/common/service_impl.cpp
@@ -40,6 +40,7 @@
#include "protocols.h"
#include "privilege_db.h"
#include "cynara.h"
+#include "permissible-set.h"
#include "smack-rules.h"
#include "smack-labels.h"
#include "security-manager.h"
@@ -440,6 +441,7 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
// WTF? Why this commit is here? Shouldn't it be at the end of this function?
PrivilegeDb::getInstance().CommitTransaction();
LogDebug("Application installation commited to database");
+ PermissibleSet::updatePermissibleFile(req.uid, req.installationType);
} catch (const PrivilegeDb::Exception::IOError &e) {
LogError("Cannot access application database: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
@@ -455,6 +457,9 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
PrivilegeDb::getInstance().RollbackTransaction();
LogError("Error while setting Cynara rules for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ } catch (const PermissibleSet::PermissibleSetException::Base &e) {
+ LogError("Error while updating permissible file: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const SmackException::InvalidLabel &e) {
PrivilegeDb::getInstance().RollbackTransaction();
LogError("Error while generating Smack labels: " << e.DumpToString());
@@ -551,6 +556,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector<std::string>());
PrivilegeDb::getInstance().CommitTransaction();
LogDebug("Application uninstallation commited to database");
+ PermissibleSet::updatePermissibleFile(req.uid, req.installationType);
} catch (const PrivilegeDb::Exception::IOError &e) {
LogError("Cannot access application database: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
@@ -562,6 +568,9 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
PrivilegeDb::getInstance().RollbackTransaction();
LogError("Error while setting Cynara rules for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ } catch (const PermissibleSet::PermissibleSetException::Base &e) {
+ LogError("Error while updating permissible file: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const SmackException::InvalidLabel &e) {
PrivilegeDb::getInstance().RollbackTransaction();
LogError("Error while generating Smack labels: " << e.DumpToString());
diff --git a/src/include/CMakeLists.txt b/src/include/CMakeLists.txt
index 1a6d090c..f1d42643 100644
--- a/src/include/CMakeLists.txt
+++ b/src/include/CMakeLists.txt
@@ -4,6 +4,7 @@ INSTALL(FILES
${INCLUDE_PATH}/app-manager.h
${INCLUDE_PATH}/app-runtime.h
${INCLUDE_PATH}/app-sharing.h
+ ${INCLUDE_PATH}/label-monitor.h
${INCLUDE_PATH}/user-manager.h
${INCLUDE_PATH}/policy-manager.h
DESTINATION ${INCLUDE_INSTALL_DIR}/security-manager
diff --git a/src/include/label-monitor.h b/src/include/label-monitor.h
new file mode 100644
index 00000000..2637eaba
--- /dev/null
+++ b/src/include/label-monitor.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2016 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 label-monitor.h
+ * @author Rafal Krypa (r.krypa@samsung.com)
+ * @author Radoslaw Bartosiak (r.bartosiak@samsung.com)
+ * @version 1.0
+ * @brief Header with API targeted for launcher to monitor labels of installed applications
+ */
+#ifndef _LABEL_MONITOR_H_
+#define _LABEL_MONITOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "security-manager-types.h"
+
+typedef struct app_labels_monitor app_labels_monitor;
+
+/**
+ * Initialize applications' labels monitor
+ * The monitor is intended for watching for changes to the list of labels
+ * assigned to currently installed applications.
+ * It will allocate resources that must be freed later by
+ * \ref security_manager_app_labels_monitor_finish.
+ * Intended user of this function is the application launcher.
+ *
+ * \param[out] monitor pointer to the resulting applications' label monitor
+ *
+ * \return SECURITY_MANAGER_SUCCESS on success or error code on failure
+ *
+ * \par Example
+ * \parblock
+ * (warning: simplified code example, with committed error handling)
+ * \code{.c}
+ * app_labels_monitor *monitor;
+ * int fd;
+ * nfds_t nfds = 1;
+ * struct pollfd fds[1];
+ *
+ * security_manager_app_labels_monitor_init(&monitor);
+ * security_manager_app_labels_monitor_process(monitor);
+ * security_manager_app_labels_monitor_get_fd(monitor, &fd);
+ * fds[0].fd = fd;
+ * fds[0].events = POLLIN;
+ * while (1) {
+ * int poll_num = TEMP_FAILURE_RETRY(poll(fds, nfds, -1));
+ * if (poll_num > 0) {
+ * if (fds[0].revents & POLLIN) {
+ * security_manager_app_labels_monitor_process(monitor);
+ * // Do your stuff - react on new list of applications' labels
+ * }
+ * }
+ * }
+ * // ...
+ * // Before finishing, release the labels monitor
+ * security_manager_app_labels_monitor_finish(monitor);
+ *
+ * \endcode
+ */
+int security_manager_app_labels_monitor_init(app_labels_monitor **monitor);
+
+/**
+ * De-initialize applications' labels monitor
+ * Frees all resources previously allocated by \ref security_manager_app_labels_monitor_init
+ *
+ * \param[in] monitor an initialized applications' label monitor
+ *
+ * \return SECURITY_MANAGER_SUCCESS on success or error code on failure
+ */
+void security_manager_app_labels_monitor_finish(app_labels_monitor *monitor);
+
+/**
+ * Retrieve file descriptor for waiting on applications' labels monitor
+ * The file descriptor should be put to a select-like waiting loop. It will indicate
+ * new list of applications' labels by being ready for reading.
+ *
+ * \param[in] monitor an initialized applications' label monitor
+ * \param[out] fd pointer to the resulting file descriptor
+ *
+ * \return SECURITY_MANAGER_SUCCESS on success or error code on failure
+ */
+int security_manager_app_labels_monitor_get_fd(app_labels_monitor const *monitor, int *fd);
+
+/**
+ * Apply new list of applications' labels to Smack relabel-list of the current process
+ * This will give permission to the current process to change its Smack label to one
+ * of application labels, even after it drops CAP_MAC_ADMIN capability.
+ *
+ * \param[in] monitor an initialized applications' label monitor
+ *
+ * \return SECURITY_MANAGER_SUCCESS on success or error code on failure
+ *
+ * Access to this function requires CAP_MAC_ADMIN capability.
+ */
+int security_manager_app_labels_monitor_process(app_labels_monitor *monitor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LABEL_MONITOR_H_ */
diff --git a/src/include/security-manager-types.h b/src/include/security-manager-types.h
index 8f1c1db6..26ed29cf 100644
--- a/src/include/security-manager-types.h
+++ b/src/include/security-manager-types.h
@@ -47,6 +47,10 @@ enum lib_retcode {
SECURITY_MANAGER_ERROR_NO_SUCH_SERVICE,
SECURITY_MANAGER_ERROR_SERVER_ERROR,
SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED,
+ SECURITY_MANAGER_ERROR_WATCH_ADD_TO_FILE_FAILED,
+ SECURITY_MANAGER_ERROR_FILE_OPEN_FAILED,
+ SECURITY_MANAGER_ERROR_SET_RELABEL_SELF_FAILED,
+ SECURITY_MANAGER_ERROR_NOT_INITIALIZED,
};
/*! \brief accesses types for application installation paths*/
@@ -120,6 +124,11 @@ typedef struct private_sharing_req private_sharing_req;
struct path_req;
typedef struct path_req path_req;
+/*! \brief data structure responsible for handling information on
+ * changes in labels required by applications*/
+struct app_labels_monitor;
+typedef struct app_labels_monitor app_labels_monitor;
+
/*! \brief wildcard to be used in requests to match all possible values of given field.
* Use it, for example when it is desired to list or apply policy change for all
* users or all apps for selected user.
diff --git a/src/include/security-manager.h b/src/include/security-manager.h
index d9277744..b13a26a0 100644
--- a/src/include/security-manager.h
+++ b/src/include/security-manager.h
@@ -32,6 +32,7 @@
#include "app-manager.h"
#include "app-runtime.h"
#include "app-sharing.h"
+#include "label-monitor.h"
#include "user-manager.h"
#include "policy-manager.h"