1/* 2 * Copyright (C) 2024 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 <stdio.h> 17#include <stdlib.h> 18#include <signal.h> 19#include <pthread.h> 20#include <fcntl.h> 21#include <stdint.h> 22#include <string.h> 23#include <sys/wait.h> 24#include <unistd.h> 25#include <musl_log.h> 26#include <stdio_impl.h> 27 28#include <unordered_map> 29 30#include "functionalext.h" 31 32#define DEV_NULL_PATH "/dev/null" 33 34void signal_handler_abort(int signum) 35{ 36 kill(getpid(), SIGSTOP); 37} 38 39void signal_handler_abort1(int signum) 40{ 41 exit(signum); 42} 43 44void fdsan_test_get_tag_value() 45{ 46 int fd = open(DEV_NULL_PATH, O_RDONLY); 47 uint64_t tag = fdsan_get_owner_tag(fd); 48 EXPECT_EQ("fdsan_test_get_tag_value", strcmp(fdsan_get_tag_type(tag), "native object of unknown type"), 0); 49 EXPECT_EQ("fdsan_test_get_tag_value", fdsan_get_tag_value(tag), 0); 50 EXPECT_EQ("fdsan_test_get_tag_value", close(fd), 0); 51} 52 53void fdsan_test_overflow() 54{ 55 std::unordered_map<int, uint64_t> fds; 56 for (int i = 0; i < 4096; ++i) { 57 int fd = open(DEV_NULL_PATH, O_RDONLY); 58 auto tag = 0xdead00000000ULL | i; 59 fdsan_exchange_owner_tag(fd, 0, tag); 60 fds[fd] = tag; 61 } 62 63 for (auto [fd, tag] : fds) { 64 EXPECT_EQ("fdsan_test_overflow", fdsan_close_with_tag(fd, tag), 0); 65 } 66} 67 68void fdsan_test_vfork() 69{ 70 int fd = open(DEV_NULL_PATH, O_RDONLY); 71 72 pid_t rc = vfork(); 73 EXPECT_NE("fdsan_test_vfork", -1, rc); 74 75 if (rc == 0) { 76 close(fd); 77 _exit(0); 78 } 79 80 int status; 81 pid_t wait_result = waitpid(rc, &status, 0); 82 EXPECT_EQ("fdsan_test_vfork", wait_result, rc); 83 EXPECT_TRUE("fdsan_test_vfork", WIFEXITED(status)); 84 EXPECT_EQ("fdsan_test_vfork", 0, WEXITSTATUS(status)); 85} 86 87void fdsan_test_fatal_level() 88{ 89 struct sigaction sigabrt = { 90 .sa_handler = signal_handler_abort, 91 }; 92 sigaction(SIGABRT, &sigabrt, nullptr); 93 94 int status; 95 int pid = fork(); 96 switch (pid) { 97 case -1: { 98 t_error("fork failed: %d\n", __LINE__); 99 break; 100 } 101 case 0: { 102 fdsan_set_error_level(FDSAN_ERROR_LEVEL_FATAL); 103 int fd = open(DEV_NULL_PATH, O_RDONLY); 104 uint64_t tag = 0xdead00000000ULL; 105 fdsan_exchange_owner_tag(fd, 0, tag); 106 fdsan_close_with_tag(fd, 0); 107 exit(0); 108 } 109 default: { 110 waitpid(pid, &status, WUNTRACED); 111 EXPECT_EQ("fdsan_test_fatal_level", WIFEXITED(status), 0); 112 EXPECT_EQ("fdsan_test_fatal_level", WIFSTOPPED(status), 1); 113 EXPECT_EQ("fdsan_test_fatal_level", WSTOPSIG(status), SIGSTOP); 114 kill(pid, SIGCONT); 115 break; 116 } 117 } 118 return; 119} 120 121bool CreateFile() 122{ 123 // 创建一个临时文件 124 // 指定文件路径 125 const char *file_path = "/data/local/tmp/test.txt"; 126 127 // 创建文件并打开文件描述符 128 int fd = open(file_path, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); 129 if (fd == -1) { 130 return false; 131 } 132 133 // 关闭文件描述符 134 close(fd); 135 return true; 136} 137 138 139void fdsan_test_internal_fopen_succeed() 140{ 141 struct sigaction sigabrt = { 142 .sa_handler = signal_handler_abort, 143 }; 144 sigaction(SIGABRT, &sigabrt, nullptr); 145 bool res = CreateFile(); 146 if (!res) { 147 t_error("fdsan_test_internal_fopen create file failed"); 148 return; 149 } 150 int status; 151 int pid = fork(); 152 switch (pid) { 153 case -1: { 154 t_error("fork failed: %d\n", __LINE__); 155 break; 156 } 157 case 0: { 158 fdsan_set_error_level(FDSAN_ERROR_LEVEL_FATAL); 159 unsigned char str[1024]; 160 FILE f; 161 FILE *ptr = __fopen_rb_ca(file_path, &f, str, sizeof(str)); 162 EXPECT_NE("fdsan_test_internal_fopen_succeed open file failed", ptr, NULL); 163 if (ptr) { 164 __fclose_ca(ptr); 165 } 166 exit(0); 167 } 168 default: { 169 waitpid(pid, &status, WUNTRACED); 170 EXPECT_EQ("fdsan_test_fork_subprocess_disabled WIFEXITED", WIFEXITED(status), 1); 171 EXPECT_EQ("fdsan_test_fork_subprocess_disabled WIFSTOPPED", WIFSTOPPED(status), 0); 172 // 子进程应该能够匹配到对应的tag,不应该通过信号方式退出,这里检测子进程不会收到abort信号 173 EXPECT_EQ("fdsan_test_fork_subprocess_disabled WSTOPSIG", WSTOPSIG(status), 0); 174 kill(pid, SIGCONT); 175 break; 176 } 177 } 178 return; 179} 180 181int main() 182{ 183 fdsan_test_get_tag_value(); 184 fdsan_test_overflow(); 185 fdsan_test_vfork(); 186 fdsan_test_fatal_level(); 187 fdsan_test_fork_subprocess_disabled(); 188 fdsan_test_internal_fopen_succeed(); 189 return t_status; 190} 191