• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 #include <unordered_map>
28 
29 #include "functionalext.h"
30 
31 #define DEV_NULL_PATH "/dev/null"
32 const char *file_path = "/data/local/tmp/test.txt";
33 
34 extern "C" FILE *__fopen_rb_ca(const char *, FILE *, unsigned char *, size_t);
35 extern "C" int __fclose_ca(FILE *);
36 
signal_handler_abort(int signum)37 void signal_handler_abort(int signum)
38 {
39     kill(getpid(), SIGSTOP);
40 }
41 
signal_handler_abort1(int signum)42 void signal_handler_abort1(int signum)
43 {
44     exit(signum);
45 }
46 
fdsan_test_get_tag_value()47 void fdsan_test_get_tag_value()
48 {
49     int fd = open(DEV_NULL_PATH, O_RDONLY);
50     uint64_t tag = fdsan_get_owner_tag(fd);
51     EXPECT_EQ("fdsan_test_get_tag_value", strcmp(fdsan_get_tag_type(tag), "native object of unknown type"), 0);
52     EXPECT_EQ("fdsan_test_get_tag_value", fdsan_get_tag_value(tag), 0);
53     EXPECT_EQ("fdsan_test_get_tag_value", close(fd), 0);
54 }
55 
fdsan_test_overflow()56 void fdsan_test_overflow()
57 {
58     std::unordered_map<int, uint64_t> fds;
59     for (int i = 0; i < 4096; ++i) {
60         int fd = open(DEV_NULL_PATH, O_RDONLY);
61         auto tag = 0xdead00000000ULL | i;
62         fdsan_exchange_owner_tag(fd, 0, tag);
63         fds[fd] = tag;
64     }
65 
66     for (auto [fd, tag] : fds) {
67         EXPECT_EQ("fdsan_test_overflow", fdsan_close_with_tag(fd, tag), 0);
68     }
69 }
70 
fdsan_test_vfork()71 void fdsan_test_vfork()
72 {
73     int fd = open(DEV_NULL_PATH, O_RDONLY);
74 
75     pid_t rc = vfork();
76     EXPECT_NE("fdsan_test_vfork", -1, rc);
77 
78     if (rc == 0) {
79         close(fd);
80         _exit(0);
81     }
82 
83     int status;
84     pid_t wait_result = waitpid(rc, &status, 0);
85     EXPECT_EQ("fdsan_test_vfork", wait_result, rc);
86     EXPECT_TRUE("fdsan_test_vfork", WIFEXITED(status));
87     EXPECT_EQ("fdsan_test_vfork", 0, WEXITSTATUS(status));
88 }
89 
fdsan_test_fatal_level()90 void fdsan_test_fatal_level()
91 {
92     struct sigaction sigabrt = {
93         .sa_handler = signal_handler_abort,
94     };
95     sigaction(SIGABRT, &sigabrt, nullptr);
96 
97     int status;
98     int pid = fork();
99     switch (pid) {
100         case -1: {
101             t_error("fork failed: %d\n", __LINE__);
102             break;
103         }
104         case 0: {
105             fdsan_set_error_level(FDSAN_ERROR_LEVEL_FATAL);
106             int fd = open(DEV_NULL_PATH, O_RDONLY);
107             uint64_t tag = 0xdead00000000ULL;
108             fdsan_exchange_owner_tag(fd, 0, tag);
109             fdsan_close_with_tag(fd, 0);
110             exit(0);
111         }
112         default: {
113             waitpid(pid, &status, WUNTRACED);
114             EXPECT_EQ("fdsan_test_fatal_level", WIFEXITED(status), 0);
115             EXPECT_EQ("fdsan_test_fatal_level", WIFSTOPPED(status), 1);
116             EXPECT_EQ("fdsan_test_fatal_level", WSTOPSIG(status), SIGSTOP);
117             kill(pid, SIGCONT);
118             break;
119         }
120     }
121     return;
122 }
123 
CreateFile()124 bool CreateFile()
125 {
126     // 创建文件并打开文件描述符
127     int fd = open(file_path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
128     if (fd == -1) {
129         return false;
130     }
131 
132     // 关闭文件描述符
133     close(fd);
134     return true;
135 }
136 
137 
fdsan_test_fork_subprocess_disabled()138 void fdsan_test_fork_subprocess_disabled()
139 {
140     struct sigaction sigabrt = {
141         .sa_handler = signal_handler_abort,
142     };
143     sigaction(SIGABRT, &sigabrt, nullptr);
144     int status;
145     int pid = fork();
146     switch (pid) {
147         case -1: {
148             t_error("fork failed: %d\n", __LINE__);
149             break;
150         }
151         case 0: {
152             enum fdsan_error_level errorLevel = fdsan_get_error_level();
153             if (errorLevel != FDSAN_ERROR_LEVEL_DISABLED) {
154                 abort();
155             }
156             exit(0);
157         }
158         default: {
159             waitpid(pid, &status, WUNTRACED);
160             EXPECT_EQ("fdsan_test_fork_subprocess_disabled WIFEXITED", WIFEXITED(status), 1);
161             EXPECT_EQ("fdsan_test_fork_subprocess_disabled WIFSTOPPED", WIFSTOPPED(status), 0);
162             // 子进程的错误等级默认应该是disabled,这里检测子进程不会收到abort信号
163             EXPECT_EQ("fdsan_test_fork_subprocess_disabled WSTOPSIG", WSTOPSIG(status), 0);
164             kill(pid, SIGCONT);
165             break;
166         }
167     }
168     return;
169 }
170 
fdsan_test_internal_fopen_succeed()171 void fdsan_test_internal_fopen_succeed()
172 {
173     struct sigaction sigabrt = {
174         .sa_handler = signal_handler_abort,
175     };
176     sigaction(SIGABRT, &sigabrt, nullptr);
177     bool res = CreateFile();
178     if (!res) {
179         t_error("fdsan_test_internal_fopen create file failed");
180         return;
181     }
182     int status;
183     int pid = fork();
184     switch (pid) {
185         case -1: {
186             t_error("fork failed: %d\n", __LINE__);
187             break;
188         }
189         case 0: {
190             fdsan_set_error_level(FDSAN_ERROR_LEVEL_FATAL);
191             unsigned char str[1024];
192             FILE f;
193             FILE *ptr = __fopen_rb_ca(file_path, &f, str, sizeof(str));
194             if (ptr == nullptr) {
195                 t_error("fdsan_test_internal_fopen_succeed open file failed: ptr == NULL");
196             }
197             if (ptr) {
198                 __fclose_ca(ptr);
199             }
200             exit(0);
201         }
202         default: {
203             waitpid(pid, &status, WUNTRACED);
204             EXPECT_EQ("fdsan_test_internal_fopen_succeed WIFEXITED", WIFEXITED(status), 1);
205             EXPECT_EQ("fdsan_test_internal_fopen_succeed WIFSTOPPED", WIFSTOPPED(status), 0);
206             // 子进程应该能够匹配到对应的tag,不应该通过信号方式退出,这里检测子进程不会收到abort信号
207             EXPECT_EQ("fdsan_test_internal_fopen_succeed WSTOPSIG", WSTOPSIG(status), 0);
208             kill(pid, SIGCONT);
209             break;
210         }
211     }
212     return;
213 }
214 
main()215 int main()
216 {
217     fdsan_test_get_tag_value();
218     fdsan_test_overflow();
219     fdsan_test_vfork();
220     fdsan_test_fatal_level();
221     fdsan_test_fork_subprocess_disabled();
222     fdsan_test_internal_fopen_succeed();
223     return t_status;
224 }