/* * Copyright (c) 2016-2023 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 permissible-set.cpp * @author Rafal Krypa * @author Radoslaw Bartosiak * @version 1.0 * @brief Implementation of API for adding, deleting and reading permissible names * @brief (names of installed applications) */ #ifndef _GNU_SOURCE //for TEMP_FAILURE_RETRY #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tzplatform-config.h" namespace SecurityManager { namespace PermissibleSet { template static inline int getFd(T &fstream) { return DPL::FstreamAccessors::GetFd(fstream); } template static void openAndLockNameFile(const std::string &nameFile, T &fstream) { fstream.open(nameFile); if (!fstream.is_open()) LogAndThrowErrno(PermissibleSetException::FileOpenError, "open file " << nameFile); if (TEMP_FAILURE_RETRY(flock(getFd(fstream), LOCK_EX))) LogAndThrowErrno(PermissibleSetException::FileLockError, "lock file " << nameFile); } std::string getPermissibleFileLocation(uid_t uid, int installationType) { TizenPlatformConfig tpc(uid); if ((installationType == SM_APP_INSTALL_GLOBAL) || (installationType == SM_APP_INSTALL_PRELOADED)) return std::string(LOCAL_STATE_INSTALL_DIR) + "/" + APPS_LABELS_FILE; else return std::string(LOCAL_STATE_INSTALL_DIR) + "/" + std::to_string(uid) + "/" + APPS_LABELS_FILE; } static void markPermissibleFileValid(int fd, const std::string &nameFile, bool valid) { const auto mode = valid ? 00444 : 00000; if (TEMP_FAILURE_RETRY(fchmod(fd, mode))) LogAndThrowErrno(PermissibleSetException::FileWriteError, "fchmod " << nameFile); } void updatePermissibleFile(uid_t uid, int installationType, const std::vector &labelsToAddForUser, const std::vector &labelsToRemoveForUser) { std::string nameFile = getPermissibleFileLocation(uid, installationType); std::vector labelsForUser; { std::ifstream fstream; try { openAndLockNameFile(nameFile, fstream); std::string line; while (std::getline(fstream, line)) { bool flag = true; for (auto &l : labelsToRemoveForUser) if (l == line) { flag = false; break; } if (flag) labelsForUser.push_back(line); } } catch (const PermissibleSet::PermissibleSetException::FileOpenError &e) { LogDebug("File doesn't exist yet, needs to be created - just continue; error:" << e.DumpToString()); } for (auto &l : labelsToAddForUser) labelsForUser.push_back(l); } std::ofstream fstream; openAndLockNameFile(nameFile, fstream); markPermissibleFileValid(getFd(fstream), nameFile, false); for (auto &label : labelsForUser) { fstream << label << '\n'; if (fstream.bad()) LogAndThrowErrno(PermissibleSetException::PermissibleSetException::FileWriteError, "write to file " << nameFile); } if (fstream.flush().fail()) LogAndThrowErrno(PermissibleSetException::FileWriteError, "fflush " << nameFile); if (fsync(getFd(fstream)) == -1) LogAndThrowErrno(PermissibleSetException::FileWriteError, "fsync " << nameFile); markPermissibleFileValid(getFd(fstream), nameFile, true); } void readLabelsFromPermissibleFile(const std::string &nameFile, std::vector &appLabels) { std::ifstream fstream; openAndLockNameFile(nameFile, fstream); std::string line; while (std::getline(fstream, line)) appLabels.push_back(line); if (fstream.bad()) LogAndThrowErrno(PermissibleSetException::FileReadError, "reading file " << nameFile); } void initializeUserPermissibleFile(uid_t uid) { std::string nameFile = getPermissibleFileLocation(uid, SM_APP_INSTALL_LOCAL); std::string nameDir = FS::getDirectoryName(nameFile); if (mkdir(nameDir.c_str(), 0755) != 0 && errno != EEXIST) ThrowErrno(PermissibleSetException::FileInitError, "create directory for user permissible file"); std::ofstream fstream; openAndLockNameFile(nameFile, fstream); SmackLabels::setSmackLabelForFd(getFd(fstream), "_"); markPermissibleFileValid(getFd(fstream), nameFile, true); } void removeUserPermissibleFile(uid_t uid) { std::string nameFile = getPermissibleFileLocation(uid, SM_APP_INSTALL_LOCAL); std::string nameDir = FS::getDirectoryName(nameFile); if (unlink(nameFile.c_str()) != 0 && errno != ENOENT) ThrowErrno(PermissibleSetException::FileRemoveError, "remove user permissible file"); if (rmdir(nameFile.c_str()) != 0 && errno != ENOENT) ThrowErrno(PermissibleSetException::FileRemoveError, "remove directory for user permissible file"); } } // PermissibleSet } // SecurityManager