Skip to content

Commit 41b35b6

Browse files
committed
SystemSan: add AArch64 support
1 parent c9485cb commit 41b35b6

File tree

4 files changed

+56
-21
lines changed

4 files changed

+56
-21
lines changed

infra/experimental/SystemSan/SystemSan.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <unistd.h>
2929

3030
/* Linux */
31+
#include <linux/elf.h>
3132
#include <sys/ptrace.h>
3233
#include <syscall.h>
3334
#include <fcntl.h>
@@ -40,6 +41,7 @@
4041
#include <string>
4142
#include <vector>
4243

44+
#include "arch.h"
4345
#include "inspect_utils.h"
4446
#include "inspect_dns.h"
4547

@@ -169,7 +171,7 @@ std::string read_string(pid_t pid, unsigned long reg, unsigned long length) {
169171

170172
void inspect_for_injection(pid_t pid, const user_regs_struct &regs) {
171173
// Inspect a PID's registers for the sign of shell injection.
172-
std::string path = read_string(pid, regs.rdi, kTripWire.length());
174+
std::string path = read_string(pid, REGS_ARG1, kTripWire.length());
173175
if (!path.length()) {
174176
return;
175177
}
@@ -181,7 +183,7 @@ void inspect_for_injection(pid_t pid, const user_regs_struct &regs) {
181183

182184
std::string get_pathname(pid_t pid, const user_regs_struct &regs) {
183185
// Parse the pathname from the memory specified in the RDI register.
184-
std::string pathname = read_string(pid, regs.rdi, kShellPathnameLength);
186+
std::string pathname = read_string(pid, REGS_ARG1, kShellPathnameLength);
185187
debug_log("Pathname is %s (len %lu)\n", pathname.c_str(), pathname.length());
186188
return pathname;
187189
}
@@ -262,7 +264,7 @@ void match_error_pattern(std::string buffer, std::string shell, pid_t pid) {
262264

263265
void inspect_for_corruption(pid_t pid, const user_regs_struct &regs) {
264266
// Inspect a PID's registers for shell corruption.
265-
std::string buffer = read_string(pid, regs.rsi, regs.rdx);
267+
std::string buffer = read_string(pid, REGS_ARG2, REGS_ARG3);
266268
debug_log("Write buffer: %s\n", buffer.c_str());
267269
match_error_pattern(buffer, g_shell_pids[pid], pid);
268270
}
@@ -297,12 +299,12 @@ bool has_unprintable(const std::string &value) {
297299

298300
void inspect_for_arbitrary_file_open(pid_t pid, const user_regs_struct &regs) {
299301
// Inspect a PID's register for the sign of arbitrary file open.
300-
std::string path = read_string(pid, regs.rsi, kRootDirMaxLength);
302+
std::string path = read_string(pid, REGS_ARG2, kRootDirMaxLength);
301303
if (!path.length()) {
302304
return;
303305
}
304306
if (path.substr(0, kFzAbsoluteDirectory.length()) == kFzAbsoluteDirectory) {
305-
log_file_open(path, regs.rdx, pid);
307+
log_file_open(path, REGS_ARG3, pid);
306308
return;
307309
}
308310
if (path[0] == '/' && path.length() > 1) {
@@ -314,7 +316,7 @@ void inspect_for_arbitrary_file_open(pid_t pid, const user_regs_struct &regs) {
314316
if (has_unprintable(path_absolute_topdir)) {
315317
struct stat dirstat;
316318
if (stat(path_absolute_topdir.c_str(), &dirstat) != 0) {
317-
log_file_open(path, regs.rdx, pid);
319+
log_file_open(path, REGS_ARG3, pid);
318320
}
319321
}
320322
}
@@ -399,13 +401,17 @@ int trace(std::map<pid_t, Tracee> pids) {
399401

400402
if (is_syscall) {
401403
user_regs_struct regs;
402-
if (ptrace(PTRACE_GETREGS, pid, 0, &regs) == -1) {
403-
debug_log("ptrace(PTRACE_GETREGS, %d): %s", pid, strerror(errno));
404+
struct iovec iov {
405+
.iov_base = &regs,
406+
.iov_len = sizeof(struct user_regs_struct),
407+
};
408+
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov) == -1) {
409+
debug_log("ptrace(PTRACE_GETREGSET, %d): %s", pid, strerror(errno));
404410
continue;
405411
}
406412

407413
if (tracee.syscall_enter) {
408-
if (regs.orig_rax == __NR_execve) {
414+
if (REGS_SYSCALL == __NR_execve) {
409415
// This is a new process.
410416
auto parent = root_pids[pid];
411417
parent.ran_exec = true;
@@ -420,12 +426,12 @@ int trace(std::map<pid_t, Tracee> pids) {
420426

421427
inspect_dns_syscalls(pid, regs);
422428

423-
if (regs.orig_rax == __NR_openat) {
429+
if (REGS_SYSCALL == __NR_openat) {
424430
// TODO(metzman): Re-enable this once we have config/flag support.
425431
// inspect_for_arbitrary_file_open(pid, regs);
426432
}
427433

428-
if (regs.orig_rax == __NR_write &&
434+
if (REGS_SYSCALL == __NR_write &&
429435
g_shell_pids.find(pid) != g_shell_pids.end()) {
430436
debug_log("Inspecting the `write` buffer of shell process %d.",
431437
pid);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#if defined(__aarch64__)
18+
#define REGS_SYSCALL regs.regs[8]
19+
#define REGS_ARG1 regs.regs[0]
20+
#define REGS_ARG2 regs.regs[1]
21+
#define REGS_ARG3 regs.regs[2]
22+
#elif defined(__x86_64__)
23+
#define REGS_SYSCALL regs.orig_rax
24+
#define REGS_ARG1 regs.rdi
25+
#define REGS_ARG2 regs.rsi
26+
#define REGS_ARG3 regs.rdx
27+
#endif

infra/experimental/SystemSan/inspect_dns.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <iostream>
2828

29+
#include "arch.h"
2930
#include "inspect_utils.h"
3031

3132

@@ -38,12 +39,12 @@ const size_t kDnsHeaderLen = 12;
3839

3940

4041
void inspect_for_arbitrary_dns_connect(pid_t pid, const user_regs_struct &regs) {
41-
auto memory = read_memory(pid, regs.rsi, sizeof(struct sockaddr_in));
42+
auto memory = read_memory(pid, REGS_ARG2, sizeof(struct sockaddr_in));
4243
if (memory.size()) {
4344
struct sockaddr_in * sa = reinterpret_cast<struct sockaddr_in *>(memory.data());
4445
if (sa->sin_family == AF_INET && htons(sa->sin_port) == 53) {
4546
// save file descriptor for later sendmmsg
46-
kFdDns = regs.rdi;
47+
kFdDns = REGS_ARG1;
4748
}
4849
}
4950
}
@@ -168,8 +169,8 @@ void inspect_for_arbitrary_dns_pkt(std::vector<std::byte> data, pid_t pid) {
168169
}
169170

170171
void inspect_for_arbitrary_dns_fdbuffer(pid_t pid, const user_regs_struct &regs) {
171-
if (kFdDns > 0 && kFdDns == (int) regs.rdi) {
172-
auto memory = read_memory(pid, regs.rsi, regs.rdx);
172+
if (kFdDns > 0 && kFdDns == (int) REGS_ARG1) {
173+
auto memory = read_memory(pid, REGS_ARG2, REGS_ARG3);
173174
if (memory.size()) {
174175
inspect_for_arbitrary_dns_pkt(memory, pid);
175176
}
@@ -188,8 +189,8 @@ void inspect_for_arbitrary_dns_iov(pid_t pid, unsigned long iov) {
188189
}
189190

190191
void inspect_for_arbitrary_dns_sendmsg(pid_t pid, const user_regs_struct &regs) {
191-
if (kFdDns > 0 && kFdDns == (int) regs.rdi) {
192-
auto memory = read_memory(pid, regs.rsi, sizeof(struct msghdr));
192+
if (kFdDns > 0 && kFdDns == (int) REGS_ARG1) {
193+
auto memory = read_memory(pid, REGS_ARG2, sizeof(struct msghdr));
193194
if (memory.size()) {
194195
struct msghdr * msg = reinterpret_cast<struct msghdr *>(memory.data());
195196
if (msg->msg_iovlen == 1) {
@@ -200,8 +201,8 @@ void inspect_for_arbitrary_dns_sendmsg(pid_t pid, const user_regs_struct &regs)
200201
}
201202

202203
void inspect_for_arbitrary_dns_sendmmsg(pid_t pid, const user_regs_struct &regs) {
203-
if (kFdDns > 0 && kFdDns == (int) regs.rdi) {
204-
auto memory = read_memory(pid, regs.rsi, sizeof(struct mmsghdr));
204+
if (kFdDns > 0 && kFdDns == (int) REGS_ARG1) {
205+
auto memory = read_memory(pid, REGS_ARG2, sizeof(struct mmsghdr));
205206
if (memory.size()) {
206207
struct mmsghdr * msg = reinterpret_cast<struct mmsghdr *>(memory.data());
207208
if (msg->msg_hdr.msg_iovlen == 1) {
@@ -212,12 +213,12 @@ void inspect_for_arbitrary_dns_sendmmsg(pid_t pid, const user_regs_struct &regs)
212213
}
213214

214215
void inspect_dns_syscalls(pid_t pid, const user_regs_struct &regs) {
215-
switch (regs.orig_rax) {
216+
switch (REGS_SYSCALL) {
216217
case __NR_connect:
217218
inspect_for_arbitrary_dns_connect(pid, regs);
218219
break;
219220
case __NR_close:
220-
if (kFdDns > 0 && kFdDns == (int) regs.rdi) {
221+
if (kFdDns > 0 && kFdDns == (int) REGS_ARG1) {
221222
// reset DNS file descriptor on close
222223
kFdDns = 0;
223224
}

infra/experimental/SystemSan/inspect_utils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <vector>
3030
#include <map>
3131

32+
#include "arch.h"
3233
#include "inspect_utils.h"
3334

3435
extern pid_t g_root_pid;

0 commit comments

Comments
 (0)