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 #include <errno.h>
16 #include <poll.h>
17 #include <signal.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/wait.h>
21 #include <unistd.h>
22 #include <sigchain.h>
23 #include "fortify_test.h"
24 #include "functionalext.h"
25 #include "test.h"
26
27 #define PPOLL_TIMESPEC_NSEC (100)
28
29 /**
30 * @tc.name : poll_0010
31 * @tc.desc : test poll normal condition
32 * @tc.level : Level 0
33 */
poll_0010(void)34 static void poll_0010(void)
35 {
36 errno = 0;
37 TEST(poll(NULL, 0, 1) == 0);
38 TEST(errno == 0);
39 return;
40 }
41
42 /**
43 * @tc.name : poll_0020
44 * @tc.desc : test poll suppress compiler optimizations
45 * @tc.level : Level 2
46 */
poll_0020(void)47 static void poll_0020(void)
48 {
49 struct sigaction sigabrt = {
50 .sa_handler = SignalHandler,
51 };
52 sigaction(SIGABRT, &sigabrt, NULL);
53
54 nfds_t fd_count = atoi("2");
55 struct pollfd buf[1] = {{0, POLLIN, 0}};
56
57 int status;
58 int pid = fork();
59 switch (pid) {
60 case -1:
61 t_error("fork failed: %s\n", strerror(errno));
62 break;
63 case 0:
64 // Set timeout to 0 to prevent waiting for polling if hardening tests fail.
65 poll(buf, fd_count, 0);
66 exit(0);
67 default:
68 waitpid(pid, &status, WUNTRACED);
69 TEST(WIFEXITED(status) == 0);
70 TEST(WIFSTOPPED(status) == 1);
71 TEST(WSTOPSIG(status) == SIGSTOP);
72 kill(pid, SIGCONT);
73 break;
74 }
75
76 return;
77 }
78
79 /**
80 * @tc.name : poll_0030
81 * @tc.desc : test poll with buf's size greater than fd_count, return fd_count
82 * @tc.level : Level 1
83 */
poll_0030(void)84 static void poll_0030(void)
85 {
86 int fd[2];
87 int res = pipe(fd);
88 if (res != 0) {
89 EXPECT_TRUE("poll_0030 pipe", 0);
90 }
91 int pid = fork();
92 if (pid == -1) {
93 EXPECT_TRUE("poll_0030 fork", 0);
94 } else if (pid == 0) {
95 // child process: send msg to master process
96 close(fd[0]);
97 const char* message = "";
98 write(fd[1], message, strlen(message) + 1);
99 close(fd[1]);
100 exit(0);
101 } else {
102 // master process: wait events from child process
103 close(fd[1]);
104 struct pollfd buf[2] = {{fd[0], POLLIN, 0}, {fd[0], POLLIN, 0}};
105 int result = poll(buf, 1, 100);
106 char buff;
107 while (read(fd[0], &buff, 1) > 0);
108 close(fd[0]);
109 EXPECT_EQ("poll_0030", result, 1);
110 }
111 return;
112 }
113
114
115 #ifdef _GNU_SOURCE
116 /**
117 * @tc.name : ppoll_0010
118 * @tc.desc : test ppoll normal condition
119 * @tc.level : Level 0
120 */
ppoll_0010(void)121 static void ppoll_0010(void)
122 {
123 errno = 0;
124 struct timespec ts = { .tv_nsec = PPOLL_TIMESPEC_NSEC };
125 TEST(ppoll(NULL, 0, &ts, NULL) == 0);
126 TEST(errno == 0);
127 return;
128 }
129
130 /**
131 * @tc.name : ppoll_0020
132 * @tc.desc : test ppoll suppress compiler optimizations
133 * @tc.level : Level 2
134 */
ppoll_0020(void)135 static void ppoll_0020(void)
136 {
137 struct sigaction sigabrt = {
138 .sa_handler = SignalHandler,
139 };
140 sigaction(SIGABRT, &sigabrt, NULL);
141
142 nfds_t fd_count = atoi("2");
143 struct pollfd buf[1] = {{0, POLLIN, 0}};
144 // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
145 struct timespec timeout;
146 timeout.tv_sec = timeout.tv_nsec = 0;
147
148 int status;
149 int pid = fork();
150 switch (pid) {
151 case -1:
152 t_error("fork failed: %s\n", strerror(errno));
153 break;
154 case 0:
155 ppoll(buf, fd_count, &timeout, NULL);
156 exit(0);
157 default:
158 waitpid(pid, &status, WUNTRACED);
159 TEST(WIFEXITED(status) == 0);
160 TEST(WIFSTOPPED(status) == 1);
161 TEST(WSTOPSIG(status) == SIGSTOP);
162 kill(pid, SIGCONT);
163 break;
164 }
165
166 return;
167 }
168
169 /**
170 * @tc.name : ppoll_0030
171 * @tc.desc : test poll with buf's size greater than fd_count, return fd_count
172 * @tc.level : Level 1
173 */
ppoll_0030(void)174 static void ppoll_0030(void)
175 {
176
177 int fd[2];
178 int res = pipe(fd);
179 if (res != 0) {
180 EXPECT_TRUE("poll_0030 pipe", 0);
181 }
182 int pid = fork();
183 if (pid == -1) {
184 EXPECT_TRUE("poll_0030 fork", 0);
185 } else if (pid == 0) {
186 // child process: send msg to master process
187 close(fd[0]);
188 const char* message = "";
189 write(fd[1], message, strlen(message) + 1);
190 close(fd[1]);
191 exit(0);
192 } else {
193 // master process: wait events from child process
194 close(fd[1]);
195 struct pollfd buf[2] = {{fd[0], POLLIN, 0}, {fd[0], POLLIN, 0}};
196 struct timespec ts = { .tv_nsec = 100000000 };
197 int result = ppoll(buf, 1, &ts, NULL);
198 char buff;
199 while (read(fd[0], &buff, 1) > 0);
200 close(fd[0]);
201 EXPECT_EQ("ppoll_0030", result, 1);
202 }
203 return;
204 }
205
206 #endif
207
main(int argc,char * argv[])208 int main(int argc, char *argv[]) {
209 remove_all_special_handler(SIGABRT);
210 poll_0010();
211 poll_0020();
212 poll_0030();
213 #ifdef _GNU_SOURCE
214 ppoll_0010();
215 ppoll_0020();
216 ppoll_0030();
217 #endif
218
219 return t_status;
220 }