2 * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file scoped_process_label.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
23 #include <scoped_process_label.h>
26 #include <sys/smack.h>
32 #include <dpl/test/test_runner.h>
36 const std::string& getOnlycapPath()
38 static std::string onlycapPath;
40 if (onlycapPath.empty()) {
41 const char* smackfs = smack_smackfs_path();
42 if (smackfs != nullptr) {
43 onlycapPath.assign(smackfs);
44 onlycapPath.append("/onlycap");
50 const char* SEPARATORS = " ";
52 OnlycapSet smackGetOnlycap()
54 std::ifstream ifs(getOnlycapPath());
56 RUNNER_ASSERT_MSG(ifs, "Opening " << getOnlycapPath() << " failed.");
58 std::string onlycap((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
61 OnlycapSet onlycapSet;
65 while (last != std::string::npos) {
66 first = onlycap.find_first_not_of(SEPARATORS, last);
67 if (first == std::string::npos)
70 last = onlycap.find_first_of(SEPARATORS, first + 1);
71 if (last == std::string::npos)
72 onlycapSet.insert(onlycap.substr(first));
74 onlycapSet.insert(onlycap.substr(first, last - first));
79 void smackSetOnlycap(const OnlycapSet& onlycapSet)
81 if (onlycapSet.empty()) {
82 int ret = smack_set_onlycap(NULL, 0);
83 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
87 const char* labels[onlycapSet.size()];
89 for (const auto& label : onlycapSet) {
90 labels[i] = label.c_str();
94 int ret = smack_set_onlycap(labels, i);
95 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
98 void smackSetLabelForSelf(const std::string& label)
100 int ret = smack_set_label_for_self(label.c_str());
101 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_label_for_self('" << label << "'): " << ret);
104 } // namespace anonymous
106 ScopedProcessLabel::ScopedProcessLabel(std::string label, bool restore) :
107 m_label(std::move(label))
110 // store the current process label
111 char* originalLabel = NULL;
112 ssize_t size = smack_new_label_from_self(&originalLabel);
113 RUNNER_ASSERT_MSG(size > 0 || originalLabel != nullptr,
114 "Error in smack_new_label_from_self():" << size);
116 std::unique_ptr<char, decltype(&free)> originalLabelPtr(originalLabel, free);
117 m_originalLabel.assign(originalLabel, size);
119 m_originalOnlycap = smackGetOnlycap();
121 // add new label to onlycap so that it's able to restore the label
122 if (!m_originalOnlycap.empty()
123 && m_originalOnlycap.find(m_label) == m_originalOnlycap.end()) {
124 OnlycapSet newOnlycap = m_originalOnlycap;
125 newOnlycap.insert(m_label);
126 smackSetOnlycap(newOnlycap);
128 m_originalOnlycap.clear();
131 smackSetLabelForSelf(m_label);
134 ScopedProcessLabel::~ScopedProcessLabel()
136 // it has to be restored
137 if (!m_originalLabel.empty()) {
139 smackSetLabelForSelf(m_originalLabel);
140 if (!m_originalOnlycap.empty())
141 smackSetOnlycap(m_originalOnlycap);
142 } catch (const DPL::Test::TestException& e) {
143 RUNNER_ERROR_MSG("Test exception occurred: " << e.GetMessage());
144 } catch (const std::exception& e) {
145 RUNNER_ERROR_MSG("Std exception occurred: " << e.what());
147 RUNNER_ERROR_MSG("Unknown exception occurred.");