1c1ed15f1Sopenharmony_ci/*
2c1ed15f1Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3c1ed15f1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c1ed15f1Sopenharmony_ci * you may not use this file except in compliance with the License.
5c1ed15f1Sopenharmony_ci * You may obtain a copy of the License at
6c1ed15f1Sopenharmony_ci *
7c1ed15f1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c1ed15f1Sopenharmony_ci *
9c1ed15f1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c1ed15f1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c1ed15f1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c1ed15f1Sopenharmony_ci * See the License for the specific language governing permissions and
13c1ed15f1Sopenharmony_ci * limitations under the License.
14c1ed15f1Sopenharmony_ci */
15c1ed15f1Sopenharmony_ci
16c1ed15f1Sopenharmony_ci#include <cstdio>
17c1ed15f1Sopenharmony_ci#include <cstdlib>
18c1ed15f1Sopenharmony_ci#include <getopt.h>
19c1ed15f1Sopenharmony_ci#include <iosfwd>
20c1ed15f1Sopenharmony_ci#include <iostream>
21c1ed15f1Sopenharmony_ci#include <istream>
22c1ed15f1Sopenharmony_ci#include <memory>
23c1ed15f1Sopenharmony_ci#include <ostream>
24c1ed15f1Sopenharmony_ci#include <string>
25c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
26c1ed15f1Sopenharmony_ci#include <sys/time.h>
27c1ed15f1Sopenharmony_ci#endif
28c1ed15f1Sopenharmony_ci#include <unistd.h>
29c1ed15f1Sopenharmony_ci#include <sys/socket.h>
30c1ed15f1Sopenharmony_ci#include <selinux/selinux.h>
31c1ed15f1Sopenharmony_ci
32c1ed15f1Sopenharmony_ci#include "selinux_error.h"
33c1ed15f1Sopenharmony_ci#include "selinux_parameter.h"
34c1ed15f1Sopenharmony_ci#include "param_checker.h"
35c1ed15f1Sopenharmony_ci
36c1ed15f1Sopenharmony_ciusing namespace Selinux;
37c1ed15f1Sopenharmony_ci
38c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
39c1ed15f1Sopenharmony_ciconst static long USEC_PER_SEC = 1000000L;
40c1ed15f1Sopenharmony_ci#endif
41c1ed15f1Sopenharmony_ci
42c1ed15f1Sopenharmony_cistruct TestInput {
43c1ed15f1Sopenharmony_ci    std::string paraName;
44c1ed15f1Sopenharmony_ci    char cmd = '\0';
45c1ed15f1Sopenharmony_ci};
46c1ed15f1Sopenharmony_ci
47c1ed15f1Sopenharmony_cistatic void TestLoadList()
48c1ed15f1Sopenharmony_ci{
49c1ed15f1Sopenharmony_ci    ParamContextsList *buff = nullptr;
50c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
51c1ed15f1Sopenharmony_ci    struct timeval start, end, diff;
52c1ed15f1Sopenharmony_ci    gettimeofday(&start, nullptr);
53c1ed15f1Sopenharmony_ci#endif
54c1ed15f1Sopenharmony_ci    buff = GetParamList();
55c1ed15f1Sopenharmony_ci    if (buff == nullptr) {
56c1ed15f1Sopenharmony_ci        std::cout << "buff empty" << std::endl;
57c1ed15f1Sopenharmony_ci        return;
58c1ed15f1Sopenharmony_ci    }
59c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
60c1ed15f1Sopenharmony_ci    gettimeofday(&end, nullptr);
61c1ed15f1Sopenharmony_ci    timersub(&end, &start, &diff);
62c1ed15f1Sopenharmony_ci    int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
63c1ed15f1Sopenharmony_ci    std::cout << "GetParamList time use: " << runtime_us << std::endl;
64c1ed15f1Sopenharmony_ci#endif
65c1ed15f1Sopenharmony_ci
66c1ed15f1Sopenharmony_ci    ParamContextsList *head = buff;
67c1ed15f1Sopenharmony_ci    while (buff != nullptr) {
68c1ed15f1Sopenharmony_ci        if (security_check_context(buff->info.paraContext) < 0) {
69c1ed15f1Sopenharmony_ci            std::cout << "failed check context: " << buff->info.paraContext << " " << strlen(buff->info.paraContext)
70c1ed15f1Sopenharmony_ci                      << std::endl;
71c1ed15f1Sopenharmony_ci            buff = buff->next;
72c1ed15f1Sopenharmony_ci            continue;
73c1ed15f1Sopenharmony_ci        }
74c1ed15f1Sopenharmony_ci        std::cout << "param: " << buff->info.paraName << ", contexts: " << buff->info.paraContext
75c1ed15f1Sopenharmony_ci                  << ", index: " << buff->info.index << std::endl;
76c1ed15f1Sopenharmony_ci        buff = buff->next;
77c1ed15f1Sopenharmony_ci    }
78c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
79c1ed15f1Sopenharmony_ci    gettimeofday(&start, nullptr);
80c1ed15f1Sopenharmony_ci#endif
81c1ed15f1Sopenharmony_ci    DestroyParamList(&head);
82c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
83c1ed15f1Sopenharmony_ci    gettimeofday(&end, nullptr);
84c1ed15f1Sopenharmony_ci    timersub(&end, &start, &diff);
85c1ed15f1Sopenharmony_ci    runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
86c1ed15f1Sopenharmony_ci    std::cout << "DestroyParamList time use: " << runtime_us << std::endl;
87c1ed15f1Sopenharmony_ci#endif
88c1ed15f1Sopenharmony_ci}
89c1ed15f1Sopenharmony_ci
90c1ed15f1Sopenharmony_cistatic void TestGetContext(std::string &paraName)
91c1ed15f1Sopenharmony_ci{
92c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
93c1ed15f1Sopenharmony_ci    struct timeval start, end, diff;
94c1ed15f1Sopenharmony_ci    gettimeofday(&start, nullptr);
95c1ed15f1Sopenharmony_ci#endif
96c1ed15f1Sopenharmony_ci    const char *context = GetParamLabel(paraName.c_str());
97c1ed15f1Sopenharmony_ci    int index = GetParamLabelIndex(paraName.c_str());
98c1ed15f1Sopenharmony_ci    std::cout << "paraName: " << paraName << "context: " << context << " index: " << index << std::endl;
99c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
100c1ed15f1Sopenharmony_ci    gettimeofday(&end, nullptr);
101c1ed15f1Sopenharmony_ci    timersub(&end, &start, &diff);
102c1ed15f1Sopenharmony_ci    int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
103c1ed15f1Sopenharmony_ci    std::cout << "time use: " << runtime_us << std::endl;
104c1ed15f1Sopenharmony_ci#endif
105c1ed15f1Sopenharmony_ci    std::cout << "para " << paraName.c_str() << "'s context is " << context << std::endl;
106c1ed15f1Sopenharmony_ci}
107c1ed15f1Sopenharmony_ci
108c1ed15f1Sopenharmony_cistatic void TestReadPara(std::string &paraName)
109c1ed15f1Sopenharmony_ci{
110c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
111c1ed15f1Sopenharmony_ci    struct timeval start, end, diff;
112c1ed15f1Sopenharmony_ci    gettimeofday(&start, nullptr);
113c1ed15f1Sopenharmony_ci#endif
114c1ed15f1Sopenharmony_ci    const char *contexts = GetParamLabel(paraName.c_str());
115c1ed15f1Sopenharmony_ci    std::string path = "/dev/__parameters__/" + std::string(contexts);
116c1ed15f1Sopenharmony_ci    if (access(path.c_str(), F_OK) != 0) {
117c1ed15f1Sopenharmony_ci        std::cout << "read param: " << paraName << " fail" << std::endl;
118c1ed15f1Sopenharmony_ci    } else {
119c1ed15f1Sopenharmony_ci        std::cout << "read param: " << paraName << " succ" << std::endl;
120c1ed15f1Sopenharmony_ci    }
121c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
122c1ed15f1Sopenharmony_ci    gettimeofday(&end, nullptr);
123c1ed15f1Sopenharmony_ci    timersub(&end, &start, &diff);
124c1ed15f1Sopenharmony_ci    int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
125c1ed15f1Sopenharmony_ci    std::cout << "time use: " << runtime_us << std::endl;
126c1ed15f1Sopenharmony_ci#endif
127c1ed15f1Sopenharmony_ci}
128c1ed15f1Sopenharmony_ci
129c1ed15f1Sopenharmony_cistatic void TestSetPara(std::string &paraName, SrcInfo *info)
130c1ed15f1Sopenharmony_ci{
131c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
132c1ed15f1Sopenharmony_ci    struct timeval start, end, diff;
133c1ed15f1Sopenharmony_ci    gettimeofday(&start, nullptr);
134c1ed15f1Sopenharmony_ci#endif
135c1ed15f1Sopenharmony_ci    std::cout << GetErrStr(SetParamCheck(paraName.c_str(), GetParamLabel(paraName.c_str()), info)) << std::endl;
136c1ed15f1Sopenharmony_ci#ifdef TIME_DISPLAY
137c1ed15f1Sopenharmony_ci    gettimeofday(&end, nullptr);
138c1ed15f1Sopenharmony_ci    timersub(&end, &start, &diff);
139c1ed15f1Sopenharmony_ci    int runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
140c1ed15f1Sopenharmony_ci    std::cout << "time use: " << runtime_us << std::endl;
141c1ed15f1Sopenharmony_ci#endif
142c1ed15f1Sopenharmony_ci}
143c1ed15f1Sopenharmony_ci
144c1ed15f1Sopenharmony_cistatic void PrintUsage()
145c1ed15f1Sopenharmony_ci{
146c1ed15f1Sopenharmony_ci    std::cout << "Options:" << std::endl;
147c1ed15f1Sopenharmony_ci    std::cout << " -h (--help)           show the help information.      [eg: param_check -h]" << std::endl;
148c1ed15f1Sopenharmony_ci    std::cout << " -g (--getContext)     get context for paraName.       [eg: param_check -g]" << std::endl;
149c1ed15f1Sopenharmony_ci    std::cout << " -r (--read)           read para perm.                 [eg: param_check -r]" << std::endl;
150c1ed15f1Sopenharmony_ci    std::cout << " -w (--write)          write para perm.                [eg: param_check -w]" << std::endl;
151c1ed15f1Sopenharmony_ci    std::cout << " -l (--list)           load para list.                 [eg: param_check -l]" << std::endl;
152c1ed15f1Sopenharmony_ci    std::cout << " -n (--paraName)       paraName.                       [eg: param_check -r|-w|-g -n para_name]"
153c1ed15f1Sopenharmony_ci              << std::endl;
154c1ed15f1Sopenharmony_ci    std::cout << "" << std::endl;
155c1ed15f1Sopenharmony_ci    std::cout << "Usage:" << std::endl;
156c1ed15f1Sopenharmony_ci    std::cout << ">>>>>>> choice 1: continuous input parameters" << std::endl;
157c1ed15f1Sopenharmony_ci    std::cout << "step 1:" << std::endl;
158c1ed15f1Sopenharmony_ci    std::cout << "param_check -r|-w|-g|-l" << std::endl;
159c1ed15f1Sopenharmony_ci    std::cout << "step 2:" << std::endl;
160c1ed15f1Sopenharmony_ci    std::cout << "input param name and press 'enter' to continue, or ctrl+C to end process" << std::endl;
161c1ed15f1Sopenharmony_ci    std::cout << "" << std::endl;
162c1ed15f1Sopenharmony_ci    std::cout << ">>>>>>> choice 2: single input parameter" << std::endl;
163c1ed15f1Sopenharmony_ci    std::cout << "param_check -r|-w|-g -n para_name" << std::endl;
164c1ed15f1Sopenharmony_ci    std::cout << "" << std::endl;
165c1ed15f1Sopenharmony_ci}
166c1ed15f1Sopenharmony_ci
167c1ed15f1Sopenharmony_cistatic void SetOptions(int argc, char *argv[], const option *options, TestInput &input)
168c1ed15f1Sopenharmony_ci{
169c1ed15f1Sopenharmony_ci    int index = 0;
170c1ed15f1Sopenharmony_ci    const char *optStr = "hgrwln:";
171c1ed15f1Sopenharmony_ci    int para = 0;
172c1ed15f1Sopenharmony_ci    while ((para = getopt_long(argc, argv, optStr, options, &index)) != -1) {
173c1ed15f1Sopenharmony_ci        switch (para) {
174c1ed15f1Sopenharmony_ci            case 'h': {
175c1ed15f1Sopenharmony_ci                PrintUsage();
176c1ed15f1Sopenharmony_ci                exit(0);
177c1ed15f1Sopenharmony_ci            }
178c1ed15f1Sopenharmony_ci            case 'n': {
179c1ed15f1Sopenharmony_ci                input.paraName = optarg;
180c1ed15f1Sopenharmony_ci                break;
181c1ed15f1Sopenharmony_ci            }
182c1ed15f1Sopenharmony_ci            case 'g': {
183c1ed15f1Sopenharmony_ci                input.cmd = 'g';
184c1ed15f1Sopenharmony_ci                break;
185c1ed15f1Sopenharmony_ci            }
186c1ed15f1Sopenharmony_ci            case 'r': {
187c1ed15f1Sopenharmony_ci                input.cmd = 'r';
188c1ed15f1Sopenharmony_ci                break;
189c1ed15f1Sopenharmony_ci            }
190c1ed15f1Sopenharmony_ci            case 'w': {
191c1ed15f1Sopenharmony_ci                input.cmd = 'w';
192c1ed15f1Sopenharmony_ci                break;
193c1ed15f1Sopenharmony_ci            }
194c1ed15f1Sopenharmony_ci            case 'l': {
195c1ed15f1Sopenharmony_ci                TestLoadList();
196c1ed15f1Sopenharmony_ci                exit(0);
197c1ed15f1Sopenharmony_ci            }
198c1ed15f1Sopenharmony_ci            default:
199c1ed15f1Sopenharmony_ci                std::cout << "Try 'param_check -h' for more information." << std::endl;
200c1ed15f1Sopenharmony_ci                exit(-1);
201c1ed15f1Sopenharmony_ci        }
202c1ed15f1Sopenharmony_ci    }
203c1ed15f1Sopenharmony_ci}
204c1ed15f1Sopenharmony_ci
205c1ed15f1Sopenharmony_cistatic void TestWriteParameters(TestInput &testCmd)
206c1ed15f1Sopenharmony_ci{
207c1ed15f1Sopenharmony_ci    int fd[2];
208c1ed15f1Sopenharmony_ci    if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd) < 0) {
209c1ed15f1Sopenharmony_ci        perror("socketpair");
210c1ed15f1Sopenharmony_ci        exit(EXIT_FAILURE);
211c1ed15f1Sopenharmony_ci    }
212c1ed15f1Sopenharmony_ci
213c1ed15f1Sopenharmony_ci    SrcInfo info;
214c1ed15f1Sopenharmony_ci    info.uc.pid = getpid();
215c1ed15f1Sopenharmony_ci    info.uc.uid = getuid();
216c1ed15f1Sopenharmony_ci    info.uc.gid = getgid();
217c1ed15f1Sopenharmony_ci    info.sockFd = fd[0];
218c1ed15f1Sopenharmony_ci    if (!testCmd.paraName.empty()) {
219c1ed15f1Sopenharmony_ci        TestSetPara(testCmd.paraName, &info);
220c1ed15f1Sopenharmony_ci        close(fd[0]);
221c1ed15f1Sopenharmony_ci        close(fd[1]);
222c1ed15f1Sopenharmony_ci        exit(0);
223c1ed15f1Sopenharmony_ci    }
224c1ed15f1Sopenharmony_ci    std::string paraName;
225c1ed15f1Sopenharmony_ci    while (std::cin >> paraName) {
226c1ed15f1Sopenharmony_ci        TestSetPara(paraName, &info);
227c1ed15f1Sopenharmony_ci    }
228c1ed15f1Sopenharmony_ci    close(fd[0]);
229c1ed15f1Sopenharmony_ci    close(fd[1]);
230c1ed15f1Sopenharmony_ci    exit(0);
231c1ed15f1Sopenharmony_ci}
232c1ed15f1Sopenharmony_ci
233c1ed15f1Sopenharmony_cistatic void Test(TestInput &testCmd)
234c1ed15f1Sopenharmony_ci{
235c1ed15f1Sopenharmony_ci    std::string paraName;
236c1ed15f1Sopenharmony_ci    switch (testCmd.cmd) {
237c1ed15f1Sopenharmony_ci        case 'g': {
238c1ed15f1Sopenharmony_ci            if (!testCmd.paraName.empty()) {
239c1ed15f1Sopenharmony_ci                TestGetContext(testCmd.paraName);
240c1ed15f1Sopenharmony_ci                exit(0);
241c1ed15f1Sopenharmony_ci            }
242c1ed15f1Sopenharmony_ci            while (std::cin >> paraName) {
243c1ed15f1Sopenharmony_ci                TestGetContext(paraName);
244c1ed15f1Sopenharmony_ci            }
245c1ed15f1Sopenharmony_ci            exit(0);
246c1ed15f1Sopenharmony_ci        }
247c1ed15f1Sopenharmony_ci        case 'r': {
248c1ed15f1Sopenharmony_ci            if (!testCmd.paraName.empty()) {
249c1ed15f1Sopenharmony_ci                TestReadPara(testCmd.paraName);
250c1ed15f1Sopenharmony_ci                exit(0);
251c1ed15f1Sopenharmony_ci            }
252c1ed15f1Sopenharmony_ci            while (std::cin >> paraName) {
253c1ed15f1Sopenharmony_ci                TestReadPara(paraName);
254c1ed15f1Sopenharmony_ci            }
255c1ed15f1Sopenharmony_ci            exit(0);
256c1ed15f1Sopenharmony_ci        }
257c1ed15f1Sopenharmony_ci        case 'w': {
258c1ed15f1Sopenharmony_ci            TestWriteParameters(testCmd);
259c1ed15f1Sopenharmony_ci            break;
260c1ed15f1Sopenharmony_ci        }
261c1ed15f1Sopenharmony_ci        default:
262c1ed15f1Sopenharmony_ci            PrintUsage();
263c1ed15f1Sopenharmony_ci            exit(-1);
264c1ed15f1Sopenharmony_ci    }
265c1ed15f1Sopenharmony_ci}
266c1ed15f1Sopenharmony_ci
267c1ed15f1Sopenharmony_ciint main(int argc, char *argv[])
268c1ed15f1Sopenharmony_ci{
269c1ed15f1Sopenharmony_ci    struct option options[] = {
270c1ed15f1Sopenharmony_ci        {"help", no_argument, nullptr, 'h'}, {"paraName", required_argument, nullptr, 'n'},
271c1ed15f1Sopenharmony_ci        {"read", no_argument, nullptr, 'r'}, {"write", no_argument, nullptr, 'w'},
272c1ed15f1Sopenharmony_ci        {"list", no_argument, nullptr, 'l'}, {"getContext", no_argument, nullptr, 'g'},
273c1ed15f1Sopenharmony_ci        {nullptr, no_argument, nullptr, 0},
274c1ed15f1Sopenharmony_ci    };
275c1ed15f1Sopenharmony_ci
276c1ed15f1Sopenharmony_ci    if (argc == 1) {
277c1ed15f1Sopenharmony_ci        PrintUsage();
278c1ed15f1Sopenharmony_ci        exit(0);
279c1ed15f1Sopenharmony_ci    }
280c1ed15f1Sopenharmony_ci    InitParamSelinux(0);
281c1ed15f1Sopenharmony_ci    TestInput testCmd;
282c1ed15f1Sopenharmony_ci    SetOptions(argc, argv, options, testCmd);
283c1ed15f1Sopenharmony_ci    Test(testCmd);
284c1ed15f1Sopenharmony_ci    exit(0);
285c1ed15f1Sopenharmony_ci}
286