2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Rafal Krypa <r.krypa@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
19 * @file smack-rules.cpp
20 * @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
22 * @brief Implementation of a class managing smack rules
27 #include <sys/types.h>
29 #include <sys/smack.h>
35 #include <dpl/log/log.h>
36 #include <tzplatform_config.h>
38 #include "smack-rules.h"
40 namespace SecurityManager {
42 const char *const SMACK_APP_LABEL_TEMPLATE = "~APP~";
43 const char *const APP_RULES_TEMPLATE_FILE_PATH = tzplatform_mkpath(TZ_SYS_SMACK, "app-rules-template.smack");
45 bool SmackRules::generateAppLabel(const std::string &appPkgId, std::string &label)
47 (void) appPkgId; //todo use pkgId to generate label
52 SmackRules::SmackRules()
54 if (smack_accesses_new(&m_handle) < 0) {
55 LogError("Failed to create smack_accesses handle");
56 throw std::bad_alloc();
60 SmackRules::~SmackRules() {
61 smack_accesses_free(m_handle);
64 bool SmackRules::add(const std::string &subject, const std::string &object,
65 const std::string &permissions)
67 return 0 == smack_accesses_add(m_handle, subject.c_str(), object.c_str(), permissions.c_str());
70 bool SmackRules::clear() const
72 return 0 == smack_accesses_clear(m_handle);
75 bool SmackRules::apply() const
77 return 0 == smack_accesses_apply(m_handle);
80 bool SmackRules::loadFromFile(const std::string &path)
85 fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY));
87 LogError("Failed to open file: %s" << path);
91 if (smack_accesses_add_from_file(m_handle, fd)) {
92 LogError("Failed to load smack rules from file: %s" << path);
96 if (close(fd) == -1) {
97 // don't change the return code, the descriptor should be closed despite the error.
98 LogWarning("Error while closing the file: " << path << ", error: " << strerror(errno));
104 bool SmackRules::saveToFile(const std::string &path) const
109 fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644));
111 LogError("Failed to create file: %s" << path);
115 if (smack_accesses_save(m_handle, fd)) {
116 LogError("Failed to save rules to file: %s" << path);
117 unlink(path.c_str());
121 if (close(fd) == -1) {
123 LogError("I/O Error occured while closing the file: " << path << ", error: " << strerror(errno));
124 unlink(path.c_str());
127 // non critical error
128 // don't change the return code, the descriptor should be closed despite the error.
129 LogWarning("Error while closing the file: " << path << ", error: " << strerror(errno));
137 bool SmackRules::addFromTemplateFile(const std::string &pkgId)
139 std::vector<std::string> templateRules;
141 std::ifstream templateRulesFile(APP_RULES_TEMPLATE_FILE_PATH);
143 if (!templateRulesFile.is_open()) {
144 LogError("Cannot open rules template file: " << APP_RULES_TEMPLATE_FILE_PATH);
148 while (std::getline(templateRulesFile, line)) {
149 templateRules.push_back(line);
152 if (templateRulesFile.bad()) {
153 LogError("Error reading template file: " << APP_RULES_TEMPLATE_FILE_PATH);
157 return addFromTemplate(templateRules, pkgId);
160 bool SmackRules::addFromTemplate(const std::vector<std::string> &templateRules,
161 const std::string &pkgId)
163 for (auto rule : templateRules) {
167 std::stringstream stream(rule);
168 std::string subject, object, permissions;
169 stream >> subject >> object >> permissions;
171 if (stream.fail() || !stream.eof()) {
172 LogError("Invalid rule template: " << rule);
176 bool subjectIsTemplate = (subject == SMACK_APP_LABEL_TEMPLATE);
177 bool objectIsTemplate = (object == SMACK_APP_LABEL_TEMPLATE);
179 if (objectIsTemplate == subjectIsTemplate) {
180 LogError("Invalid rule template. Exactly one app label template expected: " << rule);
184 if (subjectIsTemplate) {
185 if (!generateAppLabel(pkgId, subject)) {
186 LogError("Failed to generate app label from pkgid: " << pkgId);
191 if (objectIsTemplate) {
192 if (!generateAppLabel(pkgId, object)) {
193 LogError("Failed to generate app label from pkgid: " << pkgId);
198 if (!add(subject, object, permissions)) {
199 LogError("Failed to add rule: " << subject << " " << object << " " << permissions);
207 std::string SmackRules::getPackageRulesFilePath(const std::string &pkgId)
209 std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", pkgId.c_str()));
213 bool SmackRules::installPackageRules(const std::string &pkgId) {
215 SmackRules smackRules;
216 std::string path = getPackageRulesFilePath(pkgId);
218 if (!smackRules.addFromTemplateFile(pkgId)) {
219 LogError("Failed to load smack rules for pkgId " << pkgId);
223 if (smack_smackfs_path() != NULL && !smackRules.apply()) {
224 LogError("Failed to apply application rules to kernel");
228 if (!smackRules.saveToFile(path)) {
234 } catch (const std::bad_alloc &e) {
235 LogError("Out of memory while trying to install smack rules for pkgId " << pkgId);
240 bool SmackRules::uninstallPackageRules(const std::string &pkgId) {
241 std::string path = getPackageRulesFilePath(pkgId);
242 if (access(path.c_str(), F_OK) == -1) {
243 if (errno == ENOENT) {
244 LogWarning("Smack rules were not installed for pkgId: " << pkgId);
248 LogWarning("Cannot access smack rules path: " << path);
254 if (rules.loadFromFile(path)) {
255 if (smack_smackfs_path() != NULL && !rules.clear()) {
256 LogWarning("Failed to clear smack kernel rules for pkgId: " << pkgId);
257 // don't stop uninstallation
260 LogWarning("Failed to load rules from file: " << path);
261 // don't stop uninstallation
264 if (unlink(path.c_str()) == -1) {
265 LogError("Failed to remove smack rules file: " << path);
270 } catch (const std::bad_alloc &e) {
271 LogError("Out of memory while trying to uninstall smack rules for pkgId: " << pkgId);
276 } // namespace SecurityManager