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 16#include <stdlib.h> 17#include <unistd.h> 18#include <sys/wait.h> 19#include <signal.h> 20#include <sigchain.h> 21#include <errno.h> 22#include <string.h> 23#include "test.h" 24 25#define UNIT 16 26#define OFF_OFFSET 2 27#define FIRST_OFFSET (-4) 28#define FIRST_OFF_OFFSET 8 29#define MALLOC_SIZE_S (10 * sizeof(uintptr_t)) 30#define MALLOC_SIZE_L (50 * sizeof(uintptr_t)) 31#define TEST_NUM 512 32 33struct meta_in { 34 struct meta_in *prev, *next; 35 uintptr_t *mem; 36}; 37 38struct group_in { 39 struct meta_in *meta; 40}; 41 42static struct group_in *get_group(const uint8_t *p) 43{ 44 int offset = *(const uint16_t *)(p - OFF_OFFSET); 45 46 if (p[FIRST_OFFSET]) { 47 offset = *(uint32_t *)(p - FIRST_OFF_OFFSET); 48 } 49 struct group_in *base = (void *)(p - UNIT*offset - UNIT); 50 return base; 51} 52 53static void handler(int s) 54{ 55} 56 57static int child(void) 58{ 59 void *d0; 60 void *d1; 61 62 struct group_in *g0 = NULL; 63 struct group_in *g1 = NULL; 64 struct group_in *g2 = NULL; 65 66 for (int i = 0; i < TEST_NUM; ++i) { 67 d0 = malloc(MALLOC_SIZE_S); 68 if (!d0) { 69 t_error("Malloc d0 failed: %s\n", strerror(errno)); 70 return -1; 71 } 72 73 g0 = get_group(d0); 74 75 d1 = malloc(MALLOC_SIZE_L); 76 if (!d1) { 77 t_error("Malloc d1 failed: %s\n", strerror(errno)); 78 return -1; 79 } 80 g1 = get_group(d1); 81 82 if ((uintptr_t)g0->meta->mem == (uintptr_t)g0) 83 t_error("encoding pointer is equal to real pointer 1\n"); 84 85 if ((uintptr_t)g1->meta->mem == (uintptr_t)g1) 86 t_error("encoding pointer is equal to real pointer 2\n"); 87 88 if ((uintptr_t)g0->meta->prev->next == (uintptr_t)g0->meta->mem) 89 t_error("encoding pointer is equal to real pointer 1\n"); 90 91 if ((uintptr_t)g1->meta->prev->next == (uintptr_t)g1->meta->mem) 92 t_error("encoding pointer is equal to real pointer 2\n"); 93 94 free(d0); 95 free(d1); 96 } 97 98 return 0; 99} 100 101static pid_t start_child(void) 102{ 103 pid_t pid; 104 int ret; 105 pid = fork(); 106 if (pid == 0) { 107 ret = child(); 108 t_error("child process normally out with %d\n", ret); 109 return ret; 110 } 111 return pid; 112} 113 114int main(int argc, char *argv[]) 115{ 116 sigset_t set; 117 int status; 118 pid_t pid; 119 int flag = 0; 120 121 sigemptyset(&set); 122 sigaddset(&set, SIGCHLD); 123 sigprocmask(SIG_BLOCK, &set, 0); 124 signal(SIGCHLD, handler); 125 remove_all_special_handler(SIGSEGV); 126 127 pid = start_child(); 128 if (pid == -1) { 129 t_error("%s fork failed: %s\n", argv[0], strerror(errno)); 130 return -1; 131 } 132 if (sigtimedwait(&set, 0, &(struct timespec){5, 0}) == -1) { /* Wait for 5 seconds */ 133 if (errno == EAGAIN) 134 flag = 1; 135 else 136 t_error("%s sigtimedwait failed: %s\n", argv[0], strerror(errno)); 137 if (kill(pid, SIGKILL) == -1) 138 t_error("%s kill failed: %s\n", argv[0], strerror(errno)); 139 } 140 141 if (waitpid(pid, &status, 0) != pid) { 142 t_error("%s waitpid failed: %s\n", argv[0], strerror(errno)); 143 return -1; 144 } 145 146 if (flag) { 147 t_error("Child process time out\n"); 148 } 149 150 if (WIFSIGNALED(status)) { 151 if (WTERMSIG(status) != SIGSEGV && WTERMSIG(status) != SIGILL) { 152 t_error("%s child process out with %s\n", argv[0], strsignal(WTERMSIG(status))); 153 return -1; 154 } 155 } else { 156 t_error("%s child process finished normally\n", argv[0]); 157 } 158 return 0; 159} 160 161