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 */ 34static 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 */ 47static 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 */ 84static 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 */ 121static 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 */ 135static 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 */ 174static 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 208int 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}