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