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 onlycapSet.insert(onlycap.substr(first, last - first));
76 void smackSetOnlycap(const OnlycapSet& onlycapSet)
78 if (onlycapSet.empty()) {
79 int ret = smack_set_onlycap(NULL, 0);
80 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
84 const char* labels[onlycapSet.size()];
86 for (const auto& label : onlycapSet) {
87 labels[i] = label.c_str();
91 int ret = smack_set_onlycap(labels, i);
92 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
95 void smackSetLabelForSelf(const std::string& label)
97 int ret = smack_set_label_for_self(label.c_str());
98 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_label_for_self('" << label << "'): " << ret);
101 } // namespace anonymous
103 ScopedProcessLabel::ScopedProcessLabel(std::string label, bool restore) :
104 m_label(std::move(label))
107 // store the current process label
108 char* originalLabel = NULL;
109 ssize_t size = smack_new_label_from_self(&originalLabel);
110 RUNNER_ASSERT_MSG(size > 0 || originalLabel != nullptr,
111 "Error in smack_new_label_from_self():" << size);
113 std::unique_ptr<char, decltype(&free)> originalLabelPtr(originalLabel, free);
114 m_originalLabel.assign(originalLabel, size);
116 m_originalOnlycap = smackGetOnlycap();
118 // add new label to onlycap so that it's able to restore the label
119 if (!m_originalOnlycap.empty()
120 && m_originalOnlycap.find(m_label) == m_originalOnlycap.end()) {
121 OnlycapSet newOnlycap = m_originalOnlycap;
122 newOnlycap.insert(m_label);
123 smackSetOnlycap(newOnlycap);
125 m_originalLabel.clear();
126 m_originalOnlycap.clear();
129 smackSetLabelForSelf(m_label);
132 ScopedProcessLabel::~ScopedProcessLabel()
134 // it has to be restored
135 if (!m_originalLabel.empty()) {
137 smackSetLabelForSelf(m_originalLabel);
138 smackSetOnlycap(m_originalOnlycap);
139 } catch (const DPL::Test::TestException& e) {
140 RUNNER_ERROR_MSG("Test exception occurred: " << e.GetMessage());
141 } catch (const std::exception& e) {
142 RUNNER_ERROR_MSG("Std exception occurred: " << e.what());
144 RUNNER_ERROR_MSG("Unknown exception occurred.");