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 36using namespace Selinux; 37 38#ifdef TIME_DISPLAY 39const static long USEC_PER_SEC = 1000000L; 40#endif 41 42struct TestInput { 43 std::string paraName; 44 char cmd = '\0'; 45}; 46 47static 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 90static 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 108static 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 129static 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 144static 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 167static 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 205static 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 233static 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 267int 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