• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include "pthread.h"
32 #include "linux/capability.h"
33 #include <sys/capability.h>
34 #include "it_test_capability.h"
35 #include <signal.h>
36 #include <sys/types.h>
37 #include <time.h>
38 
39 #define CAP_NUM 2
40 #define INVAILD_PID 65535
41 #define CHANGE_CHILD_UID 1000
42 
Sigac(int param)43 static void Sigac(int param)
44 {
45     return;
46 }
47 
Child()48 static void Child()
49 {
50     int i = 10;
51     signal(25, Sigac);
52 
53     while (i--) {
54         sleep(1);
55     }
56     exit(0);
57 }
58 
TestChild(VOID)59 static int TestChild(VOID)
60 {
61     struct __user_cap_header_struct capheader;
62     struct __user_cap_data_struct capdata[CAP_NUM];
63     struct __user_cap_data_struct capdatac[CAP_NUM];
64     struct timespec tp;
65     int ret;
66 
67     (void)memset_s(&capheader, sizeof(struct __user_cap_header_struct), 0, sizeof(struct __user_cap_header_struct));
68     (void)memset_s(capdata, CAP_NUM * sizeof(struct __user_cap_data_struct), 0,
69         CAP_NUM * sizeof(struct __user_cap_data_struct));
70     capdata[0].permitted = 0xffffffff;
71     capdata[1].permitted = 0xffffffff;
72     capheader.version = _LINUX_CAPABILITY_VERSION_3;
73     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SETPCAP);
74     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SETUID);
75     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_KILL);
76     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_TIME);
77     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE);
78     ret = capset(&capheader, &capdata[0]);
79     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
80     ret = capget(&capheader, &capdatac[0]);
81     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
82     capheader.pid = INVAILD_PID;
83     ret = capget(&capheader, &capdatac[0]);
84     ICUNIT_ASSERT_EQUAL(ret, -1, ret);
85     errno = 0;
86     capheader.pid = 3;
87     kill(capheader.pid, 0);
88     if (errno != ESRCH) {
89         ret = capget(&capheader, &capdatac[0]);
90         ICUNIT_ASSERT_EQUAL(ret, 0, ret);
91         printf("e %d,p %d\n", capdatac[0].effective, capdatac[0].permitted);
92     }
93     errno = 0;
94     capheader.pid = 4;
95     kill(capheader.pid, 0);
96     if (errno != ESRCH) {
97         ret = capget(&capheader, &capdatac[0]);
98         ICUNIT_ASSERT_EQUAL(ret, 0, ret);
99         printf("e %d,p %d\n", capdatac[0].effective, capdatac[0].permitted);
100     }
101     errno = 0;
102     capheader.pid = 5;
103     kill(capheader.pid, 0);
104     if (errno != ESRCH) {
105         ret = capget(&capheader, &capdatac[0]);
106         ICUNIT_ASSERT_EQUAL(ret, 0, ret);
107         printf("e %d,p %d\n", capdatac[0].effective, capdatac[0].permitted);
108     }
109     errno = 0;
110     capheader.pid = 6;
111     kill(capheader.pid, 0);
112     if (errno != ESRCH) {
113         ret = capget(&capheader, &capdatac[0]);
114         ICUNIT_ASSERT_EQUAL(ret, 0, ret);
115         printf("e %d,p %d\n", capdatac[0].effective, capdatac[0].permitted);
116     }
117     capheader.pid = 0;
118 
119     int pid = fork();
120     if (pid == 0) {
121         ret = setuid(CHANGE_CHILD_UID);
122         ICUNIT_ASSERT_EQUAL(ret, 0, ret);
123         Child();
124     }
125     sleep(1);
126     ret = kill(pid, SIGXFSZ);
127     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
128     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective &= ~CAP_TO_MASK(CAP_KILL);
129     ret = capset(&capheader, &capdata[0]);
130     ret = kill(pid, SIGXFSZ);
131     ICUNIT_ASSERT_EQUAL(ret, -1, ret);
132 
133     tp.tv_sec = 0;
134     tp.tv_nsec = 0;
135     ret = clock_settime(CLOCK_REALTIME, &tp);
136     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
137     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective &= ~CAP_TO_MASK(CAP_SYS_TIME);
138     ret = capset(&capheader, &capdata[0]);
139     ret = clock_settime(CLOCK_REALTIME, &tp);
140     ICUNIT_ASSERT_EQUAL(ret, -1, ret);
141 
142     struct sched_param param = { 0 };
143     ret = sched_getparam(pid, &param);
144     param.sched_priority--;
145     ret = sched_setparam(pid, &param);
146     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
147     capdata[CAP_TO_INDEX(CAP_SYS_NICE)].effective &= ~CAP_TO_MASK(CAP_SYS_NICE);
148     ret = capset(&capheader, &capdata[0]);
149     ret = sched_setparam(pid, &param);
150     ICUNIT_ASSERT_EQUAL(ret, -1, ret);
151     wait(nullptr);
152     exit(92);
153 
154     return 0;
155 }
156 
TestCase(VOID)157 static int TestCase(VOID)
158 {
159     int ret;
160     int status = 0;
161     pid_t pid = fork();
162     ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT);
163     if (pid == 0) {
164         ret = TestChild();
165         exit(__LINE__);
166     }
167 
168     ret = waitpid(pid, &status, 0);
169     ICUNIT_GOTO_EQUAL(ret, pid, ret, EXIT);
170     status = WEXITSTATUS(status);
171     ICUNIT_GOTO_EQUAL(status, 92, status, EXIT);
172 
173     return 0;
174 
175 EXIT:
176     return 1;
177 }
178 
ItTestCap001(void)179 void ItTestCap001(void)
180 {
181     TEST_ADD_CASE("IT_SEC_CAP_001", TestCase, TEST_POSIX, TEST_SEC, TEST_LEVEL0, TEST_FUNCTION);
182 }
183