Skip to content

Commit 00be611

Browse files
committed
add C strace-grate
1 parent 5cf97e9 commit 00be611

File tree

3 files changed

+274
-0
lines changed

3 files changed

+274
-0
lines changed

examples/strace-grate/strace.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#include <stdio.h>
2+
#include <stdint.h>
3+
#include <stdlib.h>
4+
#include "strace.h"
5+
6+
// table for storing syscall handlers
7+
syscall_handler_t syscall_handler_table[MAX_SYSCALLS] = {0};
8+
9+
// defined syscall handlers
10+
//
11+
// args:
12+
// 1st: syscall name
13+
// 2nd: syscall number
14+
// 3rd - 8th: ARG type (ARG_INT || ARG_PTR || ARG_STR)
15+
//
16+
// NOTE: if unsure of ARG_TYPE follow:
17+
// https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
18+
//
19+
// defines handler for all syscalls supported by lind
20+
21+
DEFINE_HANDLER(read, 0, ARG_INT, ARG_PTR, ARG_INT)
22+
DEFINE_HANDLER(write, 1, ARG_INT, ARG_PTR, ARG_INT)
23+
DEFINE_HANDLER(open, 2, ARG_STR, ARG_INT, ARG_INT)
24+
DEFINE_HANDLER(close, 3, ARG_INT)
25+
DEFINE_HANDLER(stat, 4, ARG_STR, ARG_PTR)
26+
DEFINE_HANDLER(fstat, 5, ARG_INT, ARG_PTR)
27+
DEFINE_HANDLER(poll, 7, ARG_PTR, ARG_INT, ARG_INT)
28+
DEFINE_HANDLER(lseek, 8, ARG_INT, ARG_INT, ARG_INT)
29+
DEFINE_HANDLER(mmap, 9, ARG_PTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT)
30+
DEFINE_HANDLER(mprotect, 10, ARG_PTR, ARG_INT, ARG_INT)
31+
DEFINE_HANDLER(munmap, 11, ARG_PTR, ARG_INT)
32+
DEFINE_HANDLER(brk, 12, ARG_PTR)
33+
DEFINE_HANDLER(sigaction, 13, ARG_INT, ARG_PTR, ARG_PTR)
34+
DEFINE_HANDLER(sigprocmask, 14, ARG_INT, ARG_PTR, ARG_PTR)
35+
DEFINE_HANDLER(ioctl, 16, ARG_INT, ARG_INT, ARG_PTR)
36+
DEFINE_HANDLER(pread, 17, ARG_INT, ARG_PTR, ARG_INT, ARG_INT)
37+
DEFINE_HANDLER(pwrite, 18, ARG_INT, ARG_PTR, ARG_INT, ARG_INT)
38+
DEFINE_HANDLER(writev, 20, ARG_INT, ARG_PTR, ARG_INT)
39+
DEFINE_HANDLER(access, 21, ARG_STR, ARG_INT)
40+
DEFINE_HANDLER(pipe, 22, ARG_PTR)
41+
DEFINE_HANDLER(select, 23, ARG_INT, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR)
42+
DEFINE_HANDLER(sched_yield, 24)
43+
DEFINE_HANDLER(shmget, 29, ARG_INT, ARG_INT, ARG_INT)
44+
DEFINE_HANDLER(shmat, 30, ARG_INT, ARG_PTR, ARG_INT)
45+
DEFINE_HANDLER(shmctl, 31, ARG_INT, ARG_INT, ARG_PTR)
46+
DEFINE_HANDLER(dup, 32, ARG_INT)
47+
DEFINE_HANDLER(dup2, 33, ARG_INT, ARG_INT)
48+
DEFINE_HANDLER(nanosleep, 35, ARG_PTR, ARG_PTR)
49+
DEFINE_HANDLER(setitimer, 38, ARG_INT, ARG_PTR, ARG_PTR)
50+
DEFINE_HANDLER(getpid, 39)
51+
DEFINE_HANDLER(socket, 41, ARG_INT, ARG_INT, ARG_INT)
52+
DEFINE_HANDLER(connect, 42, ARG_INT, ARG_PTR, ARG_INT)
53+
DEFINE_HANDLER(accept, 43, ARG_INT, ARG_PTR, ARG_PTR)
54+
DEFINE_HANDLER(sendto, 44, ARG_INT, ARG_PTR, ARG_INT, ARG_INT, ARG_PTR, ARG_INT)
55+
DEFINE_HANDLER(recvfrom, 45, ARG_INT, ARG_PTR, ARG_INT, ARG_INT, ARG_PTR, ARG_PTR)
56+
DEFINE_HANDLER(shutdown, 48, ARG_INT, ARG_INT)
57+
DEFINE_HANDLER(bind, 49, ARG_INT, ARG_PTR, ARG_INT)
58+
DEFINE_HANDLER(listen, 50, ARG_INT, ARG_INT)
59+
DEFINE_HANDLER(getsockname, 51, ARG_INT, ARG_PTR, ARG_PTR)
60+
DEFINE_HANDLER(getpeername, 52, ARG_INT, ARG_PTR, ARG_PTR)
61+
DEFINE_HANDLER(socketpair, 53, ARG_INT, ARG_INT, ARG_INT, ARG_PTR)
62+
DEFINE_HANDLER(setsockopt, 54, ARG_INT, ARG_INT, ARG_INT, ARG_PTR, ARG_INT)
63+
DEFINE_HANDLER(getsockopt, 55, ARG_INT, ARG_INT, ARG_INT, ARG_PTR, ARG_PTR)
64+
//DEFINE_HANDLER(clone, 56, ARG_INT, ARG_PTR, ARG_PTR, ARG_PTR, ARG_PTR)
65+
DEFINE_HANDLER(fork, 57)
66+
//DEFINE_HANDLER(exec, 59, ARG_STR, ARG_PTR, ARG_PTR)
67+
DEFINE_HANDLER(exit, 60, ARG_INT)
68+
DEFINE_HANDLER(waitpid, 61, ARG_INT, ARG_PTR, ARG_INT)
69+
DEFINE_HANDLER(kill, 62, ARG_INT, ARG_INT)
70+
DEFINE_HANDLER(shmdt, 67, ARG_PTR)
71+
DEFINE_HANDLER(fcntl, 72, ARG_INT, ARG_INT, ARG_PTR)
72+
DEFINE_HANDLER(flock, 73, ARG_INT, ARG_INT)
73+
DEFINE_HANDLER(fsync, 74, ARG_INT)
74+
DEFINE_HANDLER(fdatasync, 75, ARG_INT)
75+
DEFINE_HANDLER(truncate, 76, ARG_STR, ARG_INT)
76+
DEFINE_HANDLER(ftruncate, 77, ARG_INT, ARG_INT)
77+
DEFINE_HANDLER(getdents, 78, ARG_INT, ARG_PTR, ARG_INT)
78+
DEFINE_HANDLER(getcwd, 79, ARG_PTR, ARG_INT)
79+
DEFINE_HANDLER(chdir, 80, ARG_STR)
80+
DEFINE_HANDLER(fchdir, 81, ARG_INT)
81+
DEFINE_HANDLER(rename, 82, ARG_STR, ARG_STR)
82+
DEFINE_HANDLER(mkdir, 83, ARG_STR, ARG_INT)
83+
DEFINE_HANDLER(rmdir, 84, ARG_STR)
84+
DEFINE_HANDLER(link, 86, ARG_STR, ARG_STR)
85+
DEFINE_HANDLER(unlink, 87, ARG_STR)
86+
DEFINE_HANDLER(readlink, 89, ARG_STR, ARG_PTR, ARG_INT)
87+
DEFINE_HANDLER(chmod, 90, ARG_STR, ARG_INT)
88+
DEFINE_HANDLER(fchmod, 91, ARG_INT, ARG_INT)
89+
DEFINE_HANDLER(getuid, 102)
90+
DEFINE_HANDLER(getgid, 104)
91+
DEFINE_HANDLER(geteuid, 107)
92+
DEFINE_HANDLER(getegid, 108)
93+
DEFINE_HANDLER(getppid, 110)
94+
DEFINE_HANDLER(statfs, 137, ARG_STR, ARG_PTR)
95+
DEFINE_HANDLER(fstatfs, 138, ARG_INT, ARG_PTR)
96+
DEFINE_HANDLER(gethostname, 170, ARG_PTR, ARG_INT)
97+
DEFINE_HANDLER(futex, 202, ARG_PTR, ARG_INT, ARG_INT, ARG_PTR, ARG_PTR, ARG_INT)
98+
DEFINE_HANDLER(epoll_create, 213, ARG_INT)
99+
DEFINE_HANDLER(clock_gettime, 228, ARG_INT, ARG_PTR)
100+
DEFINE_HANDLER(epoll_wait, 232, ARG_INT, ARG_PTR, ARG_INT, ARG_INT)
101+
DEFINE_HANDLER(epoll_ctl, 233, ARG_INT, ARG_INT, ARG_INT, ARG_PTR)
102+
DEFINE_HANDLER(unlinkat, 263, ARG_INT, ARG_STR, ARG_INT)
103+
DEFINE_HANDLER(readlinkat, 267, ARG_INT, ARG_STR, ARG_PTR, ARG_INT)
104+
DEFINE_HANDLER(sync_file_range, 277, ARG_INT, ARG_INT, ARG_INT, ARG_INT)
105+
DEFINE_HANDLER(epoll_create1, 291, ARG_INT)
106+
DEFINE_HANDLER(dup3, 292, ARG_INT, ARG_INT, ARG_INT)
107+
DEFINE_HANDLER(pipe2, 293, ARG_PTR, ARG_INT)
108+
DEFINE_HANDLER(getrandom, 318, ARG_PTR, ARG_INT, ARG_INT)
109+
110+
// dispatcher function
111+
int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t cageid,
112+
uint64_t arg1, uint64_t arg1cage,
113+
uint64_t arg2, uint64_t arg2cage,
114+
uint64_t arg3, uint64_t arg3cage,
115+
uint64_t arg4, uint64_t arg4cage,
116+
uint64_t arg5, uint64_t arg5cage,
117+
uint64_t arg6, uint64_t arg6cage) {
118+
119+
if (fn_ptr_uint == 0) {
120+
return -1;
121+
}
122+
123+
syscall_handler_t fn = (syscall_handler_t)(uintptr_t)fn_ptr_uint;
124+
125+
return fn(cageid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage,
126+
arg4, arg4cage, arg5, arg5cage, arg6, arg6cage);
127+
}

examples/strace-grate/strace.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#ifndef STRACE_H
2+
#define STRACE_H
3+
4+
#include <stdint.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <unistd.h>
8+
#include <lind_syscall.h>
9+
10+
#define ARG_INT 0
11+
#define ARG_STR 1
12+
#define ARG_PTR 2
13+
#define MAX_SYSCALLS 334
14+
15+
extern int tracing_enabled;
16+
17+
// function ptr for storing syscall handlers
18+
typedef int (*syscall_handler_t)(uint64_t, uint64_t, uint64_t, uint64_t,
19+
uint64_t, uint64_t, uint64_t, uint64_t,
20+
uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
21+
22+
// table for storing syscall handlers
23+
extern syscall_handler_t syscall_handler_table[MAX_SYSCALLS];
24+
25+
// macro for defining syscall handlers dynamically
26+
#define DEFINE_HANDLER(name, num, ...) \
27+
/* function defination for syscall handler */ \
28+
int name##_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, \
29+
uint64_t arg2, uint64_t arg2cage, \
30+
uint64_t arg3, uint64_t arg3cage, \
31+
uint64_t arg4, uint64_t arg4cage, \
32+
uint64_t arg5, uint64_t arg5cage, \
33+
uint64_t arg6, uint64_t arg6cage) { \
34+
\
35+
int thiscage = getpid(); \
36+
int types[] = {__VA_ARGS__}; \
37+
int argsnum = sizeof(types) / sizeof(int); \
38+
uint64_t args[] = {arg1, arg2, arg3, arg4, arg5, arg6}; \
39+
uint64_t argcages[] = {arg1cage, arg2cage, arg3cage, arg4cage, \
40+
arg5cage, arg6cage}; \
41+
\
42+
char log_buffer[1024]; \
43+
int offset = 0; \
44+
\
45+
/* log buffer to print syscall with args and ret val */ \
46+
offset += snprintf(log_buffer + offset, 1024 - offset, "%s(", #name); \
47+
\
48+
for (int i = 0; i < argsnum; i++) { \
49+
if (i > 0) \
50+
offset += snprintf(log_buffer + offset, 1024 - offset, ", "); \
51+
\
52+
if (types[i] == ARG_STR && args[i] != 0) { \
53+
char *buf = malloc(256); \
54+
if (buf) { \
55+
copy_data_between_cages(thiscage, argcages[i], \
56+
args[i], argcages[i], \
57+
(uint64_t)buf, thiscage, \
58+
256, 1); \
59+
offset += snprintf(log_buffer + offset, 1024 - offset, \
60+
"\"%s\"", buf); \
61+
free(buf); \
62+
} else { \
63+
offset += snprintf(log_buffer + offset, 1024 - offset, \
64+
"0x%lx", (unsigned long)args[i]); \
65+
} \
66+
} else if (types[i] == ARG_PTR || args[i] > 0xFFFFFF || args[i] == 0) { \
67+
offset += snprintf(log_buffer + offset, 1024 - offset, \
68+
"0x%lx", (unsigned long)args[i]); \
69+
} else { \
70+
offset += snprintf(log_buffer + offset, 1024 - offset, \
71+
"%ld", (long)args[i]); \
72+
} \
73+
} \
74+
offset += snprintf(log_buffer + offset, 1024 - offset, ")"); \
75+
\
76+
/* flush log buffer before exit */ \
77+
int exit_call = (num == 60); \
78+
if (exit_call) { \
79+
fprintf(stderr, "%s\n", log_buffer); \
80+
fflush(stderr); \
81+
} \
82+
\
83+
/* forward interposed syscall */ \
84+
int ret = make_threei_call(num, 0, \
85+
thiscage, arg1cage, \
86+
arg1, arg1cage, arg2, arg2cage, \
87+
arg3, arg3cage, arg4, arg4cage, \
88+
arg5, arg5cage, arg6, arg6cage, 0); \
89+
\
90+
if (!exit_call) { \
91+
fprintf(stderr, "%s = %d\n", log_buffer, ret); \
92+
} else { \
93+
fprintf(stderr, "%s [failed] = %d\n", log_buffer, ret); \
94+
} \
95+
\
96+
/* printing log buffer after return to ensure proper printing */ \
97+
/*fprintf(stderr, "%s = %d\n", log_buffer, ret);*/ \
98+
return ret; \
99+
} \
100+
\
101+
/* constructor to store handler address in the table */ \
102+
__attribute__((constructor)) static void register_##name() { \
103+
syscall_handler_table[num] = &name##_grate; \
104+
}
105+
106+
#endif
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <sys/wait.h>
4+
#include <unistd.h>
5+
#include "strace.h"
6+
7+
int main(int argc, char *argv[]) {
8+
if (argc < 2) {
9+
fprintf(stderr, "Usage: %s <cage_binary> [args...]\n", argv[0]);
10+
exit(EXIT_FAILURE);
11+
}
12+
13+
int grateid = getpid();
14+
pid_t pid = fork();
15+
16+
if (pid < 0) {
17+
perror("fork failed");
18+
exit(EXIT_FAILURE);
19+
} else if (pid == 0) {
20+
int cageid = getpid();
21+
22+
// loop to register syscall handlers
23+
for (int i = 0; i < MAX_SYSCALLS; i++) {
24+
if (syscall_handler_table[i] != NULL) {
25+
uint64_t fn_ptr = (uint64_t)(uintptr_t)syscall_handler_table[i];
26+
register_handler(cageid, i, 1, grateid, fn_ptr);
27+
//fprintf(stderr, "[Grate] Registered handler for syscall %d at 0x%llx\n", i, fn_ptr);
28+
}
29+
}
30+
if (execv(argv[1], &argv[1]) == -1) {
31+
perror("execv failed");
32+
exit(EXIT_FAILURE);
33+
}
34+
}
35+
36+
int status;
37+
while (wait(&status) > 0) {
38+
fprintf(stderr, "[Grate] process terminated, status: %d\n", status);
39+
}
40+
return 0;
41+
}

0 commit comments

Comments
 (0)