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 <cstdio>
17 #include <cstdlib>
18 #include <getopt.h>
19 #include <iosfwd>
20 #include <iostream>
21 #include <istream>
22 #include <memory>
23 #include <ostream>
24 #include <string>
25 #ifdef TIME_DISPLAY
26 #include <sys/time.h>
27 #endif
28 #include <unistd.h>
29 #include <sys/socket.h>
30 #include <selinux/selinux.h>
31
32 #include "selinux_error.h"
33 #include "selinux_parameter.h"
34 #include "param_checker.h"
35
36 using namespace Selinux;
37
38 #ifdef TIME_DISPLAY
39 const static long USEC_PER_SEC = 1000000L;
40 #endif
41
42 struct testInput {
43 std::string paraName;
44 char cmd = '\0';
45 };
46
TestLoadList()47 static void TestLoadList()
48 {
49 ParamContextsList *buff = nullptr;
50 #ifdef TIME_DISPLAY
51 struct timeval start, end, diff;
52 gettimeofday(&start, nullptr);
53 #endif
54 buff = GetParamList();
55 if (buff == nullptr) {
56 std::cout << "buff empty" << std::endl;
57 return;
58 }
59 #ifdef TIME_DISPLAY
60 gettimeofday(&end, nullptr);
61 timersub(&end, &start, &diff);
62 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
63 std::cout << "GetParamList time use: " << runtime_us << std::endl;
64 #endif
65
66 ParamContextsList *head = buff;
67 while (buff != nullptr) {
68 if (security_check_context(buff->info.paraContext) < 0) {
69 std::cout << "failed check context: " << buff->info.paraContext << " " << strlen(buff->info.paraContext)
70 << std::endl;
71 buff = buff->next;
72 continue;
73 }
74 std::cout << "param: " << buff->info.paraName << ", contexts: " << buff->info.paraContext
75 << ", index: " << buff->info.index << std::endl;
76 buff = buff->next;
77 }
78 #ifdef TIME_DISPLAY
79 gettimeofday(&start, nullptr);
80 #endif
81 DestroyParamList(&head);
82 #ifdef TIME_DISPLAY
83 gettimeofday(&end, nullptr);
84 timersub(&end, &start, &diff);
85 runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
86 std::cout << "DestroyParamList time use: " << runtime_us << std::endl;
87 #endif
88 }
89
TestGetContext(std::string & paraName)90 static void TestGetContext(std::string ¶Name)
91 {
92 #ifdef TIME_DISPLAY
93 struct timeval start, end, diff;
94 gettimeofday(&start, nullptr);
95 #endif
96 const char *context = GetParamLabel(paraName.c_str());
97 int index = GetParamLabelIndex(paraName.c_str());
98 std::cout << "paraName: " << paraName << "context: " << context << " index: " << index << std::endl;
99 #ifdef TIME_DISPLAY
100 gettimeofday(&end, nullptr);
101 timersub(&end, &start, &diff);
102 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
103 std::cout << "time use: " << runtime_us << std::endl;
104 #endif
105 std::cout << "para " << paraName.c_str() << "'s context is " << context << std::endl;
106 }
107
TestReadPara(std::string & paraName)108 static void TestReadPara(std::string ¶Name)
109 {
110 #ifdef TIME_DISPLAY
111 struct timeval start, end, diff;
112 gettimeofday(&start, nullptr);
113 #endif
114 const char *contexts = GetParamLabel(paraName.c_str());
115 std::string path = "/dev/__parameters__/" + std::string(contexts);
116 if (access(path.c_str(), F_OK) != 0) {
117 std::cout << "read param: " << paraName << " fail" << std::endl;
118 } else {
119 std::cout << "read param: " << paraName << " succ" << std::endl;
120 }
121 #ifdef TIME_DISPLAY
122 gettimeofday(&end, nullptr);
123 timersub(&end, &start, &diff);
124 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
125 std::cout << "time use: " << runtime_us << std::endl;
126 #endif
127 }
128
TestSetPara(std::string & paraName,SrcInfo * info)129 static void TestSetPara(std::string ¶Name, SrcInfo *info)
130 {
131 #ifdef TIME_DISPLAY
132 struct timeval start, end, diff;
133 gettimeofday(&start, nullptr);
134 #endif
135 std::cout << GetErrStr(SetParamCheck(paraName.c_str(), GetParamLabel(paraName.c_str()), info)) << std::endl;
136 #ifdef TIME_DISPLAY
137 gettimeofday(&end, nullptr);
138 timersub(&end, &start, &diff);
139 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
140 std::cout << "time use: " << runtime_us << std::endl;
141 #endif
142 }
143
PrintUsage()144 static void PrintUsage()
145 {
146 std::cout << "Options:" << std::endl;
147 std::cout << " -h (--help) show the help information. [eg: param_check -h]" << std::endl;
148 std::cout << " -g (--getContext) get context for paraName. [eg: param_check -g]" << std::endl;
149 std::cout << " -r (--read) read para perm. [eg: param_check -r]" << std::endl;
150 std::cout << " -w (--write) write para perm. [eg: param_check -w]" << std::endl;
151 std::cout << " -l (--list) load para list. [eg: param_check -l]" << std::endl;
152 std::cout << " -n (--paraName) paraName. [eg: param_check -r|-w|-g -n para_name]"
153 << std::endl;
154 std::cout << "" << std::endl;
155 std::cout << "Usage:" << std::endl;
156 std::cout << ">>>>>>> choice 1: continuous input parameters" << std::endl;
157 std::cout << "step 1:" << std::endl;
158 std::cout << "param_check -r|-w|-g|-l" << std::endl;
159 std::cout << "step 2:" << std::endl;
160 std::cout << "input param name and press 'enter' to continue, or ctrl+C to end process" << std::endl;
161 std::cout << "" << std::endl;
162 std::cout << ">>>>>>> choice 2: single input parameter" << std::endl;
163 std::cout << "param_check -r|-w|-g -n para_name" << std::endl;
164 std::cout << "" << std::endl;
165 }
166
SetOptions(int argc,char * argv[],const option * options,testInput & input)167 static void SetOptions(int argc, char *argv[], const option *options, testInput &input)
168 {
169 int index = 0;
170 const char *optStr = "hgrwln:";
171 int para = 0;
172 while ((para = getopt_long(argc, argv, optStr, options, &index)) != -1) {
173 switch (para) {
174 case 'h': {
175 PrintUsage();
176 exit(0);
177 }
178 case 'n': {
179 input.paraName = optarg;
180 break;
181 }
182 case 'g': {
183 input.cmd = 'g';
184 break;
185 }
186 case 'r': {
187 input.cmd = 'r';
188 break;
189 }
190 case 'w': {
191 input.cmd = 'w';
192 break;
193 }
194 case 'l': {
195 TestLoadList();
196 exit(0);
197 }
198 default:
199 std::cout << "Try 'param_check -h' for more information." << std::endl;
200 exit(-1);
201 }
202 }
203 }
204
TestWriteParameters(testInput & testCmd)205 static void TestWriteParameters(testInput &testCmd)
206 {
207 int fd[2];
208 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) {
209 perror("socketpair");
210 exit(EXIT_FAILURE);
211 }
212
213 SrcInfo info;
214 info.uc.pid = getpid();
215 info.uc.uid = getuid();
216 info.uc.gid = getgid();
217 info.sockFd = fd[0];
218 if (!testCmd.paraName.empty()) {
219 TestSetPara(testCmd.paraName, &info);
220 close(fd[0]);
221 close(fd[1]);
222 exit(0);
223 }
224 std::string paraName;
225 while (std::cin >> paraName) {
226 TestSetPara(paraName, &info);
227 }
228 close(fd[0]);
229 close(fd[1]);
230 exit(0);
231 }
232
Test(testInput & testCmd)233 static void Test(testInput &testCmd)
234 {
235 std::string paraName;
236 switch (testCmd.cmd) {
237 case 'g': {
238 if (!testCmd.paraName.empty()) {
239 TestGetContext(testCmd.paraName);
240 exit(0);
241 }
242 while (std::cin >> paraName) {
243 TestGetContext(paraName);
244 }
245 exit(0);
246 }
247 case 'r': {
248 if (!testCmd.paraName.empty()) {
249 TestReadPara(testCmd.paraName);
250 exit(0);
251 }
252 while (std::cin >> paraName) {
253 TestReadPara(paraName);
254 }
255 exit(0);
256 }
257 case 'w': {
258 TestWriteParameters(testCmd);
259 break;
260 }
261 default:
262 PrintUsage();
263 exit(-1);
264 }
265 }
266
main(int argc,char * argv[])267 int main(int argc, char *argv[])
268 {
269 struct option options[] = {
270 {"help", no_argument, nullptr, 'h'}, {"paraName", required_argument, nullptr, 'n'},
271 {"read", no_argument, nullptr, 'r'}, {"write", no_argument, nullptr, 'w'},
272 {"list", no_argument, nullptr, 'l'}, {"getContext", no_argument, nullptr, 'g'},
273 {nullptr, no_argument, nullptr, 0},
274 };
275
276 if (argc == 1) {
277 PrintUsage();
278 exit(0);
279 }
280 InitParamSelinux(0);
281 testInput testCmd;
282 SetOptions(argc, argv, options, testCmd);
283 Test(testCmd);
284 exit(0);
285 }
286