CKM: Handle onlycap even if trailing space is missing
[platform/core/test/security-tests.git] / src / common / scoped_process_label.cpp
1 /*
2  *  Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       scoped_process_label.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  * @brief
21  */
22
23 #include <scoped_process_label.h>
24
25 #include <stdlib.h>
26 #include <sys/smack.h>
27
28 #include <utility>
29 #include <memory>
30 #include <fstream>
31
32 #include <dpl/test/test_runner.h>
33
34 namespace {
35
36 const std::string& getOnlycapPath()
37 {
38         static std::string onlycapPath;
39
40         if (onlycapPath.empty()) {
41                 const char* smackfs = smack_smackfs_path();
42                 if (smackfs != nullptr) {
43                         onlycapPath.assign(smackfs);
44                         onlycapPath.append("/onlycap");
45                 }
46         }
47         return onlycapPath;
48 }
49
50 const char* SEPARATORS = " ";
51
52 OnlycapSet smackGetOnlycap()
53 {
54         std::ifstream ifs(getOnlycapPath());
55
56         RUNNER_ASSERT_MSG(ifs, "Opening " << getOnlycapPath() << " failed.");
57
58         std::string onlycap((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
59         ifs.close();
60
61         OnlycapSet onlycapSet;
62
63         size_t first = 0;
64         size_t last = 0;
65         while (last != std::string::npos) {
66                 first = onlycap.find_first_not_of(SEPARATORS, last);
67                 if (first == std::string::npos)
68                         break;
69
70                 last = onlycap.find_first_of(SEPARATORS, first + 1);
71                 if (last == std::string::npos)
72                         onlycapSet.insert(onlycap.substr(first));
73                 else
74                         onlycapSet.insert(onlycap.substr(first, last - first));
75         }
76         return onlycapSet;
77 }
78
79 void smackSetOnlycap(const OnlycapSet& onlycapSet)
80 {
81         if (onlycapSet.empty()) {
82                 int ret = smack_set_onlycap(NULL, 0);
83                 RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
84                 return;
85         }
86
87         const char* labels[onlycapSet.size()];
88         size_t i = 0;
89         for (const auto& label : onlycapSet) {
90                 labels[i] = label.c_str();
91                 i++;
92         }
93
94         int ret = smack_set_onlycap(labels, i);
95         RUNNER_ASSERT_MSG(ret == 0, "Error in smack_set_onlycap():" << ret);
96 }
97
98 void smackSetLabelForSelf(const std::string& label)
99 {
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);
102 }
103
104 } // namespace anonymous
105
106 ScopedProcessLabel::ScopedProcessLabel(std::string label, bool restore) :
107                 m_label(std::move(label))
108 {
109         if (restore) {
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);
115
116                 std::unique_ptr<char, decltype(&free)> originalLabelPtr(originalLabel, free);
117                 m_originalLabel.assign(originalLabel, size);
118
119                 m_originalOnlycap = smackGetOnlycap();
120
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);
127                 } else {
128                         m_originalOnlycap.clear();
129                 }
130         }
131         smackSetLabelForSelf(m_label);
132 }
133
134 ScopedProcessLabel::~ScopedProcessLabel()
135 {
136         // it has to be restored
137         if (!m_originalLabel.empty()) {
138                 try {
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());
146                 } catch (...) {
147                         RUNNER_ERROR_MSG("Unknown exception occurred.");
148                 }
149         }
150 }