1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <getopt.h>
17 #include <iostream>
18 #include <selinux/selinux.h>
19 #include <unistd.h>
20 #ifdef TIME_DISPLAY
21 #include <sys/time.h>
22 #endif
23 #include "selinux_error.h"
24 #include "selinux_parameter.h"
25
26 using namespace Selinux;
27
28 #ifdef TIME_DISPLAY
29 const static long USEC_PER_SEC = 1000000L;
30 #endif
31
32 struct testInput {
33 std::string paraName;
34 char cmd = '\0';
35 };
36
TestLoadList()37 static void TestLoadList()
38 {
39 std::string path = "/dev/__parameters__/";
40 ParamContextsList *buff = nullptr;
41 #ifdef TIME_DISPLAY
42 struct timeval start, end, diff;
43 gettimeofday(&start, nullptr);
44 #endif
45 buff = GetParamList();
46 if (buff == nullptr) {
47 std::cout << "buff empty" << std::endl;
48 return;
49 }
50 #ifdef TIME_DISPLAY
51 gettimeofday(&end, nullptr);
52 timersub(&end, &start, &diff);
53 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
54 std::cout << "GetParamList time use: " << runtime_us << std::endl;
55 #endif
56
57 ParamContextsList *head = buff;
58 while (buff != nullptr) {
59 if (security_check_context(buff->info.paraContext) < 0) {
60 std::cout << "failed check context: " << buff->info.paraContext << std::endl;
61 buff = buff->next;
62 continue;
63 }
64 std::string name = path + std::string(buff->info.paraContext);
65 FILE *fp = fopen(name.c_str(), "w");
66 if (fp == nullptr) {
67 std::cout << "failed: " << name << std::endl;
68 buff = buff->next;
69 continue;
70 }
71 (void)fclose(fp);
72 if (setfilecon(name.c_str(), buff->info.paraContext) < 0) {
73 std::cout << "setcon failed: " << name << std::endl;
74 }
75 buff = buff->next;
76 }
77 #ifdef TIME_DISPLAY
78 gettimeofday(&start, nullptr);
79 #endif
80 DestroyParamList(&head);
81 #ifdef TIME_DISPLAY
82 gettimeofday(&end, nullptr);
83 timersub(&end, &start, &diff);
84 runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
85 std::cout << "DestroyParamList time use: " << runtime_us << std::endl;
86 #endif
87 }
88
TestGetContext(std::string & paraName)89 static void TestGetContext(std::string ¶Name)
90 {
91 char *context = nullptr;
92 #ifdef TIME_DISPLAY
93 struct timeval start, end, diff;
94 gettimeofday(&start, nullptr);
95 #endif
96 int res = GetParamLabel(paraName.c_str(), &context);
97 #ifdef TIME_DISPLAY
98 gettimeofday(&end, nullptr);
99 timersub(&end, &start, &diff);
100 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
101 std::cout << "time use: " << runtime_us << std::endl;
102 #endif
103 if (res == 0) {
104 std::cout << "para " << paraName.c_str() << "'s context is " << context << std::endl;
105 } else {
106 std::cout << "para " << paraName.c_str() << "'s context get fail, " << GetErrStr(res) << std::endl;
107 }
108 if (!context) {
109 free(context);
110 }
111 }
112
TestReadPara(std::string & paraName)113 static void TestReadPara(std::string ¶Name)
114 {
115 #ifdef TIME_DISPLAY
116 struct timeval start, end, diff;
117 gettimeofday(&start, nullptr);
118 #endif
119 std::cout << GetErrStr(ReadParamCheck(paraName.c_str())) << std::endl;
120 #ifdef TIME_DISPLAY
121 gettimeofday(&end, nullptr);
122 timersub(&end, &start, &diff);
123 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
124 std::cout << "time use: " << runtime_us << std::endl;
125 #endif
126 }
127
TestSetPara(std::string & paraName,struct ucred * uc)128 static void TestSetPara(std::string ¶Name, struct ucred *uc)
129 {
130 #ifdef TIME_DISPLAY
131 struct timeval start, end, diff;
132 gettimeofday(&start, nullptr);
133 #endif
134 std::cout << GetErrStr(SetParamCheck(paraName.c_str(), uc)) << std::endl;
135 #ifdef TIME_DISPLAY
136 gettimeofday(&end, nullptr);
137 timersub(&end, &start, &diff);
138 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
139 std::cout << "time use: " << runtime_us << std::endl;
140 #endif
141 }
142
PrintUsage()143 static void PrintUsage()
144 {
145 std::cout << "Options:" << std::endl;
146 std::cout << " -h (--help) show the help information. [eg: param_check -h]" << std::endl;
147 std::cout << " -g (--getContext) get context for paraName. [eg: param_check -g]" << std::endl;
148 std::cout << " -r (--read) read para perm. [eg: param_check -r]" << std::endl;
149 std::cout << " -w (--write) write para perm. [eg: param_check -w]" << std::endl;
150 std::cout << " -l (--list) load para list. [eg: param_check -l]" << std::endl;
151 std::cout << " -n (--paraName) paraName. [eg: param_check -r|-w|-g -n para_name]"
152 << std::endl;
153 std::cout << "" << std::endl;
154 std::cout << "Usage:" << std::endl;
155 std::cout << ">>>>>>> choice 1: continuous input parameters" << std::endl;
156 std::cout << "step 1:" << std::endl;
157 std::cout << "param_check -r|-w|-g|-l" << std::endl;
158 std::cout << "step 2:" << std::endl;
159 std::cout << "input param name and press 'enter' to continue, or ctrl+C to end process" << std::endl;
160 std::cout << "" << std::endl;
161 std::cout << ">>>>>>> choice 2: single input parameter" << std::endl;
162 std::cout << "param_check -r|-w|-g -n para_name" << std::endl;
163 std::cout << "" << std::endl;
164 }
165
SetOptions(int argc,char * argv[],const option * options,testInput & input)166 static void SetOptions(int argc, char *argv[], const option *options, testInput &input)
167 {
168 int index = 0;
169 const char *optStr = "hgrwln:";
170 int para = 0;
171 while ((para = getopt_long(argc, argv, optStr, options, &index)) != -1) {
172 switch (para) {
173 case 'h': {
174 PrintUsage();
175 exit(0);
176 }
177 case 'n': {
178 input.paraName = optarg;
179 break;
180 }
181 case 'g': {
182 input.cmd = 'g';
183 break;
184 }
185 case 'r': {
186 input.cmd = 'r';
187 break;
188 }
189 case 'w': {
190 input.cmd = 'w';
191 break;
192 }
193 case 'l': {
194 TestLoadList();
195 exit(0);
196 }
197 default:
198 std::cout << "Try 'param_check -h' for more information." << std::endl;
199 exit(-1);
200 }
201 }
202 }
203
Test(testInput & testCmd)204 static void Test(testInput &testCmd)
205 {
206 std::string paraName;
207 switch (testCmd.cmd) {
208 case 'g': {
209 if (!testCmd.paraName.empty()) {
210 TestGetContext(testCmd.paraName);
211 exit(0);
212 }
213 while (std::cin >> paraName) {
214 TestGetContext(paraName);
215 }
216 exit(0);
217 }
218 case 'r': {
219 if (!testCmd.paraName.empty()) {
220 TestReadPara(testCmd.paraName);
221 exit(0);
222 }
223 while (std::cin >> paraName) {
224 TestReadPara(paraName);
225 }
226 exit(0);
227 }
228 case 'w': {
229 struct ucred uc;
230 uc.pid = getpid();
231 uc.uid = getuid();
232 uc.gid = getgid();
233 if (!testCmd.paraName.empty()) {
234 TestSetPara(testCmd.paraName, &uc);
235 exit(0);
236 }
237 while (std::cin >> paraName) {
238 TestSetPara(paraName, &uc);
239 }
240 exit(0);
241 }
242 default:
243 PrintUsage();
244 exit(-1);
245 }
246 }
247
main(int argc,char * argv[])248 int main(int argc, char *argv[])
249 {
250 struct option options[] = {
251 {"help", no_argument, nullptr, 'h'}, {"paraName", required_argument, nullptr, 'n'},
252 {"read", no_argument, nullptr, 'r'}, {"write", no_argument, nullptr, 'w'},
253 {"list", no_argument, nullptr, 'l'}, {"getContext", no_argument, nullptr, 'g'},
254 {nullptr, no_argument, nullptr, 0},
255 };
256
257 if (argc == 1) {
258 PrintUsage();
259 exit(0);
260 }
261 SetSelinuxLogCallback();
262 testInput testCmd;
263 SetOptions(argc, argv, options, testCmd);
264 Test(testCmd);
265 exit(0);
266 }
267