1570af302Sopenharmony_ci/* 2570af302Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4570af302Sopenharmony_ci * you may not use this file except in compliance with the License. 5570af302Sopenharmony_ci * You may obtain a copy of the License at 6570af302Sopenharmony_ci * 7570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8570af302Sopenharmony_ci * 9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12570af302Sopenharmony_ci * See the License for the specific language governing permissions and 13570af302Sopenharmony_ci * limitations under the License. 14570af302Sopenharmony_ci */ 15570af302Sopenharmony_ci#include <errno.h> 16570af302Sopenharmony_ci#include <poll.h> 17570af302Sopenharmony_ci#include <signal.h> 18570af302Sopenharmony_ci#include <stdlib.h> 19570af302Sopenharmony_ci#include <string.h> 20570af302Sopenharmony_ci#include <sys/wait.h> 21570af302Sopenharmony_ci#include <unistd.h> 22570af302Sopenharmony_ci#include <sigchain.h> 23570af302Sopenharmony_ci#include "fortify_test.h" 24570af302Sopenharmony_ci#include "functionalext.h" 25570af302Sopenharmony_ci#include "test.h" 26570af302Sopenharmony_ci 27570af302Sopenharmony_ci#define PPOLL_TIMESPEC_NSEC (100) 28570af302Sopenharmony_ci 29570af302Sopenharmony_ci/** 30570af302Sopenharmony_ci * @tc.name : poll_0010 31570af302Sopenharmony_ci * @tc.desc : test poll normal condition 32570af302Sopenharmony_ci * @tc.level : Level 0 33570af302Sopenharmony_ci */ 34570af302Sopenharmony_cistatic void poll_0010(void) 35570af302Sopenharmony_ci{ 36570af302Sopenharmony_ci errno = 0; 37570af302Sopenharmony_ci TEST(poll(NULL, 0, 1) == 0); 38570af302Sopenharmony_ci TEST(errno == 0); 39570af302Sopenharmony_ci return; 40570af302Sopenharmony_ci} 41570af302Sopenharmony_ci 42570af302Sopenharmony_ci/** 43570af302Sopenharmony_ci * @tc.name : poll_0020 44570af302Sopenharmony_ci * @tc.desc : test poll suppress compiler optimizations 45570af302Sopenharmony_ci * @tc.level : Level 2 46570af302Sopenharmony_ci */ 47570af302Sopenharmony_cistatic void poll_0020(void) 48570af302Sopenharmony_ci{ 49570af302Sopenharmony_ci struct sigaction sigabrt = { 50570af302Sopenharmony_ci .sa_handler = SignalHandler, 51570af302Sopenharmony_ci }; 52570af302Sopenharmony_ci sigaction(SIGABRT, &sigabrt, NULL); 53570af302Sopenharmony_ci 54570af302Sopenharmony_ci nfds_t fd_count = atoi("2"); 55570af302Sopenharmony_ci struct pollfd buf[1] = {{0, POLLIN, 0}}; 56570af302Sopenharmony_ci 57570af302Sopenharmony_ci int status; 58570af302Sopenharmony_ci int pid = fork(); 59570af302Sopenharmony_ci switch (pid) { 60570af302Sopenharmony_ci case -1: 61570af302Sopenharmony_ci t_error("fork failed: %s\n", strerror(errno)); 62570af302Sopenharmony_ci break; 63570af302Sopenharmony_ci case 0: 64570af302Sopenharmony_ci // Set timeout to 0 to prevent waiting for polling if hardening tests fail. 65570af302Sopenharmony_ci poll(buf, fd_count, 0); 66570af302Sopenharmony_ci exit(0); 67570af302Sopenharmony_ci default: 68570af302Sopenharmony_ci waitpid(pid, &status, WUNTRACED); 69570af302Sopenharmony_ci TEST(WIFEXITED(status) == 0); 70570af302Sopenharmony_ci TEST(WIFSTOPPED(status) == 1); 71570af302Sopenharmony_ci TEST(WSTOPSIG(status) == SIGSTOP); 72570af302Sopenharmony_ci kill(pid, SIGCONT); 73570af302Sopenharmony_ci break; 74570af302Sopenharmony_ci } 75570af302Sopenharmony_ci 76570af302Sopenharmony_ci return; 77570af302Sopenharmony_ci} 78570af302Sopenharmony_ci 79570af302Sopenharmony_ci/** 80570af302Sopenharmony_ci * @tc.name : poll_0030 81570af302Sopenharmony_ci * @tc.desc : test poll with buf's size greater than fd_count, return fd_count 82570af302Sopenharmony_ci * @tc.level : Level 1 83570af302Sopenharmony_ci */ 84570af302Sopenharmony_cistatic void poll_0030(void) 85570af302Sopenharmony_ci{ 86570af302Sopenharmony_ci int fd[2]; 87570af302Sopenharmony_ci int res = pipe(fd); 88570af302Sopenharmony_ci if (res != 0) { 89570af302Sopenharmony_ci EXPECT_TRUE("poll_0030 pipe", 0); 90570af302Sopenharmony_ci } 91570af302Sopenharmony_ci int pid = fork(); 92570af302Sopenharmony_ci if (pid == -1) { 93570af302Sopenharmony_ci EXPECT_TRUE("poll_0030 fork", 0); 94570af302Sopenharmony_ci } else if (pid == 0) { 95570af302Sopenharmony_ci // child process: send msg to master process 96570af302Sopenharmony_ci close(fd[0]); 97570af302Sopenharmony_ci const char* message = ""; 98570af302Sopenharmony_ci write(fd[1], message, strlen(message) + 1); 99570af302Sopenharmony_ci close(fd[1]); 100570af302Sopenharmony_ci exit(0); 101570af302Sopenharmony_ci } else { 102570af302Sopenharmony_ci // master process: wait events from child process 103570af302Sopenharmony_ci close(fd[1]); 104570af302Sopenharmony_ci struct pollfd buf[2] = {{fd[0], POLLIN, 0}, {fd[0], POLLIN, 0}}; 105570af302Sopenharmony_ci int result = poll(buf, 1, 100); 106570af302Sopenharmony_ci char buff; 107570af302Sopenharmony_ci while (read(fd[0], &buff, 1) > 0); 108570af302Sopenharmony_ci close(fd[0]); 109570af302Sopenharmony_ci EXPECT_EQ("poll_0030", result, 1); 110570af302Sopenharmony_ci } 111570af302Sopenharmony_ci return; 112570af302Sopenharmony_ci} 113570af302Sopenharmony_ci 114570af302Sopenharmony_ci 115570af302Sopenharmony_ci#ifdef _GNU_SOURCE 116570af302Sopenharmony_ci/** 117570af302Sopenharmony_ci * @tc.name : ppoll_0010 118570af302Sopenharmony_ci * @tc.desc : test ppoll normal condition 119570af302Sopenharmony_ci * @tc.level : Level 0 120570af302Sopenharmony_ci */ 121570af302Sopenharmony_cistatic void ppoll_0010(void) 122570af302Sopenharmony_ci{ 123570af302Sopenharmony_ci errno = 0; 124570af302Sopenharmony_ci struct timespec ts = { .tv_nsec = PPOLL_TIMESPEC_NSEC }; 125570af302Sopenharmony_ci TEST(ppoll(NULL, 0, &ts, NULL) == 0); 126570af302Sopenharmony_ci TEST(errno == 0); 127570af302Sopenharmony_ci return; 128570af302Sopenharmony_ci} 129570af302Sopenharmony_ci 130570af302Sopenharmony_ci/** 131570af302Sopenharmony_ci * @tc.name : ppoll_0020 132570af302Sopenharmony_ci * @tc.desc : test ppoll suppress compiler optimizations 133570af302Sopenharmony_ci * @tc.level : Level 2 134570af302Sopenharmony_ci */ 135570af302Sopenharmony_cistatic void ppoll_0020(void) 136570af302Sopenharmony_ci{ 137570af302Sopenharmony_ci struct sigaction sigabrt = { 138570af302Sopenharmony_ci .sa_handler = SignalHandler, 139570af302Sopenharmony_ci }; 140570af302Sopenharmony_ci sigaction(SIGABRT, &sigabrt, NULL); 141570af302Sopenharmony_ci 142570af302Sopenharmony_ci nfds_t fd_count = atoi("2"); 143570af302Sopenharmony_ci struct pollfd buf[1] = {{0, POLLIN, 0}}; 144570af302Sopenharmony_ci // Set timeout to zero to prevent waiting in ppoll when fortify test fails. 145570af302Sopenharmony_ci struct timespec timeout; 146570af302Sopenharmony_ci timeout.tv_sec = timeout.tv_nsec = 0; 147570af302Sopenharmony_ci 148570af302Sopenharmony_ci int status; 149570af302Sopenharmony_ci int pid = fork(); 150570af302Sopenharmony_ci switch (pid) { 151570af302Sopenharmony_ci case -1: 152570af302Sopenharmony_ci t_error("fork failed: %s\n", strerror(errno)); 153570af302Sopenharmony_ci break; 154570af302Sopenharmony_ci case 0: 155570af302Sopenharmony_ci ppoll(buf, fd_count, &timeout, NULL); 156570af302Sopenharmony_ci exit(0); 157570af302Sopenharmony_ci default: 158570af302Sopenharmony_ci waitpid(pid, &status, WUNTRACED); 159570af302Sopenharmony_ci TEST(WIFEXITED(status) == 0); 160570af302Sopenharmony_ci TEST(WIFSTOPPED(status) == 1); 161570af302Sopenharmony_ci TEST(WSTOPSIG(status) == SIGSTOP); 162570af302Sopenharmony_ci kill(pid, SIGCONT); 163570af302Sopenharmony_ci break; 164570af302Sopenharmony_ci } 165570af302Sopenharmony_ci 166570af302Sopenharmony_ci return; 167570af302Sopenharmony_ci} 168570af302Sopenharmony_ci 169570af302Sopenharmony_ci/** 170570af302Sopenharmony_ci * @tc.name : ppoll_0030 171570af302Sopenharmony_ci * @tc.desc : test poll with buf's size greater than fd_count, return fd_count 172570af302Sopenharmony_ci * @tc.level : Level 1 173570af302Sopenharmony_ci */ 174570af302Sopenharmony_cistatic void ppoll_0030(void) 175570af302Sopenharmony_ci{ 176570af302Sopenharmony_ci 177570af302Sopenharmony_ci int fd[2]; 178570af302Sopenharmony_ci int res = pipe(fd); 179570af302Sopenharmony_ci if (res != 0) { 180570af302Sopenharmony_ci EXPECT_TRUE("poll_0030 pipe", 0); 181570af302Sopenharmony_ci } 182570af302Sopenharmony_ci int pid = fork(); 183570af302Sopenharmony_ci if (pid == -1) { 184570af302Sopenharmony_ci EXPECT_TRUE("poll_0030 fork", 0); 185570af302Sopenharmony_ci } else if (pid == 0) { 186570af302Sopenharmony_ci // child process: send msg to master process 187570af302Sopenharmony_ci close(fd[0]); 188570af302Sopenharmony_ci const char* message = ""; 189570af302Sopenharmony_ci write(fd[1], message, strlen(message) + 1); 190570af302Sopenharmony_ci close(fd[1]); 191570af302Sopenharmony_ci exit(0); 192570af302Sopenharmony_ci } else { 193570af302Sopenharmony_ci // master process: wait events from child process 194570af302Sopenharmony_ci close(fd[1]); 195570af302Sopenharmony_ci struct pollfd buf[2] = {{fd[0], POLLIN, 0}, {fd[0], POLLIN, 0}}; 196570af302Sopenharmony_ci struct timespec ts = { .tv_nsec = 100000000 }; 197570af302Sopenharmony_ci int result = ppoll(buf, 1, &ts, NULL); 198570af302Sopenharmony_ci char buff; 199570af302Sopenharmony_ci while (read(fd[0], &buff, 1) > 0); 200570af302Sopenharmony_ci close(fd[0]); 201570af302Sopenharmony_ci EXPECT_EQ("ppoll_0030", result, 1); 202570af302Sopenharmony_ci } 203570af302Sopenharmony_ci return; 204570af302Sopenharmony_ci} 205570af302Sopenharmony_ci 206570af302Sopenharmony_ci#endif 207570af302Sopenharmony_ci 208570af302Sopenharmony_ciint main(int argc, char *argv[]) { 209570af302Sopenharmony_ci remove_all_special_handler(SIGABRT); 210570af302Sopenharmony_ci poll_0010(); 211570af302Sopenharmony_ci poll_0020(); 212570af302Sopenharmony_ci poll_0030(); 213570af302Sopenharmony_ci#ifdef _GNU_SOURCE 214570af302Sopenharmony_ci ppoll_0010(); 215570af302Sopenharmony_ci ppoll_0020(); 216570af302Sopenharmony_ci ppoll_0030(); 217570af302Sopenharmony_ci#endif 218570af302Sopenharmony_ci 219570af302Sopenharmony_ci return t_status; 220570af302Sopenharmony_ci}