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
26 #include <unordered_map>
27
28 #include "functionalext.h"
29
30 #define DEV_NULL_PATH "/dev/null"
31
signal_handler_abort(int signum)32 void signal_handler_abort(int signum)
33 {
34 kill(getpid(), SIGSTOP);
35 }
36
fdsan_test_get_tag_value()37 void fdsan_test_get_tag_value()
38 {
39 int fd = open(DEV_NULL_PATH, O_RDONLY);
40 uint64_t tag = fdsan_get_owner_tag(fd);
41 EXPECT_EQ("fdsan_test_get_tag_value", strcmp(fdsan_get_tag_type(tag), "native object of unknown type"), 0);
42 EXPECT_EQ("fdsan_test_get_tag_value", fdsan_get_tag_value(tag), 0);
43 EXPECT_EQ("fdsan_test_get_tag_value", close(fd), 0);
44 }
45
fdsan_test_overflow()46 void fdsan_test_overflow()
47 {
48 std::unordered_map<int, uint64_t> fds;
49 for (int i = 0; i < 4096; ++i) {
50 int fd = open(DEV_NULL_PATH, O_RDONLY);
51 auto tag = 0xdead00000000ULL | i;
52 fdsan_exchange_owner_tag(fd, 0, tag);
53 fds[fd] = tag;
54 }
55
56 for (auto [fd, tag] : fds) {
57 EXPECT_EQ("fdsan_test_overflow", fdsan_close_with_tag(fd, tag), 0);
58 }
59 }
60
fdsan_test_vfork()61 void fdsan_test_vfork()
62 {
63 int fd = open(DEV_NULL_PATH, O_RDONLY);
64
65 pid_t rc = vfork();
66 EXPECT_NE("fdsan_test_vfork", -1, rc);
67
68 if (rc == 0) {
69 close(fd);
70 _exit(0);
71 }
72
73 int status;
74 pid_t wait_result = waitpid(rc, &status, 0);
75 EXPECT_EQ("fdsan_test_vfork", wait_result, rc);
76 EXPECT_TRUE("fdsan_test_vfork", WIFEXITED(status));
77 EXPECT_EQ("fdsan_test_vfork", 0, WEXITSTATUS(status));
78 }
79
fdsan_test_fatal_level()80 void fdsan_test_fatal_level()
81 {
82 struct sigaction sigabrt = {
83 .sa_handler = signal_handler_abort,
84 };
85 sigaction(SIGABRT, &sigabrt, nullptr);
86
87 int status;
88 int pid = fork();
89 switch (pid) {
90 case -1: {
91 t_error("fork failed: %d\n", __LINE__);
92 break;
93 }
94 case 0: {
95 fdsan_set_error_level(FDSAN_ERROR_LEVEL_FATAL);
96 int fd = open(DEV_NULL_PATH, O_RDONLY);
97 uint64_t tag = 0xdead00000000ULL;
98 fdsan_exchange_owner_tag(fd, 0, tag);
99 fdsan_close_with_tag(fd, 0);
100 exit(0);
101 }
102 default: {
103 waitpid(pid, &status, WUNTRACED);
104 EXPECT_EQ("fdsan_test_fatal_level", WIFEXITED(status), 0);
105 EXPECT_EQ("fdsan_test_fatal_level", WIFSTOPPED(status), 1);
106 EXPECT_EQ("fdsan_test_fatal_level", WSTOPSIG(status), SIGSTOP);
107 kill(pid, SIGCONT);
108 break;
109 }
110 }
111 return;
112 }
113
main()114 int main()
115 {
116 fdsan_test_get_tag_value();
117 fdsan_test_overflow();
118 fdsan_test_vfork();
119 fdsan_test_fatal_level();
120 return t_status;
121 }
122