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 16570af302Sopenharmony_ci#include <stdlib.h> 17570af302Sopenharmony_ci#include <unistd.h> 18570af302Sopenharmony_ci#include <sys/wait.h> 19570af302Sopenharmony_ci#include <signal.h> 20570af302Sopenharmony_ci#include <errno.h> 21570af302Sopenharmony_ci#include <string.h> 22570af302Sopenharmony_ci#include "test.h" 23570af302Sopenharmony_ci 24570af302Sopenharmony_ci#define ALIGNED_SIZE (8 * sizeof(size_t)) 25570af302Sopenharmony_ci#define POINTER_USAGE (2 * sizeof(void *)) 26570af302Sopenharmony_ci#define UAF_VAL 0xab 27570af302Sopenharmony_ci#define LOOP_SIZE 512 28570af302Sopenharmony_ci#define MALLOC_TIME 67 29570af302Sopenharmony_ci 30570af302Sopenharmony_cistatic void handler(int s) 31570af302Sopenharmony_ci{ 32570af302Sopenharmony_ci} 33570af302Sopenharmony_ci 34570af302Sopenharmony_cistatic int child(void) 35570af302Sopenharmony_ci{ 36570af302Sopenharmony_ci char *ptr[MALLOC_TIME]; 37570af302Sopenharmony_ci char *ptr1[MALLOC_TIME]; 38570af302Sopenharmony_ci char *divide[MALLOC_TIME]; 39570af302Sopenharmony_ci for (int i = 0; i < LOOP_SIZE; ++i) { 40570af302Sopenharmony_ci for (int j = 0; j < MALLOC_TIME; ++j) { 41570af302Sopenharmony_ci ptr[j] = (char *)malloc(ALIGNED_SIZE - 1); 42570af302Sopenharmony_ci if (!ptr[j]) { 43570af302Sopenharmony_ci t_error("Malloc failed:%s\n", strerror(errno)); 44570af302Sopenharmony_ci return -1; 45570af302Sopenharmony_ci } 46570af302Sopenharmony_ci divide[j] = (char *)malloc(ALIGNED_SIZE - 1); 47570af302Sopenharmony_ci if (!divide[j]) { 48570af302Sopenharmony_ci t_error("Malloc divide failed:%s\n", strerror(errno)); 49570af302Sopenharmony_ci return -1; 50570af302Sopenharmony_ci } 51570af302Sopenharmony_ci } 52570af302Sopenharmony_ci 53570af302Sopenharmony_ci for (int j = 0; j < MALLOC_TIME; ++j) { 54570af302Sopenharmony_ci free(ptr[j]); 55570af302Sopenharmony_ci /* Use after free, we should avoid changing the bin/quarantine deque pointer */ 56570af302Sopenharmony_ci ptr[j][POINTER_USAGE] = (char)(UAF_VAL - j); 57570af302Sopenharmony_ci } 58570af302Sopenharmony_ci 59570af302Sopenharmony_ci for (int j = 0; j < MALLOC_TIME; ++j) { 60570af302Sopenharmony_ci ptr1[j] = (char *)malloc(ALIGNED_SIZE - 1); 61570af302Sopenharmony_ci if (!ptr1[j]) { 62570af302Sopenharmony_ci t_error("Malloc failed:%s\n", strerror(errno)); 63570af302Sopenharmony_ci return -1; 64570af302Sopenharmony_ci } 65570af302Sopenharmony_ci } 66570af302Sopenharmony_ci 67570af302Sopenharmony_ci for (int j = 0; j < MALLOC_TIME; ++j) { 68570af302Sopenharmony_ci free(divide[j]); 69570af302Sopenharmony_ci divide[j][POINTER_USAGE] = (char)(UAF_VAL - j); 70570af302Sopenharmony_ci } 71570af302Sopenharmony_ci 72570af302Sopenharmony_ci for (int j = 0; j < MALLOC_TIME; ++j) { 73570af302Sopenharmony_ci free(ptr1[j]); 74570af302Sopenharmony_ci ptr1[j][POINTER_USAGE] = (char)(UAF_VAL - j); 75570af302Sopenharmony_ci } 76570af302Sopenharmony_ci } 77570af302Sopenharmony_ci 78570af302Sopenharmony_ci return 0; 79570af302Sopenharmony_ci} 80570af302Sopenharmony_ci 81570af302Sopenharmony_cistatic pid_t start_child(void) 82570af302Sopenharmony_ci{ 83570af302Sopenharmony_ci pid_t pid = 0; 84570af302Sopenharmony_ci int ret = 0; 85570af302Sopenharmony_ci pid = fork(); 86570af302Sopenharmony_ci if (pid == 0) { 87570af302Sopenharmony_ci ret = child(); 88570af302Sopenharmony_ci t_error("child process normally out with %d\n", ret); 89570af302Sopenharmony_ci return ret; 90570af302Sopenharmony_ci } 91570af302Sopenharmony_ci return pid; 92570af302Sopenharmony_ci} 93570af302Sopenharmony_ci 94570af302Sopenharmony_ciint main(int argc, char *argv[]) 95570af302Sopenharmony_ci{ 96570af302Sopenharmony_ci sigset_t set; 97570af302Sopenharmony_ci int status = 0; 98570af302Sopenharmony_ci pid_t pid = 0; 99570af302Sopenharmony_ci int flag = 0; 100570af302Sopenharmony_ci char *pname = (argc > 0) ? argv[0] : "malloc-uaf-check"; 101570af302Sopenharmony_ci 102570af302Sopenharmony_ci sigemptyset(&set); 103570af302Sopenharmony_ci sigaddset(&set, SIGCHLD); 104570af302Sopenharmony_ci sigprocmask(SIG_BLOCK, &set, 0); 105570af302Sopenharmony_ci signal(SIGCHLD, handler); 106570af302Sopenharmony_ci 107570af302Sopenharmony_ci pid = start_child(); 108570af302Sopenharmony_ci if (pid == -1) { 109570af302Sopenharmony_ci t_error("%s fork failed: %s\n", pname, strerror(errno)); 110570af302Sopenharmony_ci return -1; 111570af302Sopenharmony_ci } 112570af302Sopenharmony_ci if (sigtimedwait(&set, 0, &(struct timespec){5, 0}) == -1) { /* Wait for 5 seconds */ 113570af302Sopenharmony_ci if (errno == EAGAIN) 114570af302Sopenharmony_ci flag = 1; 115570af302Sopenharmony_ci else 116570af302Sopenharmony_ci t_error("%s sigtimedwait failed: %s\n", pname, strerror(errno)); 117570af302Sopenharmony_ci if (kill(pid, SIGKILL) == -1) 118570af302Sopenharmony_ci t_error("%s kill failed: %s\n", pname, strerror(errno)); 119570af302Sopenharmony_ci } 120570af302Sopenharmony_ci 121570af302Sopenharmony_ci if (waitpid(pid, &status, 0) != pid) { 122570af302Sopenharmony_ci t_error("%s waitpid failed: %s\n", pname, strerror(errno)); 123570af302Sopenharmony_ci return -1; 124570af302Sopenharmony_ci } 125570af302Sopenharmony_ci 126570af302Sopenharmony_ci if (flag) { 127570af302Sopenharmony_ci t_error("Child process time out\n"); 128570af302Sopenharmony_ci } 129570af302Sopenharmony_ci 130570af302Sopenharmony_ci if (WIFSIGNALED(status)) { 131570af302Sopenharmony_ci if (WTERMSIG(status) != SIGSEGV && WTERMSIG(status) != SIGILL) { 132570af302Sopenharmony_ci t_error("%s child process out with %s\n", pname, strsignal(WTERMSIG(status))); 133570af302Sopenharmony_ci return -1; 134570af302Sopenharmony_ci } 135570af302Sopenharmony_ci } else { 136570af302Sopenharmony_ci t_error("%s child process finished normally\n", pname); 137570af302Sopenharmony_ci } 138570af302Sopenharmony_ci return t_status; 139570af302Sopenharmony_ci} 140