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
signal_handler_abort(int signum)34 void signal_handler_abort(int signum)
35 {
36 kill(getpid(), SIGSTOP);
37 }
38
signal_handler_abort1(int signum)39 void signal_handler_abort1(int signum)
40 {
41 exit(signum);
42 }
43
fdsan_test_get_tag_value()44 void 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
fdsan_test_overflow()53 void 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
fdsan_test_vfork()68 void 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
fdsan_test_fatal_level()87 void 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
CreateFile()121 bool 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
fdsan_test_internal_fopen_succeed()139 void 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
main()181 int 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