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