INCLUDE(FindPkgConfig)
+######################### let's setup directories #############################
+
+SET(LOCAL_STATE_DIR
+ "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALSTATEDIR}"
+ CACHE PATH
+ "Modifiable single-machine data directory")
+
+ADD_DEFINITIONS("-DLOCAL_STATE_DIR=\"${LOCAL_STATE_DIR}\"")
+
############################# compiler flags ##################################
SET(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg -Wp,-U_FORTIFY_SOURCE")
ADD_SUBDIRECTORY(systemd)
ADD_SUBDIRECTORY(db)
ADD_SUBDIRECTORY(policy)
+ADD_SUBDIRECTORY(migration)
--- /dev/null
+# Copyright (c) 2016 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.
+#
+# @file CMakeLists.txt
+# @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+# @brief CMake for migration script
+#
+
+CONFIGURE_FILE(security-manager-migration.in security-manager-migration @ONLY)
+
+INSTALL(PROGRAMS
+ ${CMAKE_BINARY_DIR}/migration/security-manager-migration
+ DESTINATION
+ ${BIN_INSTALL_DIR}
+ )
+
+
+
--- /dev/null
+#!/bin/bash
+
+SRC_PATH=/etc/smack/accesses.d
+DSC_PATH=@LOCAL_STATE_DIR@/security-manager/rules
+MRG_PATH=@LOCAL_STATE_DIR@/security-manager/rules-merged/rules.merged
+
+if [ -e $MRG_PATH ]; then
+ echo "No migration needed. File ${MRG_PATH} already exists."
+ exit 0
+fi
+
+echo "Running migration process"
+echo "Moving files from ${SRC_PATH} to ${DSC_PATH}"
+mv ${SRC_PATH}/app_* ${SRC_PATH}/pkg_* ${SRC_PATH}/author_* ${DSC_PATH}
+echo "Merging files from ${DSC_PATH} to ${MRG_PATH}"
+cat ${DSC_PATH}/* > ${MRG_PATH}
+echo "Migration process was finished"
+
%cmake . -DVERSION=%{version} \
-DBIN_INSTALL_DIR=%{_bindir} \
-DDB_INSTALL_DIR=%{TZ_SYS_DB} \
+ -DLOCAL_STATE_DIR=%{TZ_SYS_VAR} \
-DSYSTEMD_INSTALL_DIR=%{_unitdir} \
-DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \
-DCMAKE_VERBOSE_MAKEFILE=ON
mkdir -p %{buildroot}/%{_unitdir}/sockets.target.wants
mkdir -p %{buildroot}/%{_unitdir}/sysinit.target.wants
+mkdir -p %{buildroot}/%{_unitdir}/basic.target.wants
ln -s ../security-manager.socket %{buildroot}/%{_unitdir}/sockets.target.wants/security-manager.socket
ln -s ../security-manager-cleanup.service %{buildroot}/%{_unitdir}/sysinit.target.wants/security-manager-cleanup.service
+ln -s ../security-manager-rules-loader.service %{buildroot}/%{_unitdir}/basic.target.wants/security-manager-rules-loader.service
mkdir -p %{buildroot}/%{TZ_SYS_DB}
touch %{buildroot}/%{TZ_SYS_DB}/.security-manager.db
if [ $1 = 2 ]; then
# update
+ %{_bindir}/security-manager-migration
systemctl restart security-manager.service
%{_datadir}/security-manager/db/update.sh
fi
%files -n security-manager
%manifest security-manager.manifest
%defattr(-,root,root,-)
+%attr(755,root,root) %{_bindir}/security-manager-migration
%attr(755,root,root) %{_bindir}/security-manager
%attr(755,root,root) %{_bindir}/security-manager-cmd
%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
+%dir %attr(700,root,root) %{TZ_SYS_VAR}/security-manager/rules
+%dir %attr(700,root,root) %{TZ_SYS_VAR}/security-manager/rules-merged
%{_libdir}/libsecurity-manager-commons.so.*
%attr(-,root,root) %{_unitdir}/security-manager.*
%attr(-,root,root) %{_unitdir}/security-manager-cleanup.*
+%attr(-,root,root) %{_unitdir}/security-manager-rules-loader.service
+%attr(-,root,root) %{_unitdir}/basic.target.wants/security-manager-rules-loader.service
%attr(-,root,root) %{_unitdir}/sockets.target.wants/security-manager.*
%attr(-,root,root) %{_unitdir}/sysinit.target.wants/security-manager-cleanup.*
%config(noreplace) %attr(0600,root,root) %{TZ_SYS_DB}/.security-manager.db
${COMMON_PATH}/smack-rules.cpp
${COMMON_PATH}/smack-check.cpp
${COMMON_PATH}/service_impl.cpp
+ ${COMMON_PATH}/filesystem.cpp
)
ADD_LIBRARY(${TARGET_COMMON} SHARED ${COMMON_SOURCES})
)
INSTALL(TARGETS ${TARGET_COMMON} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(DIRECTORY DESTINATION ${LOCAL_STATE_DIR}/security-manager/rules)
+INSTALL(DIRECTORY DESTINATION ${LOCAL_STATE_DIR}/security-manager/rules-merged)
+
--- /dev/null
+/*
+ * 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 filesystem.cpp
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @version 1.0
+ * @brief Wrappers for filesystem operations.
+ *
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <vector>
+#include <memory>
+#include <string>
+
+#include <dpl/exception.h>
+#include <dpl/errno_string.h>
+#include <smack-exceptions.h>
+
+#include <filesystem.h>
+#include <filesystem-exception.h>
+
+namespace SecurityManager {
+namespace FS {
+
+FileNameVector getFilesFromDirectory(const std::string &path)
+{
+ FileNameVector result;
+ dirent tmp, *ptr;
+ int err;
+ std::unique_ptr<DIR, std::function<void(DIR*)>> dir(opendir(path.c_str()), closedir);
+
+ if (!dir.get()) {
+ err = errno;
+ ThrowMsg(FS::Exception::FileError, "Error opening directory: " << GetErrnoString(err));
+ }
+
+ while (true) {
+ if (readdir_r(dir.get(), &tmp, &ptr)) {
+ err = errno;
+ ThrowMsg(FS::Exception::FileError, "Error reading directory: " << GetErrnoString(err));
+ }
+
+ if (!ptr)
+ break;
+
+ struct stat finfo;
+ std::string filepath = path + "/" + ptr->d_name;
+ if (0 > stat(filepath.c_str(), &finfo)) {
+ ThrowMsg(FS::Exception::FileError, "Error reading: " << filepath);
+ continue;
+ }
+
+ if (S_ISREG(finfo.st_mode)) {
+ result.push_back(ptr->d_name);
+ }
+ }
+
+ return result;
+}
+
+} // namespace FS
+} // nanespace SecurityManager
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 fs-exceptions.h
+ * @author Rafal Krypa <r.krypa@samsung.com>
+ * @version 1.0
+ * @brief Declaration of Smack-specific exceptions
+ *
+ */
+#ifndef _FILESYSTEM_EXCEPTIONS_H_
+#define _FILESYSTEM_EXCEPTIONS_H_
+
+#include <dpl/exception.h>
+
+namespace SecurityManager {
+namespace FS {
+
+class Exception {
+public:
+ DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, FileError)
+};
+
+} // namespace FS
+} // namespace SecurityManager
+
+#endif /* _FILESYSTEM_EXCEPTIONS_H_ */
--- /dev/null
+/*
+ * 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 filesystem.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @version 1.0
+ * @brief Very simple wrapper for opendir/readdir.
+ *
+ */
+#ifndef _FILESYSTEM_H_
+#define _FILESYSTEM_H_
+
+#include <vector>
+#include <string>
+#include <filesystem-exception.h>
+
+namespace SecurityManager {
+namespace FS {
+
+typedef std::vector<std::string> FileNameVector;
+
+FileNameVector getFilesFromDirectory(const std::string &path);
+
+} // namespace FS
+} // nanespace SecurityManager
+
+#endif // _FILESYSTEM_H_
+
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Rafal Krypa <r.krypa@samsung.com>
*
void apply() const;
void clear() const;
- void saveToFile(const std::string &path, bool truncFile = true) const;
+ void saveToFile(const std::string &path) const;
/**
* Create cross dependencies for all applications in a package
static void updatePackageRules(const std::string &pkgName, const std::vector<std::string> &pkgContents);
+ /**
+ * This function will read all rules created by security-manager and
+ * save them in one file. This file will be used during next system
+ * boot.
+ */
+ static void mergeRules();
+
private:
static void useTemplate(
const std::string &templatePath,
LogDebug("Adding Smack rules for new appName: " << req.appName << " with pkgName: "
<< req.pkgName << ". Applications in package: " << pkgContents.size());
SmackRules::installApplicationRules(req.appName, req.pkgName, authorId, pkgContents, allTizen2XApps, allTizen2XPackages);
+ SmackRules::mergeRules();
} catch (const SmackException::InvalidParam &e) {
LogError("Invalid paramater during labeling: " << e.GetMessage());
return SECURITY_MANAGER_ERROR_INPUT_PARAM;
LogDebug("Removing Smack rules for authorId " << authorId);
SmackRules::uninstallAuthorRules(authorId);
}
+
+ SmackRules::mergeRules();
} catch (const SmackException::Base &e) {
LogError("Error while removing Smack rules for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Rafal Krypa <r.krypa@samsung.com>
*
#include <cstring>
#include <sstream>
#include <memory>
+#include <algorithm>
#include <dpl/log/log.h>
#include <tzplatform_config.h>
#include <dpl/errno_string.h>
+#include <dpl/fstream_accessors.h>
+#include <filesystem.h>
#include "smack-labels.h"
#include "smack-rules.h"
const char *const PKG_RULES_TEMPLATE_FILE_PATH = tzplatform_mkpath4(TZ_SYS_RO_SHARE, "security-manager", "policy", "pkg-rules-template.smack");
const char *const AUTHOR_RULES_TEMPLATE_FILE_PATH =
tzplatform_mkpath4(TZ_SYS_RO_SHARE, "security-manager", "policy", "author-rules-template.smack");
+const char *const SMACK_RULES_PATH_MERGED = LOCAL_STATE_DIR "/security-manager/rules-merged/rules.merged";
+const char *const SMACK_RULES_PATH_MERGED_T = LOCAL_STATE_DIR "/security-manager/rules-merged/rules.merged.temp";
+const char *const SMACK_RULES_PATH = LOCAL_STATE_DIR "/security-manager/rules";
const char *const SMACK_APP_IN_PACKAGE_PERMS = "rwxat";
const char *const SMACK_APP_CROSS_PKG_PERMS = "rx";
const char *const SMACK_APP_PATH_OWNER_PERMS = "rwxat";
const char *const SMACK_SYSTEM = "System";
const char *const SMACK_APP_PATH_SYSTEM_PERMS = "rwxat";
const char *const SMACK_APP_PATH_USER_PERMS = "rwxat";
+const std::string TEMPORARY_FILE_SUFFIX = ".temp";
SmackRules::SmackRules()
{
}
}
-void SmackRules::saveToFile(const std::string &path, bool truncFile) const
+void SmackRules::saveToFile(const std::string &destPath) const
{
int fd;
- int flags = O_CREAT | O_WRONLY | (truncFile ? O_TRUNC : O_APPEND);
+ int flags = O_CREAT | O_WRONLY | O_TRUNC;
+ std::string path = destPath + TEMPORARY_FILE_SUFFIX;
fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0644));
if (fd == -1) {
LogWarning("Error while closing the file: " << path << ", error: " << GetErrnoString(errno));
}
}
+
+ if (0 > rename(path.c_str(), destPath.c_str())) {
+ LogError("Error moving file " << path << " to " << destPath << ". Errno: " << GetErrnoString(errno));
+ unlink(path.c_str());
+ ThrowMsg(SmackException::FileError, "Error moving file " << path << " to " << destPath << ". Errno: " << GetErrnoString(errno));
+ }
}
void SmackRules::addFromTemplateFile(
std::string SmackRules::getPackageRulesFilePath(const std::string &pkgName)
{
- std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("pkg_" + pkgName).c_str()));
- return path;
+ return std::string(SMACK_RULES_PATH) + "/pkg_" + pkgName;
}
std::string SmackRules::getApplicationRulesFilePath(const std::string &appName)
{
- std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("app_" + appName).c_str()));
- return path;
+ return std::string(SMACK_RULES_PATH) + "/app_" + appName;
}
std::string SmackRules::getAuthorRulesFilePath(const int authorId)
{
- std::string authorIdStr = std::to_string(authorId);
- return tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("author_" + authorIdStr).c_str());
+ return std::string(SMACK_RULES_PATH) + "/author_" + std::to_string(authorId);
+}
+
+void SmackRules::mergeRules()
+{
+ int tmp;
+ FS::FileNameVector files = FS::getFilesFromDirectory(SMACK_RULES_PATH);
+
+ // remove ignore files with ".temp" suffix
+ files.erase(
+ std::remove_if(files.begin(), files.end(),
+ [&](const std::string &path) -> bool {
+ if (path.size() < TEMPORARY_FILE_SUFFIX.size())
+ return false;
+ return std::equal(
+ TEMPORARY_FILE_SUFFIX.rbegin(),
+ TEMPORARY_FILE_SUFFIX.rend(),
+ path.rbegin());
+ }),
+ files.end());
+
+ std::ofstream dst(SMACK_RULES_PATH_MERGED_T, std::ios::binary);
+
+ if (dst.fail()) {
+ LogError("Error creating file: " << SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError, "Error creating file: " << SMACK_RULES_PATH_MERGED_T);
+ }
+
+ for(auto const &e : files) {
+ std::ifstream src(std::string(SMACK_RULES_PATH) + "/" + e, std::ios::binary);
+ dst << src.rdbuf() << '\n';
+ if (dst.bad()) {
+ LogError("I/O Error. File " << SMACK_RULES_PATH_MERGED << " will not be updated!");
+ unlink(SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError,
+ "I/O Error. File " << SMACK_RULES_PATH_MERGED << " will not be updated!");
+ }
+
+ if (dst.fail()) {
+ // src.rdbuf() was empty
+ dst.clear();
+ }
+ }
+
+ if (dst.flush().fail()) {
+ LogError("Error flushing file: " << SMACK_RULES_PATH_MERGED_T);
+ unlink(SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError, "Error flushing file: " << SMACK_RULES_PATH_MERGED_T);
+ }
+
+ if (0 > fsync(DPL::FstreamAccessors<std::ofstream>::GetFd(dst))) {
+ LogError("Error fsync on file: " << SMACK_RULES_PATH_MERGED_T);
+ unlink(SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError, "Error fsync on file: " << SMACK_RULES_PATH_MERGED_T);
+ }
+
+ dst.close();
+ if (dst.fail()) {
+ LogError("Error closing file: " << SMACK_RULES_PATH_MERGED_T);
+ unlink(SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError, "Error closing file: " << SMACK_RULES_PATH_MERGED_T);
+ }
+
+ if ((tmp = rename(SMACK_RULES_PATH_MERGED_T, SMACK_RULES_PATH_MERGED)) == 0)
+ return;
+
+ int err = errno;
+
+ LogError("Error during file rename: "
+ << SMACK_RULES_PATH_MERGED_T << " to "
+ << SMACK_RULES_PATH_MERGED << " Errno: " << GetErrnoString(err));
+ unlink(SMACK_RULES_PATH_MERGED_T);
+ ThrowMsg(SmackException::FileError, "Error during file rename: "
+ << SMACK_RULES_PATH_MERGED_T << " to "
+ << SMACK_RULES_PATH_MERGED << " Errno: " << GetErrnoString(err));
}
void SmackRules::useTemplate(
const std::vector<std::string> &pkgContents,
const std::vector<std::string> &appsGranted)
{
- useTemplate(PKG_RULES_TEMPLATE_FILE_PATH, getPackageRulesFilePath(pkgName), std::string(), pkgName);
-
SmackRules smackRules;
- std::string pkgPath = getPackageRulesFilePath(pkgName);
+ smackRules.addFromTemplateFile(
+ PKG_RULES_TEMPLATE_FILE_PATH,
+ std::string(),
+ pkgName,
+ -1);
smackRules.generatePackageCrossDeps(pkgContents);
smackRules.generateAllowOther2XApplicationDeps(pkgName, appsGranted);
if (smack_smackfs_path() != NULL)
smackRules.apply();
- smackRules.saveToFile(pkgPath, false);
+ smackRules.saveToFile(getPackageRulesFilePath(pkgName));
}
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2016 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
+ *
+ * @file fstream-helper.h
+ * @author Marek Smolinski (m.smolinski@samsung.com)
+ * @version 1.0
+ * @brief This file is the implementation file of fstream-helper
+ *
+ */
+
+#ifndef _FSTREAM_ACCESSORS_H
+#define _FSTREAM_ACCESSORS_H
+
+namespace DPL {
+
+/*
+ * Bypass lack of public member function to get file
+ * descriptor from fstream objects in std
+ * This feature is needed for flushing data from kernel space buffer to
+ * physical device [fsync(int fd) - syscall] on opened fstream object
+*/
+
+template<typename T>
+class FstreamAccessors : T::__filebuf_type {
+ typedef FstreamAccessors<T> MyType;
+public:
+ static int GetFd(T &strm) {
+ return static_cast<MyType *>(strm.rdbuf())->_M_file.fd();
+ }
+};
+
+} // namespace DPL
+
+#endif // _FSTREAM_ACCESSORS_H
CONFIGURE_FILE(security-manager.service.in security-manager.service @ONLY)
CONFIGURE_FILE(security-manager-cleanup.service.in security-manager-cleanup.service @ONLY)
+CONFIGURE_FILE(security-manager-rules-loader.service.in security-manager-rules-loader.service @ONLY)
INSTALL(FILES
security-manager.service
security-manager.socket
security-manager-cleanup.service
+ security-manager-rules-loader.service
DESTINATION
${SYSTEMD_INSTALL_DIR}
)
--- /dev/null
+[Unit]
+Description=SMACK merged rules loading
+After=local-fs.target
+Before=basic.target
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=/bin/dd if=@LOCAL_STATE_DIR@/security-manager/rules-merged/rules.merged of=/sys/fs/smackfs/load2 bs=20M
+
+[Install]
+WantedBy=basic.target
+