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 << std::endl;
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 #ifdef TIME_DISPLAY
92 struct timeval start, end, diff;
93 gettimeofday(&start, nullptr);
94 #endif
95 const char *context = GetParamLabel(paraName.c_str());
96 #ifdef TIME_DISPLAY
97 gettimeofday(&end, nullptr);
98 timersub(&end, &start, &diff);
99 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
100 std::cout << "time use: " << runtime_us << std::endl;
101 #endif
102 std::cout << "para " << paraName.c_str() << "'s context is " << context << std::endl;
103 }
104
TestReadPara(std::string & paraName)105 static void TestReadPara(std::string ¶Name)
106 {
107 #ifdef TIME_DISPLAY
108 struct timeval start, end, diff;
109 gettimeofday(&start, nullptr);
110 #endif
111 const char *contexts = GetParamLabel(paraName.c_str());
112 std::string path = "/dev/__parameters__/" + std::string(contexts);
113 if (access(path.c_str(), F_OK) != 0) {
114 std::cout << "read param: " << paraName << " fail" << std::endl;
115 } else {
116 std::cout << "read param: " << paraName << " succ" << std::endl;
117 }
118 #ifdef TIME_DISPLAY
119 gettimeofday(&end, nullptr);
120 timersub(&end, &start, &diff);
121 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
122 std::cout << "time use: " << runtime_us << std::endl;
123 #endif
124 }
125
TestSetPara(std::string & paraName,SrcInfo * info)126 static void TestSetPara(std::string ¶Name, SrcInfo *info)
127 {
128 #ifdef TIME_DISPLAY
129 struct timeval start, end, diff;
130 gettimeofday(&start, nullptr);
131 #endif
132 std::cout << GetErrStr(SetParamCheck(paraName.c_str(), GetParamLabel(paraName.c_str()), info)) << std::endl;
133 #ifdef TIME_DISPLAY
134 gettimeofday(&end, nullptr);
135 timersub(&end, &start, &diff);
136 int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
137 std::cout << "time use: " << runtime_us << std::endl;
138 #endif
139 }
140
PrintUsage()141 static void PrintUsage()
142 {
143 std::cout << "Options:" << std::endl;
144 std::cout << " -h (--help) show the help information. [eg: param_check -h]" << std::endl;
145 std::cout << " -g (--getContext) get context for paraName. [eg: param_check -g]" << std::endl;
146 std::cout << " -r (--read) read para perm. [eg: param_check -r]" << std::endl;
147 std::cout << " -w (--write) write para perm. [eg: param_check -w]" << std::endl;
148 std::cout << " -l (--list) load para list. [eg: param_check -l]" << std::endl;
149 std::cout << " -n (--paraName) paraName. [eg: param_check -r|-w|-g -n para_name]"
150 << std::endl;
151 std::cout << "" << std::endl;
152 std::cout << "Usage:" << std::endl;
153 std::cout << ">>>>>>> choice 1: continuous input parameters" << std::endl;
154 std::cout << "step 1:" << std::endl;
155 std::cout << "param_check -r|-w|-g|-l" << std::endl;
156 std::cout << "step 2:" << std::endl;
157 std::cout << "input param name and press 'enter' to continue, or ctrl+C to end process" << std::endl;
158 std::cout << "" << std::endl;
159 std::cout << ">>>>>>> choice 2: single input parameter" << std::endl;
160 std::cout << "param_check -r|-w|-g -n para_name" << std::endl;
161 std::cout << "" << std::endl;
162 }
163
SetOptions(int argc,char * argv[],const option * options,testInput & input)164 static void SetOptions(int argc, char *argv[], const option *options, testInput &input)
165 {
166 int index = 0;
167 const char *optStr = "hgrwln:";
168 int para = 0;
169 while ((para = getopt_long(argc, argv, optStr, options, &index)) != -1) {
170 switch (para) {
171 case 'h': {
172 PrintUsage();
173 exit(0);
174 }
175 case 'n': {
176 input.paraName = optarg;
177 break;
178 }
179 case 'g': {
180 input.cmd = 'g';
181 break;
182 }
183 case 'r': {
184 input.cmd = 'r';
185 break;
186 }
187 case 'w': {
188 input.cmd = 'w';
189 break;
190 }
191 case 'l': {
192 TestLoadList();
193 exit(0);
194 }
195 default:
196 std::cout << "Try 'param_check -h' for more information." << std::endl;
197 exit(-1);
198 }
199 }
200 }
201
Test(testInput & testCmd)202 static void Test(testInput &testCmd)
203 {
204 std::string paraName;
205 switch (testCmd.cmd) {
206 case 'g': {
207 if (!testCmd.paraName.empty()) {
208 TestGetContext(testCmd.paraName);
209 exit(0);
210 }
211 while (std::cin >> paraName) {
212 TestGetContext(paraName);
213 }
214 exit(0);
215 }
216 case 'r': {
217 if (!testCmd.paraName.empty()) {
218 TestReadPara(testCmd.paraName);
219 exit(0);
220 }
221 while (std::cin >> paraName) {
222 TestReadPara(paraName);
223 }
224 exit(0);
225 }
226 case 'w': {
227 int fd[2];
228 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) {
229 perror("socketpair");
230 exit(EXIT_FAILURE);
231 }
232
233 SrcInfo info;
234 info.uc.pid = getpid();
235 info.uc.uid = getuid();
236 info.uc.gid = getgid();
237 info.sockFd = fd[0];
238 if (!testCmd.paraName.empty()) {
239 TestSetPara(testCmd.paraName, &info);
240 close(fd[0]);
241 close(fd[1]);
242 exit(0);
243 }
244 while (std::cin >> paraName) {
245 TestSetPara(paraName, &info);
246 }
247 close(fd[0]);
248 close(fd[1]);
249 exit(0);
250 }
251 default:
252 PrintUsage();
253 exit(-1);
254 }
255 }
256
main(int argc,char * argv[])257 int main(int argc, char *argv[])
258 {
259 struct option options[] = {
260 {"help", no_argument, nullptr, 'h'}, {"paraName", required_argument, nullptr, 'n'},
261 {"read", no_argument, nullptr, 'r'}, {"write", no_argument, nullptr, 'w'},
262 {"list", no_argument, nullptr, 'l'}, {"getContext", no_argument, nullptr, 'g'},
263 {nullptr, no_argument, nullptr, 0},
264 };
265
266 if (argc == 1) {
267 PrintUsage();
268 exit(0);
269 }
270 InitParamSelinux();
271 testInput testCmd;
272 SetOptions(argc, argv, options, testCmd);
273 Test(testCmd);
274 exit(0);
275 }
276