* Split common and dac/smack specific code into separate files.
* Use common exceptions for Acl, Smack & Dac.
* Pass request uid to DacSetup::setupPkgBasePath and
DacSetup::setupPath.
Change-Id: If4e76a273e2bd11de6aad69d1f2c76a56a1c5bbd
* @brief This file contain client side implementation of security-manager API
*/
+#include "access-control-exception.h"
+#include "check-proper-drop.h"
+#include "client-offline.h"
+#include "client-request.h"
+#include "config.h"
+#include "config-file.h"
+#include "dpl/errno_string.h"
+#include "dpl/exception.h"
+#include "dpl/log/log.h"
+#include "filesystem.h"
+#include "group2gid.h"
+#include "mount-namespace.h"
+#include "protocols.h"
+#include "security-manager.h"
+#include "service_impl.h"
+#include "smack-check.h"
+#include "smack-labels.h"
+#include "tzplatform-config.h"
+#include "utils.h"
+
+#include <atomic>
#include <cstdio>
#include <cstdlib>
+#include <cxxabi.h>
#include <functional>
#include <memory>
-#include <utility>
-#include <atomic>
#include <system_error>
+#include <utility>
#include <vector>
-#include <stdlib.h>
-#include <cxxabi.h>
-#include <unistd.h>
-#include <grp.h>
#include <dirent.h>
#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
-#include <sys/smack.h>
+#include <grp.h>
#include <sys/capability.h>
-#include <sys/syscall.h>
#include <sys/mman.h>
+#include <sys/smack.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
#include <signal.h>
-
-#include <dpl/log/log.h>
-#include <dpl/exception.h>
-#include <smack-check.h>
-#include <smack-labels.h>
-#include <client-request.h>
-#include <service_impl.h>
-#include <check-proper-drop.h>
-#include <utils.h>
-#include <group2gid.h>
-#include <config.h>
-#include <config-file.h>
-#include <tzplatform-config.h>
-
-#include <security-manager.h>
-#include <client-offline.h>
-#include <dpl/errno_string.h>
-
-#include "filesystem.h"
-#include "mount-namespace.h"
-#include "protocols.h"
+#include <stdlib.h>
+#include <unistd.h>
static const char *EMPTY = "";
static const std::string SMACK_SYSTEM = "System";
try {
SmackLabels::generateAppPkgNameFromLabel(label, appNameString, pkgNameString);
- } catch (const SmackException::InvalidLabel &) {
+ } catch (const AccessControlException::InvalidLabel &) {
return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
}
${COMMON_PATH}/connection.cpp
${COMMON_PATH}/credentials.cpp
${COMMON_PATH}/cynara.cpp
+ ${COMMON_PATH}/dac-setup.cpp
${COMMON_PATH}/filesystem.cpp
${COMMON_PATH}/file-lock.cpp
${COMMON_PATH}/permissible-set.cpp
${COMMON_PATH}/protocols.cpp
${COMMON_PATH}/nsmount-logic.cpp
+ ${COMMON_PATH}/path-setup.cpp
${COMMON_PATH}/privilege_db.cpp
${COMMON_PATH}/smack-labels.cpp
${COMMON_PATH}/smack-accesses.cpp
${COMMON_PATH}/smack-common.cpp
${COMMON_PATH}/smack-rules.cpp
${COMMON_PATH}/smack-check.cpp
+ ${COMMON_PATH}/smack-setup.cpp
${COMMON_PATH}/template-manager.cpp
${COMMON_PATH}/service_impl.cpp
${COMMON_PATH}/service_impl_utils.cpp
*/
#include "acl.h"
+
+#include "access-control-exception.h"
#include "dpl/errno_string.h"
-#include "dpl/exception.h"
-#include <acl/libacl.h>
+#include "dpl/log/log.h"
+
#include <memory>
-#include <sys/acl.h>
-#include <vector>
namespace SecurityManager {
acl_permset_t permset = nullptr;
if (0 != acl_get_permset(m_rawEntry, &permset)) {
- LogAndThrowErrno(Exception::Base, "acl_get_permset");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_permset");
}
if (0 != acl_clear_perms(permset)) {
- LogAndThrowErrno(Exception::Base, "acl_clear_permset");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_clear_permset");
}
if (0 != acl_add_perm(permset, m_permissions)) {
- LogAndThrowErrno(Exception::Base, "acl_add_perm");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_add_perm");
}
if (0 != acl_set_tag_type(m_rawEntry, m_tag)) {
- LogAndThrowErrno(Exception::Base, "acl_set_tag_type");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_set_tag_type");
}
void *qualifier = nullptr;
if (qualifier != nullptr) {
if (0 != acl_set_qualifier(m_rawEntry, qualifier)) {
- LogAndThrowErrno(Exception::Base, "acl_set_qualifier");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_set_qualifier");
}
}
}
Acl::Entry Acl::Entry::FromRawEntry(acl_entry_t entry) {
acl_tag_t tag_type;
if (0 != acl_get_tag_type(entry, &tag_type)) {
- LogAndThrowErrno(Exception::Base, "acl_get_tag_type");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_tag_type");
}
acl_permset_t permset;
if (0 != acl_get_permset(entry, &permset)) {
- LogAndThrowErrno(Exception::Base, "acl_get_permset");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_permset");
}
acl_perm_t perms = 0;
} else if (ret == 1) {
perms |= perm;
} else {
- LogAndThrowErrno(Exception::Base, "acl_get_perm");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_perm");
}
}
switch (tag_type) {
case ACL_USER: {
if (!acl_qualifier) {
- LogAndThrowErrno(Exception::Base, "acl_get_qualifier");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_qualifier");
}
uid_t uid = *(static_cast<uid_t*>(acl_qualifier.get()));
auto uidEntry = UidEntry(perms, uid);
}
case ACL_GROUP: {
if (!acl_qualifier) {
- LogAndThrowErrno(Exception::Base, "acl_get_qualifier");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_qualifier");
}
gid_t gid = *(static_cast<gid_t*>(acl_qualifier.get()));
auto gid_entry = GidEntry(perms, gid);
}
default: {
if (acl_qualifier) {
- ThrowMsg(Exception::Base, "Unexpected acl_qualifier for tag type " << tag_type);
+ ThrowMsg(AccessControlException::AclError,
+ "Unexpected acl_qualifier for tag type " << tag_type);
}
}
}
Acl Acl::FromFile(const std::string &path, acl_type_t acl_type) {
acl_t acl = acl_get_file(path.c_str(), acl_type);
if (acl == nullptr) {
- LogAndThrowErrno(Exception::Base, "acl_get_file");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_file");
}
return Acl(acl);
int entries_count = acl_entries(m_acl);
if (entries_count < 0) {
- LogAndThrowErrno(Exception::Base, "acl_entries");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_entries");
}
entries.reserve(entries_count);
}
if (ret == -1) {
- LogAndThrowErrno(Exception::Base, "acl_get_entry");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_get_entry");
}
return entries;
if (!entry.isRawEntryAssigned()) {
acl_entry_t new_entry = nullptr;
if (0 != acl_create_entry(&m_acl, &new_entry)) {
- LogAndThrowErrno(Exception::Base, "acl_create_entry");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_create_entry");
}
entry.assignRawEntry(new_entry);
}
void Acl::deleteEntry(Entry&& entry) {
if (0 != acl_delete_entry(m_acl, entry.getAssignedRawEntry())) {
- LogAndThrowErrno(Exception::Base, "acl_delete_entry");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_delete_entry");
}
}
auto freeAcl = [](acl_t *toFree) {acl_free(*toFree);};
m_acl = acl_init(entries.size() + 1); // + 1 for ACL_MASK entry
if (m_acl == nullptr) {
- LogAndThrowErrno(Exception::Base, "acl_init");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_init");
}
std::unique_ptr<acl_t, decltype(freeAcl)> deleter(&m_acl, freeAcl);
// Acl requires one ACL_MASK entry if there are ACL_USER or ACL_GROUP entries present.
if (0 != acl_calc_mask(&m_acl)) {
- LogAndThrowErrno(Exception::Base, "acl_calc_mask");
+ LogAndThrowErrno(AccessControlException::AclError, "acl_calc_mask");
}
- LogWarning("created acl: " << toString());
int last;
int ret = acl_check(m_acl, &last);
if (ret != 0) {
} else {
LogErrno("acl_check");
}
- Throw(Exception::Base);
+ Throw(AccessControlException::AclError);
}
(void)deleter.release();
{
if (m_acl == nullptr) {
LogError("ACL object is not initialized");
- Throw(Exception::Base);
+ Throw(AccessControlException::Base);
}
if (0 != acl_set_file(path.c_str(), type, m_acl)) {
- LogErrno("acl_set_file for " << path);
- Throw(Exception::Base);
+ LogAndThrowErrno(AccessControlException::FileError, "acl_set_file for " << path);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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 "dac-setup.h"
+
+#include "access-control-exception.h"
+#include "dpl/errno_string.h"
+#include "service_impl_utils.h"
+#include "utils.h"
+
+#include <filesystem>
+#include <variant>
+
+#include <fcntl.h>
+#include <fts.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+namespace SecurityManager {
+
+void DacSetup::setupPkgBasePath(uid_t owner,
+ const std::string &basePath,
+ const std::vector<uid_t> &processUIds)
+{
+ // apply public RO access permissions
+ if (0 != chown(basePath.c_str(), owner, getSystemAccessGid()))
+ ThrowErrno(AccessControlException::FileError, "chown() for path: " << basePath);
+
+ std::vector<Acl::Entry> entries;
+ for (auto &processUId : processUIds)
+ entries.emplace_back(Acl::UidEntry(Acl::RX, processUId));
+
+ auto acl = Acl::Make(Acl::RWX, Acl::RWX, Acl::RX, std::move(entries));
+ acl.apply(basePath, ACL_TYPE_ACCESS);
+}
+
+bool DacSetup::isAppPrivatePath(uid_t appUid, const std::string &path) {
+ static constexpr auto dir_acl_types = {ACL_TYPE_ACCESS, ACL_TYPE_DEFAULT};
+ static constexpr auto file_acl_types = {ACL_TYPE_ACCESS};
+ const auto &acl_types = std::filesystem::is_directory(path) ? dir_acl_types : file_acl_types;
+ bool has_owner_rights = false;
+ bool has_other_rights = false;
+ for (auto acl_type : acl_types) {
+ auto acl = Acl::FromFile(path, acl_type);
+ LogDebug("acl from " << path << ":\n" << acl.toString());
+ for (const auto &entry : acl.toEntries()) {
+ auto qualifier = entry.getQualifier();
+ if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
+ if (appUid == uidQualifier->uid
+ && (entry.getPermissions() & Acl::RW) == Acl::RW)
+ {
+ has_owner_rights = true;
+ }
+ } else if (entry.getTag() == ACL_OTHER && (entry.getPermissions() != 0)) {
+ has_other_rights = true;
+ }
+ }
+ }
+ return has_owner_rights && !has_other_rights;
+}
+
+void DacSetup::addPrivateSharing(uid_t targetAppUid, const std::string &path) {
+ LogDebug("add private sharing called for target=" << targetAppUid
+ <<" path=" << path);
+ acl_perm_t perms = std::filesystem::is_directory(path) ? Acl::X : Acl::RX;
+ auto acl = Acl::FromFile(path, ACL_TYPE_ACCESS);
+ LogDebug("acl for " << path << " before add:\n " << acl.toString());
+ bool entry_exists = false;
+ for (auto &entry: acl.toEntries()) {
+ auto qualifier = entry.getQualifier();
+ if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
+ if (targetAppUid == uidQualifier->uid) {
+ entry_exists = true;
+ break;
+ }
+ }
+ }
+ if (!entry_exists) {
+ acl.addEntry(Acl::UidEntry(perms, targetAppUid));
+ }
+ LogDebug("acl for " << path << " after add:\n " << acl.toString());
+ acl.apply(path, ACL_TYPE_ACCESS);
+}
+
+void DacSetup::removePrivateSharing(uid_t targetAppUid, const std::string &path) {
+ LogDebug("remove private sharing called for target=" << targetAppUid
+ <<" path=" << path);
+ auto acl = Acl::FromFile(path, ACL_TYPE_ACCESS);
+ LogDebug("acl for " << path << " before remove:\n " << acl.toString());
+ for (auto &entry: acl.toEntries()) {
+ auto qualifier = entry.getQualifier();
+ if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
+ if (targetAppUid == uidQualifier->uid) {
+ acl.deleteEntry(std::move(entry));
+ // No other entry for this app should be on the list
+ break;
+ }
+ }
+ }
+ LogDebug("acl for " << path << " after remove:\n " << acl.toString());
+ acl.apply(path, ACL_TYPE_ACCESS);
+}
+
+void DacSetup::setupPath(uid_t owner,
+ const std::string &path,
+ app_install_path_type pathType,
+ const std::vector<uid_t> &processUIds,
+ std::optional<gid_t> authorGId)
+{
+ Dac dac;
+ // Make the real user (owner=5001) the owner. No app should run with this uid
+ dac.owner = owner;
+ // Make system_access the group. No app should run with it.
+ dac.group = getSystemAccessGid();
+
+ acl_perm_t appPerms;
+ acl_perm_t otherPerms;
+ bool follow_symlink;
+ std::vector<Acl::Entry> entries;
+
+ switch (pathType) {
+ case SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO:
+ appPerms = Acl::RWX;
+ otherPerms = Acl::RX;
+ follow_symlink = true;
+ break;
+
+ case SECURITY_MANAGER_PATH_RW:
+ appPerms = Acl::RWX;
+ otherPerms = 0;
+ follow_symlink = false;
+ break;
+
+ case SECURITY_MANAGER_PATH_RO:
+ appPerms = Acl::RX;
+ otherPerms = 0;
+ follow_symlink = false;
+ break;
+
+ case SECURITY_MANAGER_PATH_PUBLIC_RO:
+ appPerms = Acl::RX;
+ otherPerms = Acl::RX;
+ follow_symlink = false;
+ break;
+
+ case SECURITY_MANAGER_PATH_TRUSTED_RW:
+ if (!authorGId.has_value())
+ ThrowMsg(AccessControlException::InvalidParam,
+ "You must define author to use PATH_TRUSED_RW");
+
+ appPerms = 0;
+ otherPerms = 0;
+ follow_symlink = false;
+ entries.emplace_back(Acl::GidEntry(Acl::RWX, *authorGId));
+ break;
+
+ default:
+ LogError("Path type not known.");
+ Throw(AccessControlException::InvalidParam);
+ }
+
+ if (appPerms != 0) {
+ for (auto &processUId : processUIds)
+ entries.emplace_back(Acl::UidEntry(appPerms, processUId));
+ }
+
+ // RWX for the owner(5001) and system_access
+ dac.acl = Acl::Make(Acl::RWX, Acl::RWX, otherPerms, std::move(entries));
+
+ DacSetup dacSetup(std::move(dac));
+ if (follow_symlink)
+ dacSetup.setup(realPath(path));
+ dacSetup.setup(path);
+}
+
+void DacSetup::setupFile(FTSENT *ftsent) const
+{
+ if (0 != chown(ftsent->fts_path, m_dac.owner, m_dac.group))
+ ThrowErrno(AccessControlException::FileError, "chown() for path: " << ftsent->fts_path);
+
+ m_dac.acl.apply(ftsent->fts_path, ACL_TYPE_ACCESS);
+
+ /*
+ * For newly created files:
+ * - let the owner come from process (be it app PUId or system_access). The creator clearly
+ * already has RWX.
+ * - force the group = system_access using DAC set-group-ID bit so even files created by
+ * app will be accessible by sys daemons. SM needs CAP_FSETID and system_access group for
+ * that.
+ * - Default ACL rules will be applied from the parent directory.
+ */
+ if (m_transmute && ftsent->fts_level == 0 && S_ISDIR(ftsent->fts_statp->st_mode)) {
+ // need to re-read the mode after ACL application above
+ struct stat statbuf;
+ if (0 != stat(ftsent->fts_path, &statbuf))
+ ThrowErrno(AccessControlException::FileError, "stat() for path: " << ftsent->fts_path);
+
+ // add set-group-ID for system_access
+ if (0 != chmod(ftsent->fts_path, S_ISGID | statbuf.st_mode))
+ ThrowErrno(AccessControlException::FileError, "chmod() for path: " << ftsent->fts_path);
+
+ // this works on all files/directories below
+ m_dac.acl.apply(ftsent->fts_path, ACL_TYPE_DEFAULT);
+ }
+}
+
+} // namespace SecurityManager
* @brief Wrappers for filesystem operations.
*
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <fcntl.h>
+
+#include "dpl/errno_string.h"
+#include "dpl/exception.h"
+#include "filesystem.h"
+#include "filesystem-exception.h"
+#include "security-manager.h"
+#include "utils.h"
#include <fstream>
#include <memory>
#include <string>
-#include <sstream>
-#include <dpl/log/log.h>
-#include <dpl/exception.h>
-#include <dpl/errno_string.h>
-#include <smack-exceptions.h>
-
-#include <filesystem.h>
-#include <filesystem-exception.h>
-#include <utils.h>
-#include <security-manager.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
namespace SecurityManager {
namespace FS {
--- /dev/null
+/*
+ * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+#pragma once
+
+#include "dpl/exception.h"
+
+namespace SecurityManager {
+
+class AccessControlException {
+public:
+ DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
+ DECLARE_EXCEPTION_TYPE(Base, LibsmackError)
+ DECLARE_EXCEPTION_TYPE(Base, FileError)
+ DECLARE_EXCEPTION_TYPE(Base, InvalidLabel)
+ DECLARE_EXCEPTION_TYPE(Base, InvalidParam)
+ DECLARE_EXCEPTION_TYPE(Base, AclError)
+};
+
+} // namespace SecurityManager
#pragma once
#include <acl/libacl.h>
-#include <sys/acl.h>
-#include <vector>
-#include <memory>
-#include <variant>
-#include "dpl/exception.h"
-#include "dpl/log/log.h"
-#include "dpl/errno_string.h"
+#include <string>
+#include <variant>
+#include <vector>
namespace SecurityManager {
other.m_tag = ACL_UNDEFINED_TAG;
other.m_permissions = 0;
other.m_qualifier = NoQualifier{};
-
}
Entry& operator=(const Entry&) = delete;
static constexpr inline acl_perm_t RX = ACL_READ | ACL_EXECUTE;
static constexpr inline acl_perm_t RWX = ACL_READ | ACL_WRITE | ACL_EXECUTE;
- class Exception
- {
- public:
- DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
- };
-
Acl() : Acl(std::vector<Entry>())
{
}
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "path-setup.h"
+
+#include "acl.h"
+#include "security-manager-types.h"
+
+#include <optional>
+#include <utility>
+#include <vector>
+
+#include <sys/types.h>
+
+namespace SecurityManager {
+
+class DacSetup : public PathSetup {
+public:
+ static void setupPkgBasePath(uid_t owner,
+ const std::string &basePath,
+ const std::vector<uid_t> &processUIds);
+
+ static bool isAppPrivatePath(uid_t appUid, const std::string &path);
+ static void addPrivateSharing(uid_t targetAppUid, const std::string &path);
+ static void removePrivateSharing(uid_t targetAppUid, const std::string &path);
+
+ static void setupPath(uid_t owner,
+ const std::string &path,
+ app_install_path_type pathType,
+ const std::vector<uid_t> &processUIds,
+ std::optional<gid_t> authorGId);
+private:
+ struct Dac {
+ // ACL for files and dirs. Effective permissions will be "ANDed" with ACL mask so
+ // non-executable files won't get 'x'
+ Acl acl;
+ uid_t owner;
+ gid_t group;
+ };
+
+ explicit DacSetup(Dac dac) : PathSetup(true), m_dac(std::move(dac)) {}
+
+ void setupFile(FTSENT *ftsent) const override;
+
+ Dac m_dac;
+};
+
+} // namespace SecurityManager
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <fts.h>
+
+namespace SecurityManager {
+
+class PathSetup {
+public:
+ explicit PathSetup(bool transmute) : m_transmute(transmute) {}
+ void setup(const std::string &path) const;
+ virtual ~PathSetup() = default;
+
+protected:
+ virtual void setupFile(FTSENT *ftsent) const = 0;
+
+ bool m_transmute;
+};
+
+} // namespace SecurityManager
const uid_t &uid,
app_install_type installationType);
- int labelPaths(const Credentials &creds,
- const path_req &req,
+ int labelPaths(const path_req &req,
bool isSharedRO,
const std::vector<uid_t> &processUids);
+++ /dev/null
-/*
- * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * This file is licensed under the terms of MIT License or the Apache License
- * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
- * See the LICENSE file or the notice below for Apache License Version 2.0
- * details.
- *
- * 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-exceptions.h
- * @author Rafal Krypa <r.krypa@samsung.com>
- * @version 1.0
- * @brief Declaration of Smack-specific exceptions
- *
- */
-#pragma once
-
-#include <dpl/exception.h>
-
-namespace SecurityManager {
-
-class SmackException {
-public:
- DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
- DECLARE_EXCEPTION_TYPE(Base, LibsmackError)
- DECLARE_EXCEPTION_TYPE(Base, FileError)
- DECLARE_EXCEPTION_TYPE(Base, InvalidLabel)
- DECLARE_EXCEPTION_TYPE(Base, InvalidPathType)
- DECLARE_EXCEPTION_TYPE(Base, InvalidParam)
-};
-
-} // namespace SecurityManager
*/
#pragma once
+#include "smack-common.h"
+
#include <string>
-#include <sys/acl.h>
-#include <utility>
-#include <optional>
-#include <smack-common.h>
-#include <smack-exceptions.h>
-#include <security-manager.h>
-#include "credentials.h"
namespace SecurityManager {
namespace SmackLabels {
-/**
- * Sets Smack labels on a directory and its contents, recursively.
- *
- * @param pkgName[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
- * @param authorHash[in] hash of author_name of given application
- * (if not applicable, set to empty string)
- */
-void setupPath(
- const std::string &pkgName,
- const std::string &path,
- app_install_path_type pathType,
- const std::string &authorHash = std::string());
-
-/**
- * Sets ACL and DAC permissions on a directory and its contents, recursively.
- *
- * @param owner[in] app owner uid
- * @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
- * @param processUIds[in] list of owner applications' process UIds (PUIDs)
- * @param authorGId[in] optional group id of all apps having the same author
- */
-void setupPath(
- uid_t owner,
- const std::string &path,
- app_install_path_type pathType,
- const std::vector<uid_t>& processUIds,
- const std::optional<gid_t>& authorGId);
-
-/**
- * Sets Smack labels on a <ROOT_APP>/<pkg_id> non-recursively
- *
- * @param basePath[in] <ROOT_APP>/<pkg_id> path
- */
-void setupPkgBasePath(const std::string &basePath);
-
-/**
- * Sets ACL and DAC permissions on <ROOT_APP>/<pkg_id> non-recursively
- *
- * @param creds[in] client's credentials
- * @param basePath[in] <ROOT_APP>/<pkg_id> path
- * @param processUIds[in] list of owner applications' process UIds (PUIDs)
- */
-void setupPkgBasePath(
- const Credentials &creds,
- const std::string &basePath,
- const std::vector<uid_t> &processUIds);
-
-/**
- * Changes Smack label on path to enable private sharing
- *
- * @param pkgName[in] package identifier
- * @param path[in] path
- */
-void setupSharedPrivatePath(const std::string &pkgName,
- const std::string &path);
-
-/**
- * Checks if application has RWX access to path and others do not have any access
- *
- * @param appUid[in] application uid
- * @param path[in] path
- */
-bool isAppPrivatePath(uid_t appUid, const std::string &path);
-
-/**
- * Adds ACL rules required for target application to access path.
- *
- * @param targetAppUid[in] target application uid
- * @param path[in] path
- */
-void addPrivateSharing(uid_t targetAppUid, const std::string &path);
-
-/**
- * Removes ACL rules required for target application to access path.
- *
- * @param targetAppUid[in] target application uid
- * @param path[in] path
- */
-void removePrivateSharing(uid_t targetAppUid, const std::string &path);
+// Smack label used for SECURITY_MANAGER_PATH_PUBLIC_RO paths (RO for all apps)
+inline constexpr char LABEL_FOR_APP_PUBLIC_RO_PATH[] = "User::Home";
/**
* Generates application name for a label fetched from Cynara
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "path-setup.h"
+#include "security-manager-types.h"
+
+#include <utility>
+
+namespace SecurityManager {
+
+class SmackSetup : public PathSetup {
+public:
+ static void setupPkgBasePath(const std::string &basePath);
+ static void setupSharedPrivatePath(const std::string &pkgName, const std::string &path);
+ static void setupPath(
+ const std::string &pkgName,
+ const std::string &path,
+ app_install_path_type pathType,
+ const std::string &authorHash = std::string());
+private:
+ SmackSetup(const std::string label, bool transmute) :
+ PathSetup(transmute), m_label(std::move(label))
+ {
+ }
+
+ void setupFile(FTSENT *ftsent) const override;
+
+ std::string m_label;
+};
+
+} // namespace SecurityManager
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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 "path-setup.h"
+
+#include "access-control-exception.h"
+#include "dpl/errno_string.h"
+#include "utils.h"
+
+namespace SecurityManager {
+
+void PathSetup::setup(const std::string &path) const
+{
+ // setting access label on everything in given directory and below
+ char *const path_argv[] = { const_cast<char*>(path.c_str()), nullptr };
+ FTSENT *entry;
+
+ auto fts = makeUnique(fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, nullptr), fts_close);
+ if (!fts) {
+ LogAndThrowErrno(AccessControlException::FileError, "fts_open failed.");
+ }
+
+ while ((entry = fts_read(fts.get())) != nullptr) {
+ if (entry->fts_info == FTS_ERR || entry->fts_info == FTS_NS || entry->fts_info == FTS_DNR) {
+ LogAndThrowErrno(AccessControlException::FileError, "fts_read");
+ }
+
+ /* avoid to tag directories two times */
+ if (entry->fts_info == FTS_D)
+ continue;
+
+ setupFile(entry);
+ }
+
+ /* If last call to fts_read() set errno, we need to return error. */
+ if (errno != 0)
+ LogAndThrowErrno(AccessControlException::FileError, "last fts_read");
+}
+
+} // namespace SecurityManager
* @version 1.0
*/
-#include "privilege-info.h" // header for this file
+#include "privilege-info.h"
-#include <dpl/log/log.h>
-#include <smack-labels.h>
+#include "access-control-exception.h"
+#include "dpl/log/log.h"
+#include "smack-labels.h"
namespace SecurityManager {
try {
SmackLabels::generateAppPkgNameFromLabel(label, m_appId, m_pkgId);
- } catch(const SmackException::InvalidLabel&) {
+ } catch(const AccessControlException::InvalidLabel&) {
LogDebug("Not an application label " << label);
ThrowMsg(Exception::NotApplication, "Not an application label");
}
* @brief Implementation of the service methods
*/
-#include <cassert>
-#include <fcntl.h>
-#include <linux/xattr.h>
-#include <limits.h>
-#include <pwd.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <cstring>
-#include <algorithm>
-#include <sys/types.h>
-#include <grp.h>
-#include <optional>
-#include <sys/smack.h>
-#include <unistd.h>
-#include <stdexcept>
-#include <string_view>
-#include <unordered_set>
-
-#include <dpl/log/log.h>
-#include <dpl/errno_string.h>
+#include "service_impl.h"
-#include <config.h>
-#include <vector>
-#include "acl.h"
+#include "access-control-exception.h"
#include "check-proper-drop.h"
-#include "protocols.h"
-#include "privilege_db.h"
+#include "config.h"
#include "cynara.h"
+#include "dac-setup.h"
+#include "dpl/errno_string.h"
+#include "dpl/log/log.h"
+#include "filesystem.h"
+#include "mount-namespace.h"
#include "permissible-set.h"
+#include "privilege_db.h"
+#include "privilege-info.h"
+#include "protocols.h"
+#include "service_impl_utils.h"
#include "smack-check.h"
-#include "smack-exceptions.h"
-#include "smack-rules.h"
#include "smack-labels.h"
-#include "security-manager.h"
+#include "smack-rules.h"
+#include "smack-setup.h"
#include "tzplatform-config.h"
#include "utils.h"
-#include "filesystem.h"
-#include "mount-namespace.h"
-#include "privilege-info.h"
-#include "service_impl_utils.h"
-#include "service_impl.h"
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <optional>
+#include <stdexcept>
+#include <string>
+#include <string_view>
+#include <unordered_set>
+#include <vector>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <linux/xattr.h>
+#include <pwd.h>
+#include <sys/mman.h>
+#include <sys/smack.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
namespace SecurityManager {
const auto sharedPath = baseDir + ".shared/" + pkgName;
const auto sharedTmpPath = baseDir + ".shared_tmp/" + pkgName;
if (FS::directoryStatus(sharedPath) > 0 && FS::directoryStatus(sharedTmpPath) > 0) {
- SmackLabels::setupPkgBasePath(sharedPath);
- SmackLabels::setupPkgBasePath(sharedTmpPath);
+ SmackSetup::setupPkgBasePath(sharedPath);
+ SmackSetup::setupPkgBasePath(sharedTmpPath);
}
}
return true;
}
-int ServiceImpl::labelPaths(const Credentials &creds,
- const path_req &req,
+int ServiceImpl::labelPaths(const path_req &req,
bool isSharedRO,
const std::vector<uid_t> &processUIds)
{
const std::string &path = pkgPath.first;
app_install_path_type pathType = static_cast<app_install_path_type>(pkgPath.second);
if (smack_simple_check()) {
- SmackLabels::setupPath(req.pkgName, path, pathType, authorHash);
+ SmackSetup::setupPath(req.pkgName, path, pathType, authorHash);
} else {
gid_t authorGId;
if (m_privilegeDb.GetAuthorGId(req.pkgName, authorGId))
- SmackLabels::setupPath(req.uid, path, pathType, processUIds, authorGId);
+ DacSetup::setupPath(req.uid, path, pathType, processUIds, authorGId);
else
- SmackLabels::setupPath(req.uid, path, pathType, processUIds, std::nullopt);
+ DacSetup::setupPath(req.uid, path, pathType, processUIds, std::nullopt);
}
}
for (const auto &basePath : pkgLegalBaseDirs) {
if (containSubDir(basePath, req.pkgPaths)) {
if (smack_simple_check())
- SmackLabels::setupPkgBasePath(basePath);
+ SmackSetup::setupPkgBasePath(basePath);
else
- SmackLabels::setupPkgBasePath(creds, basePath, processUIds);
+ DacSetup::setupPkgBasePath(req.uid, basePath, processUIds);
}
}
} catch (const PrivilegeDb::Exception::Base &e) {
LogError("Database error: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidParam &e) {
- LogError("Invalid parameter during labeling: " << e.DumpToString());
- return SECURITY_MANAGER_ERROR_INPUT_PARAM;
- } catch (const SmackException::InvalidPathType &e) {
- LogError("Invalid path type: " << e.DumpToString());
- return SECURITY_MANAGER_ERROR_INPUT_PARAM;
} catch (const TizenPlatformConfig::Exception::Base &e) {
LogError("Error while reading configuration: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::Base &e) {
- LogError("Error while generating Smack labels: " << e.DumpToString());
- return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
- } catch (const Acl::Exception::Base &e) {
- LogError("Error while setting up ACL");
+ } catch (const AccessControlException::InvalidParam &e) {
+ LogError("Invalid parameter during access control setup: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+ } catch (const AccessControlException::Base &e) {
+ LogError("Error during access control setup: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
} catch (const std::runtime_error &) {
return SECURITY_MANAGER_ERROR_UNKNOWN;
if (!req.isHybrid) // is not hybrid - all labels are the same
break;
}
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidParam &e) {
+ } catch (const AccessControlException::InvalidParam &e) {
LogError("Invalid paramater during labeling: " << e.GetMessage());
return SECURITY_MANAGER_ERROR_INPUT_PARAM;
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error while applying Smack policy for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
} catch (const SecurityManager::Exception &e) {
// label paths
LogWarning("Configuring package paths");
- ret = labelPaths(creds, req, isAppSharedRO, processUids);
+ ret = labelPaths(req, isAppSharedRO, processUids);
if (ret != SECURITY_MANAGER_SUCCESS)
return ret;
// label paths
LogWarning("Configuring package paths");
- ret = labelPaths(creds, req, isAppSharedRO, processUids);
+ ret = labelPaths(req, isAppSharedRO, processUids);
if (ret != SECURITY_MANAGER_SUCCESS)
return ret;
LogDebug("Removing Smack rules for author " << uh.authorHash);
m_smackRules.uninstallAuthorRules(uh.authorHash);
}
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error while removing Smack rules for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
} catch (const TizenPlatformConfig::Exception::Base &e) {
} catch (const CynaraException::Base &e) {
LogError("Error while setting Cynara rules for application: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const TizenPlatformConfig::Exception::Base &e) {
} catch (const PermissibleSet::PermissibleSetException::FileInitError &e) {
LogError("Error while adding user: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
- } catch (const SmackException::FileError &e) {
+ } catch (const AccessControlException::FileError &e) {
LogError("Error while adding user: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SETTING_FILE_LABEL_FAILED;
} catch (const PrivilegeInfo::Exception::Base &e) {
}
try {
updateRunningAppSmackPolicy(appContext, appsAllowedPrivileges);
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("AppContext: " << appContext.appProcessLabel
<< " doesn't describe an application");
}
} catch (const CynaraException::Base &e) {
LogError("Error while listing Cynara rules: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
} catch (const CynaraException::Base &e) {
LogError("Error while listing Cynara rules: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
} catch (const CynaraException::Base &e) {
LogError("Error while querying Cynara for permissions: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
//This function can be also called when application is uninstalled, so path won't exist
if (FS::fileExists(path)) {
if (smack_simple_check() && pathCount < 1) {
- SmackLabels::setupPath(ownerPkgName, path, SECURITY_MANAGER_PATH_RW);
+ SmackSetup::setupPath(ownerPkgName, path, SECURITY_MANAGER_PATH_RW);
} else if (!smack_simple_check()) {
std::string target_puid, owner_puid, unused_agid;
m_privilegeDb.GetAppPuidAndAgid(targetAppName, target_puid, unused_agid);
auto parentDirs = getUniqueParentDirs(otherSharedPaths);
auto currentPath = path;
do {
- SmackLabels::removePrivateSharing(target_uid, currentPath);
+ DacSetup::removePrivateSharing(target_uid, currentPath);
auto parentDir = FS::getParentDirectoryName(currentPath);
if (parentDirs.count(parentDir) == 1) {
break;
}
currentPath = parentDir;
- } while (!currentPath.empty() && SmackLabels::isAppPrivatePath(owner_uid, currentPath));
+ } while (!currentPath.empty() && DacSetup::isAppPrivatePath(owner_uid, currentPath));
}
}
}
} catch (const PrivilegeDb::Exception::Base &e) {
LogError("Error while dropping private sharing in database: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error performing smack operation: " << e.GetMessage());
errorRet = SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
}
}
} else {
- if (!SmackLabels::isAppPrivatePath(owner_uid, path)) {
+ if (!DacSetup::isAppPrivatePath(owner_uid, path)) {
LogError("Path " << path << " does not belong to application " << ownerAppName);
return SECURITY_MANAGER_ERROR_APP_NOT_PATH_OWNER;
}
(pathCount > 0),
(ownerTargetCount > 0));
if (pathCount <= 0) {
- SmackLabels::setupSharedPrivatePath(ownerPkgName, path);
+ SmackSetup::setupSharedPrivatePath(ownerPkgName, path);
}
} else {
// ACLs for parent directories
auto currentPath = path;
do {
- SmackLabels::addPrivateSharing(target_uid, currentPath);
+ DacSetup::addPrivateSharing(target_uid, currentPath);
currentPath = FS::getParentDirectoryName(currentPath);
- } while (!currentPath.empty() && SmackLabels::isAppPrivatePath(owner_uid, currentPath));
+ } while (!currentPath.empty() && DacSetup::isAppPrivatePath(owner_uid, currentPath));
}
}
trans.commit();
} catch (const PrivilegeDb::Exception::Base &e) {
LogError("Error while applying private sharing in database: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error performing smack operation: " << e.GetMessage());
errorRet = SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
} catch (const PrivilegeDb::Exception::Base &e) {
LogError("Error while dropping private sharing in database: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error performing smack operation: " << e.GetMessage());
errorRet = SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
}
- return labelPaths(creds, req, isRequestSharedRO, processUids);
+ return labelPaths(req, isRequestSharedRO, processUids);
}
int ServiceImpl::shmAppName(const Credentials &creds, const std::string &shmName, const std::string &appName)
} catch (const CynaraException::Base &e) {
LogError("Error while querying Cynara for permissions: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::Base &e) {
+ } catch (const AccessControlException::Base &e) {
LogError("Error while set/get smack label in /dev/shm: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const TizenPlatformConfig::Exception::Base &e) {
} catch (const CynaraException::Base &e) {
LogError("Error while querying Cynara for permissions: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
- } catch (const SmackException::InvalidLabel &e) {
+ } catch (const AccessControlException::InvalidLabel &e) {
LogError("Error while generating Smack labels: " << e.DumpToString());
return SECURITY_MANAGER_ERROR_SERVER_ERROR;
} catch (const std::bad_alloc &e) {
*
*/
-#include <sys/smack.h>
+#include "smack-accesses.h"
-#include <dpl/log/log.h>
-#include <smack-exceptions.h>
+#include "access-control-exception.h"
+#include "dpl/log/log.h"
-#include "smack-accesses.h"
+#include <sys/smack.h>
namespace SecurityManager {
const Smack::Permission &permissions)
{
if (smack_accesses_add(m_handle, subject.c_str(), object.c_str(), permissions.c_str()))
- ThrowMsg(SmackException::LibsmackError, "smack_accesses_add");
+ ThrowMsg(AccessControlException::LibsmackError, "smack_accesses_add");
}
void SmackAccesses::add(const Smack::Rule &rule)
const Smack::Permission &allowPermissions, const Smack::Permission &denyPermissions)
{
if (smack_accesses_add_modify(m_handle, subject.c_str(), object.c_str(), allowPermissions.c_str(), denyPermissions.c_str()))
- ThrowMsg(SmackException::LibsmackError, "smack_accesses_add_modify");
+ ThrowMsg(AccessControlException::LibsmackError, "smack_accesses_add_modify");
}
void SmackAccesses::clear() const
{
if (smack_accesses_clear(m_handle))
- ThrowMsg(SmackException::LibsmackError, "smack_accesses_clear");
+ ThrowMsg(AccessControlException::LibsmackError, "smack_accesses_clear");
}
void SmackAccesses::apply() const
{
if (smack_accesses_apply(m_handle))
- ThrowMsg(SmackException::LibsmackError, "smack_accesses_apply");
+ ThrowMsg(AccessControlException::LibsmackError, "smack_accesses_apply");
}
* @brief Source file of a smack utility types and functions
*
*/
+
+#include "smack-common.h"
+
+#include "access-control-exception.h"
+#include "config-file.h"
+#include "dpl/log/log.h"
+
#include <cassert>
-#include <config-file.h>
-#include <smack-exceptions.h>
-#include <dpl/log/log.h>
#include <sys/smack.h>
-#include "smack-common.h"
-
namespace SecurityManager {
namespace Smack {
std::string errorMsg = "Invalid rule template: " + std::to_string(rawRule.size())
+ " tokens in file " + path + ". Expected 3.";
LogError(errorMsg);
- ThrowMsg(SmackException::FileError, errorMsg);
+ ThrowMsg(AccessControlException::FileError, errorMsg);
}
rules.push_back(fromRaw(rawRule));
}
*
*/
-#include <crypt.h>
-#include <sys/acl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/smack.h>
-#include <sys/xattr.h>
-#include <linux/xattr.h>
-#include <memory>
-#include <fts.h>
-#include <cstring>
-#include <cstdlib>
-#include <filesystem>
-#include <string>
-#include <algorithm>
-
-#include <dpl/log/log.h>
-#include <dpl/errno_string.h>
-#include <variant>
-#include <vector>
+#include "smack-labels.h"
-#include "acl.h"
-#include "dpl/exception.h"
-#include "security-manager.h"
-#include "service_impl_utils.h"
+#include "access-control-exception.h"
+#include "dpl/log/log.h"
+#include "protocols.h"
#include "smack-check.h"
-#include "smack-labels.h"
#include "utils.h"
+#include <crypt.h>
-namespace SecurityManager {
-namespace SmackLabels {
-
-//! Smack label used for SECURITY_MANAGER_PATH_PUBLIC_RO paths (RO for all apps)
-const char *const LABEL_FOR_APP_PUBLIC_RO_PATH = "User::Home";
-
-static inline void pathSetSmack(const char *path, const Smack::Label &label,
- const char *xattr_name)
-{
- if (smack_set_label_for_path(path, xattr_name, 0, label.c_str())) {
- LogError("smack_set_label_for_path failed. Path: " << path << " Label:" << label);
- ThrowMsg(SmackException::FileError,
- "smack_set_label_for_path failed failed. Path: " << path << " Label: " << label);
- }
-}
-
-class PathSetup {
-public:
- explicit PathSetup(bool transmute) : m_transmute(transmute) {}
- void setup(const std::string &path) const
- {
- // setting access label on everything in given directory and below
- char *const path_argv[] = { const_cast<char*>(path.c_str()), NULL };
- FTSENT *ftsent;
-
- auto fts = makeUnique(fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL), fts_close);
- if (!fts) {
- LogError("fts_open failed.");
- ThrowMsg(SmackException::FileError, "fts_open failed.");
- }
-
- 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)");
- ThrowMsg(SmackException::FileError, "FTS_ERR error or failed stat(2) (FTS_NS)");
- }
-
- /* avoid to tag directories two times */
- if (ftsent->fts_info == FTS_D)
- continue;
-
- setupFile(ftsent);
- }
-
- /* If last call to fts_read() set errno, we need to return error. */
- if ((errno != 0) && (ftsent == NULL))
- LogAndThrowErrno(SmackException::FileError, "last fts_read");
- }
-
- virtual ~PathSetup() = default;
-
-protected:
- virtual void setupFile(FTSENT *ftsent) const = 0;
-
- bool m_transmute;
-};
-
-class SmackSetup: public PathSetup {
-public:
- SmackSetup(const std::string label, bool transmute) :
- PathSetup(transmute), m_label(std::move(label))
- {
- }
-
-protected:
- void setupFile(FTSENT *ftsent) const override
- {
- pathSetSmack(ftsent->fts_path, m_label, XATTR_NAME_SMACK);
- if (m_transmute && S_ISDIR(ftsent->fts_statp->st_mode))
- pathSetSmack(ftsent->fts_path, "TRUE", XATTR_NAME_SMACKTRANSMUTE);
- }
-
-private:
- std::string m_label;
-};
-
-void setupPath(
- const std::string &pkgName,
- const std::string &path,
- app_install_path_type pathType,
- const std::string &authorHash)
-{
- std::string label;
- bool label_transmute, follow_symlink = false;
-
- switch (pathType) {
- case SECURITY_MANAGER_PATH_RW:
- label = generatePathRWLabel(pkgName);
- label_transmute = true;
- break;
- case SECURITY_MANAGER_PATH_RO:
- label = generatePathROLabel(pkgName);
- label_transmute = false;
- break;
- case SECURITY_MANAGER_PATH_PUBLIC_RO:
- label.assign(LABEL_FOR_APP_PUBLIC_RO_PATH);
- label_transmute = true;
- break;
- case SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO:
- label = generatePathSharedROLabel();
- label_transmute = true;
- follow_symlink = true;
- break;
- case SECURITY_MANAGER_PATH_TRUSTED_RW:
- if (authorHash.empty())
- ThrowMsg(SmackException::InvalidParam, "You must define author to use PATH_TRUSED_RW");
- label = generatePathTrustedLabel(authorHash);
- label_transmute = true;
- break;
- default:
- LogError("Path type not known.");
- Throw(SmackException::InvalidPathType);
- }
- SmackSetup smack(label, label_transmute);
- if (follow_symlink)
- smack.setup(realPath(path));
- smack.setup(path);
-}
-
-struct Dac {
- // ACL for files and dirs. Effective permissions will be "ANDed" with ACL mask so
- // non-executable files won't get 'x'
- Acl acl;
- uid_t owner;
- gid_t group;
-};
-
-class DacSetup: public PathSetup {
-public:
- DacSetup(Dac dac) : PathSetup(true), m_dac(std::move(dac)) {}
-
- void setupFile(FTSENT *ftsent) const override
- {
- if (0 != chown(ftsent->fts_path, m_dac.owner, m_dac.group))
- ThrowErrno(SmackException::FileError, "chown() for path: " << ftsent->fts_path);
-
- m_dac.acl.apply(ftsent->fts_path, ACL_TYPE_ACCESS);
-
- /*
- * For newly created files:
- * - let the owner come from process (be it app PUId or system_access). The creator clearly
- * already has RWX.
- * - force the group = system_access using DAC set-group-ID bit so even files created by
- * app will be accessible by sys daemons. SM needs CAP_FSETID and system_access group for
- * that.
- * - Default ACL rules will be applied from the parent directory.
- */
- if (m_transmute && ftsent->fts_level == 0 && ftsent->fts_info == FTS_D) {
- // need to re-read the mode after ACL application above
- struct stat statbuf;
- if (0 != stat(ftsent->fts_path, &statbuf))
- ThrowErrno(SmackException::FileError, "stat() for path: " << ftsent->fts_path);
-
- // add set-group-ID for system_access
- if (0 != chmod(ftsent->fts_path, S_ISGID | statbuf.st_mode))
- ThrowErrno(SmackException::FileError, "chmod() for path: " << ftsent->fts_path);
-
- // this works on all files/directories below
- m_dac.acl.apply(ftsent->fts_path, ACL_TYPE_DEFAULT);
- }
- }
-
-private:
- Dac m_dac;
-};
-
-void setupPath(const uid_t owner,
- const std::string &path,
- app_install_path_type pathType,
- const std::vector<uid_t> &processUIds,
- const std::optional<gid_t> &authorGId)
-{
- Dac dac;
- // Make the real user (owner=5001) the owner. No app should run with this uid
- dac.owner = owner;
- // Make system_access the group. No app should run with it.
- dac.group = getSystemAccessGid();
- acl_perm_t appPerms;
- acl_perm_t otherPerms;
- bool follow_symlink;
- std::vector<Acl::Entry> entries;
-
- switch (pathType) {
- case SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO:
- appPerms = Acl::RWX;
- otherPerms = Acl::RX;
- follow_symlink = true;
- break;
-
- case SECURITY_MANAGER_PATH_RW:
- appPerms = Acl::RWX;
- otherPerms = 0;
- follow_symlink = false;
- break;
-
- case SECURITY_MANAGER_PATH_RO:
- appPerms = Acl::RX;
- otherPerms = 0;
- follow_symlink = false;
- break;
-
- case SECURITY_MANAGER_PATH_PUBLIC_RO:
- appPerms = Acl::RX;
- otherPerms = Acl::RX;
- follow_symlink = false;
- break;
-
- case SECURITY_MANAGER_PATH_TRUSTED_RW:
- if (!authorGId.has_value())
- ThrowMsg(SmackException::InvalidParam, "You must define author to use PATH_TRUSED_RW");
-
- appPerms = 0;
- otherPerms = 0;
- follow_symlink = false;
- entries.emplace_back(Acl::GidEntry(Acl::RWX, *authorGId));
- break;
-
- default:
- LogError("Path type not known.");
- Throw(SmackException::InvalidPathType);
- }
-
- if (appPerms != 0) {
- for (auto &processUId : processUIds) {
- entries.emplace_back(Acl::UidEntry(appPerms, processUId));
- }
- }
-
- // RWX for the owner(5001) and system_access
- dac.acl = Acl::Make(Acl::RWX, Acl::RWX, otherPerms, std::move(entries));
-
- DacSetup dacSetup(std::move(dac));
- if (follow_symlink)
- dacSetup.setup(realPath(path));
- dacSetup.setup(path);
-}
-
-void setupPkgBasePath(const std::string &basePath)
-{
- pathSetSmack(basePath.c_str(), LABEL_FOR_APP_PUBLIC_RO_PATH, XATTR_NAME_SMACK);
-}
-
-void setupPkgBasePath(const Credentials &creds,
- const std::string &basePath,
- const std::vector<uid_t> &processUIds)
-{
- // apply public RO access permissions
- if (0 != chown(basePath.c_str(), creds.uid, getSystemAccessGid()))
- ThrowErrno(SmackException::FileError, "chown() for path: " << basePath);
-
- std::vector<Acl::Entry> entries;
- for (auto &processUId : processUIds)
- entries.emplace_back(Acl::UidEntry(Acl::RX, processUId));
-
- auto acl = Acl::Make(Acl::RWX, Acl::RWX, Acl::RX, std::move(entries));
- acl.apply(basePath, ACL_TYPE_ACCESS);
-}
-
-bool isAppPrivatePath(uid_t appUid, const std::string &path) {
- static constexpr auto dir_acl_types = {ACL_TYPE_ACCESS, ACL_TYPE_DEFAULT};
- static constexpr auto file_acl_types = {ACL_TYPE_ACCESS};
- const auto &acl_types = std::filesystem::is_directory(path) ? dir_acl_types : file_acl_types;
-
- bool has_owner_rights = false;
- bool has_other_rights = false;
- for (auto acl_type : acl_types) {
- auto acl = Acl::FromFile(path, acl_type);
- LogDebug("acl from " << path << ":\n" << acl.toString());
- for (const auto &entry : acl.toEntries()) {
- auto qualifier = entry.getQualifier();
- if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
- if (appUid == uidQualifier->uid
- && (entry.getPermissions() & Acl::RW) == Acl::RW)
- {
- has_owner_rights = true;
- }
- } else if (entry.getTag() == ACL_OTHER && (entry.getPermissions() != 0)) {
- has_other_rights = true;
- }
- }
- }
-
- return has_owner_rights && !has_other_rights;
-}
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
-void addPrivateSharing(uid_t targetAppUid, const std::string &path) {
- LogDebug("add private sharing called for target=" << targetAppUid
- <<" path=" << path);
- acl_perm_t perms = std::filesystem::is_directory(path) ? Acl::X : Acl::RX;
-
- auto acl = Acl::FromFile(path, ACL_TYPE_ACCESS);
- LogDebug("acl for " << path << " before add:\n " << acl.toString());
-
- bool entry_exists = false;
- for (auto &entry: acl.toEntries()) {
- auto qualifier = entry.getQualifier();
- if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
- if (targetAppUid == uidQualifier->uid) {
- entry_exists = true;
- break;
- }
- }
- }
- if (!entry_exists) {
- acl.addEntry(Acl::UidEntry(perms, targetAppUid));
- }
- LogDebug("acl for " << path << " after add:\n " << acl.toString());
- acl.apply(path, ACL_TYPE_ACCESS);
-}
+#include <fts.h>
+#include <linux/xattr.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
-void removePrivateSharing(uid_t targetAppUid, const std::string &path) {
- LogDebug("remove private sharing called for target=" << targetAppUid
- <<" path=" << path);
- auto acl = Acl::FromFile(path, ACL_TYPE_ACCESS);
- LogDebug("acl for " << path << " before remove:\n " << acl.toString());
-
- for (auto &entry: acl.toEntries()) {
- auto qualifier = entry.getQualifier();
- if (auto *uidQualifier = std::get_if<Acl::UidQualifier>(&qualifier)) {
- if (targetAppUid == uidQualifier->uid) {
- acl.deleteEntry(std::move(entry));
- // No other entry for this app should be on the list
- break;
- }
- }
- }
- LogDebug("acl for " << path << " after remove:\n " << acl.toString());
- acl.apply(path, ACL_TYPE_ACCESS);
-}
+namespace SecurityManager {
+namespace SmackLabels {
-void setupSharedPrivatePath(const std::string &pkgName, const std::string &path) {
- pathSetSmack(path.c_str(), generateSharedPrivateLabel(pkgName, path), XATTR_NAME_SMACK);
-}
-void generateAppPkgNameFromLabel(const Smack::Label &label, std::string &appName, std::string &pkgName)
+void generateAppPkgNameFromLabel(const Smack::Label &label,
+ std::string &appName,
+ std::string &pkgName)
{
static const char pkgPrefix[] = "User::Pkg::";
static const char appPrefix[] = "::App::";
if (label.compare(0, sizeof(pkgPrefix) - 1, pkgPrefix))
- ThrowMsg(SmackException::InvalidLabel, "Invalid application process label " << label);
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Invalid application process label " << label);
size_t pkgStartPos = sizeof(pkgPrefix) - 1;
size_t pkgEndPos = label.find(appPrefix, pkgStartPos);
}
if (pkgName.empty())
- ThrowMsg(SmackException::InvalidLabel, "No pkgName in Smack label " << label);
+ ThrowMsg(AccessControlException::InvalidLabel, "No pkgName in Smack label " << label);
}
Smack::Label generateProcessLabel(const std::string &appName, const std::string &pkgName,
label += "::App::" + appName;
if (smack_label_length(label.c_str()) <= 0)
- ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from appName " << appName);
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Invalid Smack label generated from appName " << appName);
return label;
}
Smack::Label label = "User::Pkg::" + pkgName;
if (smack_label_length(label.c_str()) <= 0)
- ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from pkgName " << pkgName);
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Invalid Smack label generated from pkgName " << pkgName);
return label;
}
Smack::Label label = "User::Pkg::" + pkgName + "::RO";
if (smack_label_length(label.c_str()) <= 0)
- ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from pkgName " << pkgName);
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Invalid Smack label generated from pkgName " << pkgName);
return label;
}
const char * cryptLabel = crypt(path.c_str(), salt.c_str());
if (!cryptLabel) {
- ThrowMsg(SmackException::Base, "crypt error");
+ ThrowMsg(AccessControlException::Base, "crypt error");
}
label += cryptLabel;
std::replace(label.begin(), label.end(), '/', '%');
if (smack_label_length(label.c_str()) <= 0)
- ThrowMsg(SmackException::InvalidLabel, "Invalid Smack label generated from path " << path);
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Invalid Smack label generated from path " << path);
return label;
}
char *label;
ssize_t labelLen = func(args..., &label);
if (labelLen <= 0)
- ThrowMsg(SmackException::Base, "Error while getting Smack label");
+ ThrowMsg(AccessControlException::Base, "Error while getting Smack label");
auto labelPtr = makeUnique(label, free);
return Smack::Label(labelPtr.get(), labelLen);
}
{
if (authorHash.empty()) {
LogError("Author was not set. It's not possible to generate label for unknown author.");
- ThrowMsg(SmackException::InvalidLabel, "Could not generate valid label without author");
+ ThrowMsg(AccessControlException::InvalidLabel,
+ "Could not generate valid label without author");
}
return "User::Author::" + authorHash;
{
if (smack_set_label_for_file(fd, XATTR_NAME_SMACK, label.c_str())) {
LogError("smack_set_label_for_file failed.");
- ThrowMsg(SmackException::FileError, "smack_set_label_for_file failed.");
+ ThrowMsg(AccessControlException::FileError, "smack_set_label_for_file failed.");
}
}
void revokeSubject(const Smack::Label &label)
{
if (smack_revoke_subject(label.c_str()))
- ThrowMsg(SmackException::LibsmackError, "smack_revoke_subject failed for " + label);
+ ThrowMsg(AccessControlException::LibsmackError, "smack_revoke_subject failed for " + label);
}
} // namespace SmackLabels
*
*/
-#include <string>
-#include <map>
-
-#include <config.h>
-#include <config-file.h>
-#include <dpl/log/log.h>
-#include <dpl/errno_string.h>
-#include <smack-check.h>
-#include <smack-exceptions.h>
-#include <smack-labels.h>
+#include "smack-rules.h"
+
+#include "dpl/log/log.h"
+#include "smack-check.h"
+#include "smack-labels.h"
+
#include <tzplatform-config.h>
-#include "smack-rules.h"
+#include <string>
namespace SecurityManager {
--- /dev/null
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * This file is licensed under the terms of MIT License or the Apache License
+ * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
+ * See the LICENSE file or the notice below for Apache License Version 2.0
+ * details.
+ *
+ * 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 "smack-setup.h"
+
+#include "access-control-exception.h"
+#include "dpl/log/log.h"
+#include "service_impl_utils.h"
+#include "smack-common.h"
+#include "smack-labels.h"
+
+#include <fts.h>
+#include <linux/xattr.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
+
+namespace SecurityManager {
+namespace {
+
+void pathSetSmack(const char *path, const Smack::Label &label, const char *xattr_name)
+{
+ if (smack_set_label_for_path(path, xattr_name, 0, label.c_str())) {
+ LogError("smack_set_label_for_path failed. Path: " << path << " Label:" << label);
+ ThrowMsg(AccessControlException::FileError,
+ "smack_set_label_for_path failed failed. Path: " << path << " Label: " << label);
+ }
+}
+
+} // namespace
+
+void SmackSetup::setupPkgBasePath(const std::string &basePath)
+{
+ pathSetSmack(basePath.c_str(), SmackLabels::LABEL_FOR_APP_PUBLIC_RO_PATH, XATTR_NAME_SMACK);
+}
+
+void SmackSetup::setupSharedPrivatePath(const std::string &pkgName, const std::string &path) {
+ pathSetSmack(path.c_str(),
+ SmackLabels::generateSharedPrivateLabel(pkgName, path),
+ XATTR_NAME_SMACK);
+}
+
+void SmackSetup::setupPath(
+ const std::string &pkgName,
+ const std::string &path,
+ app_install_path_type pathType,
+ const std::string &authorHash)
+{
+ std::string label;
+ bool label_transmute, follow_symlink = false;
+
+ switch (pathType) {
+ case SECURITY_MANAGER_PATH_RW:
+ label = SmackLabels::generatePathRWLabel(pkgName);
+ label_transmute = true;
+ break;
+ case SECURITY_MANAGER_PATH_RO:
+ label = SmackLabels::generatePathROLabel(pkgName);
+ label_transmute = false;
+ break;
+ case SECURITY_MANAGER_PATH_PUBLIC_RO:
+ label.assign(SmackLabels::LABEL_FOR_APP_PUBLIC_RO_PATH);
+ label_transmute = true;
+ break;
+ case SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO:
+ label = SmackLabels::generatePathSharedROLabel();
+ label_transmute = true;
+ follow_symlink = true;
+ break;
+ case SECURITY_MANAGER_PATH_TRUSTED_RW:
+ if (authorHash.empty())
+ ThrowMsg(AccessControlException::InvalidParam,
+ "You must define author to use PATH_TRUSED_RW");
+ label = SmackLabels::generatePathTrustedLabel(authorHash);
+ label_transmute = true;
+ break;
+ default:
+ LogError("Path type not known.");
+ Throw(AccessControlException::InvalidParam);
+ }
+ SmackSetup smack(label, label_transmute);
+ if (follow_symlink)
+ smack.setup(realPath(path));
+ smack.setup(path);
+}
+
+void SmackSetup::setupFile(FTSENT *ftsent) const
+{
+ pathSetSmack(ftsent->fts_path, m_label, XATTR_NAME_SMACK);
+ if (m_transmute && S_ISDIR(ftsent->fts_statp->st_mode))
+ pathSetSmack(ftsent->fts_path, "TRUE", XATTR_NAME_SMACKTRANSMUTE);
+}
+
+} // namespace SecurityManager
* @brief Source file of a smack rules template manager
*/
-#include <config.h>
-#include <config-file.h>
-#include <dpl/log/log.h>
-#include <filesystem.h>
-#include <smack-exceptions.h>
-
#include "template-manager.h"
+#include "access-control-exception.h"
+#include "config-file.h"
+#include "dpl/log/log.h"
+#include "filesystem-exception.h"
+
namespace SecurityManager {
namespace {
} catch (FS::Exception::Base &e) {
LogError("Error loading config files: " << e.DumpToString());
Throw(TemplateManagerException::ConfigFileError);
- } catch (SmackException::FileError &e) {
+ } catch (AccessControlException::FileError &e) {
LogError("Error parsing config files: " << e.DumpToString());
Throw(TemplateManagerException::ConfigParseError);
}
* @brief Implementation of security-manager cleanup service
*/
+#include "dpl/errno_string.h"
+#include "filesystem.h"
+#include "privilege_db.h"
+#include "smack-setup.h"
+
#include <cstdlib>
#include <cstring>
-#include <fcntl.h>
#include <iostream>
-#include <unistd.h>
+
+#include <fcntl.h>
#include <sys/stat.h>
-#include <privilege_db.h>
-#include <smack-labels.h>
-#include <dpl/errno_string.h>
-#include <filesystem.h>
+#include <unistd.h>
namespace {
const std::string tmp_flag = "/tmp/sm-cleanup-tmp-flag";
db.GetAppPkgName(appPaths.first, pkgName);
for (const auto &path : appPaths.second) {
//FIXME Make this service run as slave and master
- SmackLabels::setupPath(pkgName, path, SECURITY_MANAGER_PATH_RW);
+ SmackSetup::setupPath(pkgName, path, SECURITY_MANAGER_PATH_RW);
}
} catch (const SecurityManager::Exception &e) {
LogError("Got SecurityManager exception: " << e.GetMessage() << ", ignoring");
${PROJECT_SOURCE_DIR}/src/common/check-proper-drop.cpp
${PROJECT_SOURCE_DIR}/src/common/config-file.cpp
${PROJECT_SOURCE_DIR}/src/common/credentials.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/dac-setup.cpp
${PROJECT_SOURCE_DIR}/src/common/filesystem.cpp
${PROJECT_SOURCE_DIR}/src/common/file-lock.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/path-setup.cpp
${PROJECT_SOURCE_DIR}/src/common/permissible-set.cpp
${PROJECT_SOURCE_DIR}/src/common/privilege_db.cpp
${PROJECT_SOURCE_DIR}/src/common/service_impl_utils.cpp
${PROJECT_SOURCE_DIR}/src/common/smack-check.cpp
${PROJECT_SOURCE_DIR}/src/common/smack-labels.cpp
${PROJECT_SOURCE_DIR}/src/common/smack-rules.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/smack-setup.cpp
${PROJECT_SOURCE_DIR}/src/common/template-manager.cpp
${PROJECT_SOURCE_DIR}/src/common/filesystem.cpp
${PROJECT_SOURCE_DIR}/src/common/tzplatform-config.cpp
* limitations under the License.
*/
-#include <sys/types.h>
-#include <sys/stat.h>
+#include "acl.h"
+#include "access-control-exception.h"
+#include "testmacros.h"
+
#include <acl/libacl.h>
-#include <unistd.h>
-#include <fcntl.h>
+
#include <cstdint>
-#include <unordered_set>
#include <optional>
+#include <unordered_set>
-#include <testmacros.h>
-
-#include "acl.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
using namespace SecurityManager;
{
File file(TEST_FILE, 0000);
Acl acl;
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_ACCESS), Acl::Exception::Base);
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_DEFAULT), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_ACCESS), AccessControlException::Base);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_DEFAULT), AccessControlException::Base);
}
NEGATIVE_TEST_CASE(T1850_no_file)
{
auto acl = Acl::Make(0, 0, 0);
- BOOST_REQUIRE_THROW(acl.apply(TEST_FILE, ACL_TYPE_DEFAULT), Acl::Exception::Base);
- BOOST_REQUIRE_THROW(acl.apply(TEST_FILE, ACL_TYPE_DEFAULT), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(acl.apply(TEST_FILE, ACL_TYPE_DEFAULT), AccessControlException::FileError);
+ BOOST_REQUIRE_THROW(acl.apply(TEST_FILE, ACL_TYPE_DEFAULT), AccessControlException::FileError);
}
NEGATIVE_TEST_CASE(T1860_wrong_type)
auto acl = Acl::Make(0, 0, 0);
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), 0), Acl::Exception::Base);
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), 1), Acl::Exception::Base);
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), 0xFFFF), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), 0), AccessControlException::FileError);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), 1), AccessControlException::FileError);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), 0xFFFF), AccessControlException::FileError);
}
NEGATIVE_TEST_CASE(T1870_default_on_file)
auto acl = Acl::Make(0, 0, 0);
- BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_DEFAULT), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(acl.apply(file.Path(), ACL_TYPE_DEFAULT),
+ AccessControlException::FileError);
}
NEGATIVE_TEST_CASE(T1880_duplicated_entries)
entries.emplace_back(Acl::UidEntry(Acl::RWX, 5001));
entries.emplace_back(Acl::UidEntry(Acl::R, 5001));
- BOOST_REQUIRE_THROW(Acl::Make(0, 0, 0, std::move(entries)), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(Acl::Make(0, 0, 0, std::move(entries)), AccessControlException::AclError);
entries = std::vector<Acl::Entry>{};
entries.emplace_back(Acl::GidEntry(Acl::RWX, 100));
entries.emplace_back(Acl::GidEntry(Acl::R, 100));
- BOOST_REQUIRE_THROW(Acl::Make(0, 0, 0, std::move(entries)), Acl::Exception::Base);
+ BOOST_REQUIRE_THROW(Acl::Make(0, 0, 0, std::move(entries)), AccessControlException::AclError);
}
POSITIVE_TEST_CASE(T1890_default_file_creation)
* @version 1.0
*/
+#include "access-control-exception.h"
+#include "protocols.h"
+#include "smack-labels.h"
+#include "smack-setup.h"
+#include "testmacros.h"
+
#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
#include <linux/xattr.h>
#include <sys/smack.h>
-
-#include <dpl/log/log.h>
-#include <smack-labels.h>
-
-#include "protocols.h"
-
-#include <testmacros.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
using namespace SecurityManager;
using namespace SecurityManager::SmackLabels;
{
int invalidFd = -1;
const std::string validLabel = "smack_label";
- BOOST_REQUIRE_THROW(setSmackLabelForFd(invalidFd, validLabel), SmackException::FileError);
+ BOOST_REQUIRE_THROW(setSmackLabelForFd(invalidFd, validLabel),
+ AccessControlException::FileError);
}
NEGATIVE_FIXTURE_TEST_CASE(T1012_set_smack_label_file, FileFixture)
{
const std::string invalidLabel = "";
- BOOST_REQUIRE_THROW(setSmackLabelForFd(fd, invalidLabel), SmackException::FileError);
+ BOOST_REQUIRE_THROW(setSmackLabelForFd(fd, invalidLabel), AccessControlException::FileError);
}
NEGATIVE_FIXTURE_TEST_CASE(T1013_get_smack_label_file, FileFixture)
{
int invalidFd = -1;
- BOOST_REQUIRE_THROW(getSmackLabelFromFd(invalidFd), SmackException::Base);
+ BOOST_REQUIRE_THROW(getSmackLabelFromFd(invalidFd), AccessControlException::Base);
}
NEGATIVE_FIXTURE_TEST_CASE(T1014_get_smack_label_file, FileFixture)
{
const std::string noExistingFilePath = "/tmp/SecurityManagerUTNoExistingFile";
- BOOST_REQUIRE_THROW(getSmackLabelFromPath(noExistingFilePath), SmackException::Base);
+ BOOST_REQUIRE_THROW(getSmackLabelFromPath(noExistingFilePath), AccessControlException::Base);
}
POSITIVE_TEST_CASE(T1020_get_smack_label_process)
NEGATIVE_TEST_CASE(T1021_get_smack_label_process)
{
pid_t invalidPid = -1;
- BOOST_REQUIRE_THROW(getSmackLabelFromPid(invalidPid), SmackException::Base);
+ BOOST_REQUIRE_THROW(getSmackLabelFromPid(invalidPid), AccessControlException::Base);
}
NEGATIVE_TEST_CASE(T1022_generate_smack_label_invalid_pkg)
const std::string appName = "appNameT1030";
const std::string invalidPkgName = " ";
BOOST_REQUIRE_THROW(generateProcessLabel(appName, invalidPkgName, false),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
BOOST_REQUIRE_THROW(generateProcessLabel(appName, invalidPkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1023_generate_smack_label_invalid_app)
const std::string invalidPkgName = " ";
const std::string pkgName = "pkgNameT1031";
BOOST_REQUIRE_THROW(generateProcessLabel(invalidAppName, pkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
BOOST_REQUIRE_THROW(generateProcessLabel(invalidAppName, invalidPkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1024_generate_smack_label_path_rw_invalid_pkg)
{
const std::string invalidPkgName = " ";
- BOOST_REQUIRE_THROW(generatePathRWLabel(invalidPkgName), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generatePathRWLabel(invalidPkgName), AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1025_generate_smack_label_path_ro_invalid_pkg)
{
const std::string invalidPkgName = " ";
- BOOST_REQUIRE_THROW(generatePathROLabel(invalidPkgName), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generatePathROLabel(invalidPkgName), AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1026_generate_smack_label_path_trusted_invalid_author)
{
const std::string invalidAuthorHash = "";
- BOOST_REQUIRE_THROW(generatePathTrustedLabel(invalidAuthorHash), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generatePathTrustedLabel(invalidAuthorHash),
+ AccessControlException::InvalidLabel);
}
POSITIVE_TEST_CASE(T1030_generate_smack_labels)
const std::string invalidPkgName = " ";
BOOST_REQUIRE_THROW(generateProcessLabel(appName, invalidPkgName, false),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1032_generate_smack_label_invalid_pkg_name_hybrid)
const std::string invalidPkgName = " ";
BOOST_REQUIRE_THROW(generateProcessLabel(appName, invalidPkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1033_generate_smack_label_invalid_app_name_hybrid)
const std::string pkgName = "pkgNameT1033";
BOOST_REQUIRE_THROW(generateProcessLabel(invalidAppName, pkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1034_generate_smack_label_invalid_app_and_pkg_hybrd)
const std::string invalidPkgName = " ";
BOOST_REQUIRE_THROW(generateProcessLabel(invalidAppName, invalidPkgName, true),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
NEGATIVE_TEST_CASE(T1035_generate_smack_label_invalid_app_and_pkg_non_hybrd)
const std::string invalidPkgName = " ";
BOOST_REQUIRE_THROW(generateProcessLabel(invalidAppName, invalidPkgName, false),
- SmackException::InvalidLabel);
+ AccessControlException::InvalidLabel);
}
POSITIVE_TEST_CASE(T1041_generate_app_pkg_name_from_label)
{
std::string app, pkg;
static constexpr char invalidPrefixLabel[] = "User::Pkg:InvalidPrefix";
- BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(invalidPrefixLabel, app, pkg), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(invalidPrefixLabel, app, pkg),
+ AccessControlException::InvalidLabel);
static constexpr char emptyPkgNameLabel[] = "User::Pkg::";
- BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel, app, pkg), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel, app, pkg),
+ AccessControlException::InvalidLabel);
static constexpr char emptyPkgNameLabel2[] = "User::Pkg::::App::AppName";
- BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel2, app, pkg), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel2, app, pkg),
+ AccessControlException::InvalidLabel);
static constexpr char emptyPkgNameLabel3[] = "System::Privileged";
- BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel3, app, pkg), SmackException::InvalidLabel);
+ BOOST_REQUIRE_THROW(generateAppPkgNameFromLabel(emptyPkgNameLabel3, app, pkg),
+ AccessControlException::InvalidLabel);
}
POSITIVE_FIXTURE_TEST_CASE(T1050_setup_path_rw, DirectoryFixture)
{
const std::string pkgName = "pkgNameT1050";
- BOOST_REQUIRE_NO_THROW(setupPath(pkgName, directoryPath, SECURITY_MANAGER_PATH_RW));
+ BOOST_REQUIRE_NO_THROW(SmackSetup::setupPath(pkgName, directoryPath, SECURITY_MANAGER_PATH_RW));
const std::string pathRWLabel = generatePathRWLabel(pkgName);
BOOST_REQUIRE(pathRWLabel == getLabel(directoryPath, XATTR_NAME_SMACK));
{
const std::string pkgName = "pkgNameT1052";
- BOOST_REQUIRE_THROW(setupPath(pkgName, directoryPath, static_cast<app_install_path_type>(-1)),
- SmackException::InvalidPathType);
+ BOOST_REQUIRE_THROW(
+ SmackSetup::setupPath(pkgName, directoryPath, static_cast<app_install_path_type>(-1)),
+ AccessControlException::InvalidParam);
}
NEGATIVE_FIXTURE_TEST_CASE(T1053_setup_path_rw, DirectoryFixture)
const std::string pkgName = "pkgNameT1053";
const std::string invalidAuthorHash = "";
- BOOST_REQUIRE_THROW(setupPath(pkgName, directoryPath, SECURITY_MANAGER_PATH_TRUSTED_RW, invalidAuthorHash),
- SmackException::InvalidParam);
+ BOOST_REQUIRE_THROW(
+ SmackSetup::setupPath(pkgName,
+ directoryPath,
+ SECURITY_MANAGER_PATH_TRUSTED_RW,
+ invalidAuthorHash),
+ AccessControlException::InvalidParam);
}
NEGATIVE_FIXTURE_TEST_CASE(T1054_setup_path_rw, DirectoryFixture)
const std::string pkgName = "pkgNameT1054";
const std::string noExistingDirectoryPath = "/tmp/SecurityManagerUTNoExistingDirectory/";
- BOOST_REQUIRE_THROW(setupPath(pkgName, noExistingDirectoryPath, SECURITY_MANAGER_PATH_RW),
- SmackException::FileError);
+ BOOST_REQUIRE_THROW(
+ SmackSetup::setupPath(pkgName, noExistingDirectoryPath, SECURITY_MANAGER_PATH_RW),
+ AccessControlException::FileError);
}
POSITIVE_FIXTURE_TEST_CASE(T1060_setup_path_ro, DirectoryFixture)
{
const std::string pkgName = "pkgNameT1060";
- BOOST_REQUIRE_NO_THROW(setupPath(pkgName, directoryPath, SECURITY_MANAGER_PATH_RO));
+ BOOST_REQUIRE_NO_THROW(SmackSetup::setupPath(pkgName, directoryPath, SECURITY_MANAGER_PATH_RO));
const std::string pathROLabel = generatePathROLabel(pkgName);
BOOST_REQUIRE(pathROLabel == getLabel(directoryPath, XATTR_NAME_SMACK));
* @version 1.0
*/
+#include "access-control-exception.h"
+#include "privilege_db.h"
+#include "smack-accesses.h"
+#include "smack-labels.h"
+#include "smack-rules.h"
+#include "testmacros.h"
+
#include <algorithm>
-#include <fstream>
#include <string>
#include <vector>
-#include <smack-accesses.h>
-#include <smack-rules.h>
-#include <smack-labels.h>
-#include <privilege_db.h>
-#include <testmacros.h>
-
using namespace SecurityManager;
using namespace SecurityManager::SmackLabels;
SmackAccesses smackRules;
BOOST_REQUIRE_THROW(smackRules.add("subject", "object", "invalidPermission"),
- SmackException::LibsmackError);
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1120_smack_rules_exception_invalid_object)
{
SmackAccesses smackRules;
- BOOST_REQUIRE_THROW(smackRules.add("subject", "", "rwxatl"), SmackException::LibsmackError);
+ BOOST_REQUIRE_THROW(smackRules.add("subject", "", "rwxatl"),
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1121_smack_rules_exception_invalid_subject)
{
SmackAccesses smackRules;
- BOOST_REQUIRE_THROW(smackRules.add("", "object", "rwxatl"), SmackException::LibsmackError);
+ BOOST_REQUIRE_THROW(smackRules.add("", "object", "rwxatl"),
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1122_smack_rules_exception_addModify_invalid_permission)
SmackAccesses smackRules;
BOOST_REQUIRE_THROW(smackRules.addModify("subject", "object", "invalidPermission", ""),
- SmackException::LibsmackError);
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1123_smack_rules_exception_addModify_invalid_permission)
SmackAccesses smackRules;
BOOST_REQUIRE_THROW(smackRules.addModify("subject", "object", "", "invalidPermission"),
- SmackException::LibsmackError);
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1124_smack_rules_exception_addModify_invalid_object)
SmackAccesses smackRules;
BOOST_REQUIRE_THROW(smackRules.addModify("subject", "", "rw", "xt"),
- SmackException::LibsmackError);
+ AccessControlException::LibsmackError);
}
NEGATIVE_TEST_CASE(T1125_smack_rules_exception_addModify_invalid_subject)
SmackAccesses smackRules;
BOOST_REQUIRE_THROW(smackRules.addModify("", "object", "rw", "xt"),
- SmackException::LibsmackError);
+ AccessControlException::LibsmackError);
}
POSITIVE_TEST_CASE(T1126_smack_rules_exception)
{ \
BOOST_REQUIRE_THROW( \
SmackAccesses().add(SUBJ, OBJ, PERM), \
- SmackException::LibsmackError); \
+ AccessControlException::LibsmackError); \
}
NEGATIVE_RULE_ADD(T1127_smack_rules_exception_invalid_printable_character_subject, "subject/", "object", "rwxat")
std::string object = "object"; \
subject[0] = n; /* unprintable */ \
BOOST_REQUIRE_THROW(smackRules.add(subject, object, "rwxat"), \
- SmackException::LibsmackError); \
+ AccessControlException::LibsmackError); \
}
#define NEGATIVE_ASCII_OBJECT(n) \
std::string object = "object"; \
object[0] = n; /* unprintable */ \
BOOST_REQUIRE_THROW(smackRules.add(subject, object, "rwxat"), \
- SmackException::LibsmackError); \
+ AccessControlException::LibsmackError); \
}
NEGATIVE_ASCII_SUBJECT(1)