1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | #define _POSIX_C_SOURCE 200809L |
5 | |
6 | #include <assert.h> |
7 | #include <inttypes.h> |
8 | #include <math.h> |
9 | #include <stdio.h> |
10 | #include <time.h> |
11 | #include <sys/syscall.h> |
12 | #include <sys/stat.h> |
13 | #include <sys/ptrace.h> |
14 | #include <sys/types.h> |
15 | #include <sys/wait.h> |
16 | /* For constants ORIG_EAX (32bit) OR ORIG_RAX(64bit) etc */ |
17 | #include <linux/unistd.h> |
18 | #include <linux/capability.h> |
19 | #include <linux/magic.h> |
20 | |
21 | #include "utils.h" |
22 | |
23 | using namespace std; |
24 | |
25 | bool has_effective_caps() |
26 | { |
27 | #if 0 |
28 | //TODO: SYS_capget not work! |
29 | struct NativeArch::cap_header header = {.version = |
30 | _LINUX_CAPABILITY_VERSION_3, |
31 | .pid = 0 }; |
32 | struct NativeArch::cap_data data[_LINUX_CAPABILITY_U32S_3]; |
33 | if (syscall(SYS_capget, &header, data) != 0) { |
34 | assert(0 && "FAILED to read capabilities" ); |
35 | } |
36 | for (int i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) { |
37 | if ((data[i].effective & (uint32_t)caps) != (uint32_t)caps) { |
38 | return false; |
39 | } |
40 | caps >>= 32; |
41 | } |
42 | #endif |
43 | |
44 | return true; |
45 | } |
46 | |
47 | bool ensure_dir(const string& dir, const char* dir_type, mode_t mode) |
48 | { |
49 | string d = dir; |
50 | while (!d.empty() && d[d.length() - 1] == '/') { |
51 | d = d.substr(0, d.length() - 1); |
52 | } |
53 | |
54 | struct stat st; |
55 | if (0 > stat(d.c_str(), &st)) { |
56 | if (errno != ENOENT) { |
57 | return false; |
58 | } |
59 | |
60 | size_t last_slash = d.find_last_of('/'); |
61 | if (last_slash == string::npos || last_slash == 0) { |
62 | return false; |
63 | } |
64 | ensure_dir(d.substr(0, last_slash), dir_type, mode); |
65 | |
66 | // Allow for a race condition where someone else creates the directory |
67 | if (0 > mkdir(d.c_str(), mode) && errno != EEXIST) { |
68 | return false; |
69 | } |
70 | if (0 > stat(d.c_str(), &st)) { |
71 | return false; |
72 | } |
73 | } |
74 | |
75 | if (!(S_IFDIR & st.st_mode)) { |
76 | return false; |
77 | } |
78 | if (access(d.c_str(), W_OK)) { |
79 | return false; |
80 | } |
81 | |
82 | return true; |
83 | } |
84 | |
85 | const char* tmp_dir() |
86 | { |
87 | const char* dir = getenv("RR_TMPDIR" ); |
88 | if (dir) { |
89 | if (ensure_dir(string(dir), "temporary file directory (RR_TMPDIR)" , S_IRWXU)) |
90 | return dir; |
91 | } |
92 | dir = getenv("TMPDIR" ); |
93 | if (dir) { |
94 | if (ensure_dir(string(dir), "temporary file directory (TMPDIR)" , S_IRWXU)) |
95 | return dir; |
96 | } |
97 | // Don't try to create "/tmp", that probably won't work well. |
98 | if (access("/tmp" , W_OK)) { |
99 | return nullptr; |
100 | } |
101 | return "/tmp" ; |
102 | } |
103 | |
104 | #define CASE(_id) \ |
105 | case _id: \ |
106 | return #_id; |
107 | |
108 | const char* ptrace_cmd_name(int request) |
109 | { |
110 | switch (request) { |
111 | CASE(PTRACE_TRACEME); |
112 | CASE(PTRACE_PEEKTEXT); |
113 | CASE(PTRACE_PEEKDATA); |
114 | CASE(PTRACE_PEEKUSER); |
115 | CASE(PTRACE_POKETEXT); |
116 | CASE(PTRACE_POKEDATA); |
117 | CASE(PTRACE_POKEUSER); |
118 | CASE(PTRACE_CONT); |
119 | CASE(PTRACE_KILL); |
120 | CASE(PTRACE_SINGLESTEP); |
121 | CASE(PTRACE_ATTACH); |
122 | CASE(PTRACE_DETACH); |
123 | |
124 | #if !defined(__aarch64__) |
125 | CASE(PTRACE_GETREGS); |
126 | CASE(PTRACE_SETREGS); |
127 | CASE(PTRACE_GETFPREGS); |
128 | CASE(PTRACE_SETFPREGS); |
129 | CASE(PTRACE_GETFPXREGS); |
130 | CASE(PTRACE_SETFPXREGS); |
131 | #endif |
132 | |
133 | CASE(PTRACE_SYSCALL); |
134 | CASE(PTRACE_SETOPTIONS); |
135 | CASE(PTRACE_GETEVENTMSG); |
136 | CASE(PTRACE_GETSIGINFO); |
137 | CASE(PTRACE_SETSIGINFO); |
138 | CASE(PTRACE_GETREGSET); |
139 | CASE(PTRACE_SETREGSET); |
140 | CASE(PTRACE_SEIZE); |
141 | CASE(PTRACE_INTERRUPT); |
142 | CASE(PTRACE_LISTEN); |
143 | CASE(PTRACE_PEEKSIGINFO); |
144 | #ifndef KYLIN_MIPS64 |
145 | CASE(PTRACE_GETSIGMASK); |
146 | CASE(PTRACE_SETSIGMASK); |
147 | CASE(PTRACE_SECCOMP_GET_FILTER); |
148 | #endif |
149 | |
150 | default: { |
151 | static char buf[100]; |
152 | sprintf(buf, "(0x%x)" , request); |
153 | return (buf); |
154 | } |
155 | } |
156 | } |
157 | |
158 | |