• 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
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 &paraName)
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 &paraName)
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 &paraName, 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