From f84d2aebd4d295f08c50b88ed4452f6c9b6605e6 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 2 Jun 2020 04:20:21 +0200 Subject: Reject i386 and x32 applications (not yet supported) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 1 + arch-x86-64.h | 29 +++++++++++++++++++++++++++++ common.h | 16 ++++++++++++---- process.c | 22 +++++++++++----------- sctrace.c | 42 +++++++++++++++++++++++++++++------------- tests/.gitignore | 3 ++- tests/Makefile | 54 ++++++++++++++++++++++++++++++------------------------ tests/fork.c | 4 +++- tests/signal.c | 4 +++- 9 files changed, 120 insertions(+), 55 deletions(-) create mode 100644 arch-x86-64.h diff --git a/Makefile b/Makefile index 6687ce7..44c177b 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ OBJ =\ util.o HDR =\ + arch-x86-64.h\ arg.h\ common.h\ list-errnos.h\ diff --git a/arch-x86-64.h b/arch-x86-64.h new file mode 100644 index 0000000..044b73f --- /dev/null +++ b/arch-x86-64.h @@ -0,0 +1,29 @@ +struct i386_user_regs_struct +{ + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t xds; + uint32_t xes; + uint32_t xfs; + uint32_t xgs; + uint32_t orig_eax; + uint32_t eip; + uint32_t xcs; + uint32_t eflags; + uint32_t esp; + uint32_t xss; +}; + +#define SYSCALL_NUM_REG orig_rax +#define SYSCALL_ARG1_REG rdi +#define SYSCALL_ARG2_REG rsi +#define SYSCALL_ARG3_REG rdx +#define SYSCALL_ARG4_REG r10 +#define SYSCALL_ARG5_REG r8 +#define SYSCALL_ARG6_REG r9 +#define SYSCALL_RET_REG rax diff --git a/common.h b/common.h index 458d4f9..0c9ff8f 100644 --- a/common.h +++ b/common.h @@ -1,9 +1,7 @@ /* See LICENSE file for copyright and license details. */ -#if !defined __x86_64__ || defined __IPL32__ -# error "This program is only implemented for x86-64" -#endif - +#include #include +#include /* After */ #include #include #include @@ -19,6 +17,16 @@ #include #include +#if defined(__x86_64__) && !defined(__IPL32__) +# include "arch-x86-64.h" +#else +# error "This program is only implemented for x86-64" +#endif + +#if !defined(__linux__) +# error "This program is only implemented for Linux" +#endif + #include "arg.h" #include "list-errnos.h" #include "list-signums.h" diff --git a/process.c b/process.c index f979e21..117fd6a 100644 --- a/process.c +++ b/process.c @@ -9,7 +9,7 @@ static struct process tail; void init_process_list(void) { - head.next = &tail; + head.next = &tail; tail.prev = &head; } @@ -17,25 +17,25 @@ init_process_list(void) struct process * find_process(pid_t pid) { - struct process *p; - for (p = head.next; p->next; p = p->next) - if (p->pid == pid) - return p; - return NULL; + struct process *p; + for (p = head.next; p->next; p = p->next) + if (p->pid == pid) + return p; + return NULL; } struct process * add_process(pid_t pid, unsigned long int trace_options) { - struct process *proc; + struct process *proc; int status; - proc = calloc(1, sizeof(*proc)); + proc = calloc(1, sizeof(*proc)); if (!proc) - eprintf("calloc: %s\n"); - proc->pid = pid; - proc->next = &tail; + eprintf("calloc: %s\n"); + proc->pid = pid; + proc->next = &tail; proc->prev = tail.prev; proc->prev->next = proc; tail.prev = proc; diff --git a/sctrace.c b/sctrace.c index 55ce808..9bab8ff 100644 --- a/sctrace.c +++ b/sctrace.c @@ -18,19 +18,35 @@ static void handle_syscall(struct process *proc) { struct user_regs_struct regs; + struct iovec iov = { + .iov_base = ®s, + .iov_len = sizeof(regs), + }; switch ((int)proc->state) { default: /* Get system call arguments */ if (ptrace(PTRACE_GETREGS, proc->pid, NULL, ®s)) eprintf("ptrace PTRACE_GETREGS %ju NULL :", (uintmax_t)proc->pid); - proc->scall = regs.orig_rax; - proc->args[0] = regs.rdi; - proc->args[1] = regs.rsi; - proc->args[2] = regs.rdx; - proc->args[3] = regs.r10; - proc->args[4] = regs.r8; - proc->args[5] = regs.r9; + proc->scall = regs.SYSCALL_NUM_REG; + proc->args[0] = regs.SYSCALL_ARG1_REG; + proc->args[1] = regs.SYSCALL_ARG2_REG; + proc->args[2] = regs.SYSCALL_ARG3_REG; + proc->args[3] = regs.SYSCALL_ARG4_REG; + proc->args[4] = regs.SYSCALL_ARG5_REG; + proc->args[5] = regs.SYSCALL_ARG6_REG; + + /* Check architecture */ + if (ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iov)) { + eprintf("ptrace PTRACE_GETREGSET %ju NT_PRSTATUS {.iov_base=, .iov_len=%zu}:", + (uintmax_t)proc->pid, sizeof(regs)); + } else if (iov.iov_len != sizeof(regs)) { + tprintf(proc, "Process is running as i386, this is not yet supported\n"); + exit(1); + } else if (proc->scall & __X32_SYSCALL_BIT) { + tprintf(proc, "Process is running as x32, this is not yet supported\n"); + exit(1); + } /* Print system call */ print_systemcall(proc); @@ -51,9 +67,9 @@ handle_syscall(struct process *proc) /* Get or set return */ if (proc->state == Syscall) { - proc->ret = regs.rax; + proc->ret = regs.SYSCALL_RET_REG; } else { - regs.rax = proc->ret; + regs.SYSCALL_RET_REG = proc->ret; if (ptrace(PTRACE_SETREGS, proc->pid, NULL, ®s)) eprintf("ptrace PTRACE_SETREGS %ju NULL :", (uintmax_t)proc->pid); if (ptrace(PTRACE_SYSCALL, proc->pid, NULL, 0)) @@ -104,7 +120,7 @@ handle_event(struct process *proc, int status) case PTRACE_EVENT_VFORK: tprintf(proc, "\nProcess stopped by vfork until child exits or exec(2)s\n"); - /* fall thought */ + /* fall through */ case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: if (ptrace(PTRACE_GETEVENTMSG, proc->pid, NULL, &event)) @@ -259,11 +275,11 @@ main(int argc, char **argv) exit_code = status; if (WIFEXITED(status)) { tprintf(proc, "\nProcess exited with value %i%s\n", WEXITSTATUS(status), - WCOREDUMP(status) ? ", core dumped" : ""); + WCOREDUMP(status) ? ", core dumped" : ""); } else { tprintf(proc, "\nProcess terminated by signal %i (%s: %s)%s\n", WTERMSIG(status), - get_signum_name(WTERMSIG(status)), strsignal(WTERMSIG(status)), - WCOREDUMP(status) ? ", core dumped" : ""); + get_signum_name(WTERMSIG(status)), strsignal(WTERMSIG(status)), + WCOREDUMP(status) ? ", core dumped" : ""); } proc2 = proc->continue_on_exit; remove_process(proc); diff --git a/tests/.gitignore b/tests/.gitignore index a8d6b6c..d961f3e 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1 +1,2 @@ -*.t +*.32 +*.64 diff --git a/tests/Makefile b/tests/Makefile index db5caa7..6e0d8da 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,32 +1,38 @@ .POSIX: -BIN =\ - abort.t\ - cont.t\ - exec.t\ - exit.t\ - fork.t\ - fork-stop.t\ - kill.t\ - raise.t\ - siginfo.t\ - signal.t\ - stop.t\ - threads.t\ - tstp.t\ - vfork.t\ - vfork-exec.t - -all: $(BIN) -$(BIN): $(@:.t=.c) - -.c.t: - $(CC) -static -pthread -Og -g -o $@ $< -D_XOPEN_SOURCE=700 +BIN_64 =\ + abort.64\ + cont.64\ + exec.64\ + exit.64\ + fork.64\ + fork-stop.64\ + kill.64\ + raise.64\ + siginfo.64\ + signal.64\ + stop.64\ + threads.64\ + tstp.64\ + vfork.64\ + vfork-exec.64 + +BIN_32 = $(BIN_64:.64=.32) + +all: $(BIN_64) $(BIN_32) +$(BIN_64): $(@:.64=.c) +$(BIN_32): $(@:.32=.c) + +.c.64: + $(CC) -static -pthread -Og -g -o $@ $< -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE + +.c.32: + $(CC) -m32 -static -pthread -Og -g -o $@ $< -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE clean: - -rm -f -- $(BIN) + -rm -f -- $(BIN_64) $(BIN_32) .SUFFIXES: -.SUFFIXES: .t .c +.SUFFIXES: .32 .64 .c .PHONY: all clean diff --git a/tests/fork.c b/tests/fork.c index 7bbc4c2..993e0d4 100644 --- a/tests/fork.c +++ b/tests/fork.c @@ -1,15 +1,17 @@ +#include #include int main(void) { + struct timespec ts = {0, 100000000L}; switch (fork()) { case -1: return -1; case 0: return 2; default: - usleep(100000U); + nanosleep(&ts, NULL); return 1; } } diff --git a/tests/signal.c b/tests/signal.c index e4862cd..a68edcd 100644 --- a/tests/signal.c +++ b/tests/signal.c @@ -1,4 +1,5 @@ #include +#include #include static void @@ -10,9 +11,10 @@ interrupt() int main(void) { + struct timespec ts = {0, 100000000L}; signal(SIGINT, interrupt); kill(getpid(), SIGINT); - usleep(100000U); + nanosleep(&ts, NULL); write(-1, "qwerty\n", 7); return 0; } -- cgit v1.2.3-70-g09d2