• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &paraName)
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 &paraName)
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 &paraName, 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