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, ¶m);
144 param.sched_priority--;
145 ret = sched_setparam(pid, ¶m);
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, ¶m);
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