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
23using namespace std;
24
25bool 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
47bool 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
85const 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
108const 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