From 8d2b3f8187d7a3732c0559ec56b13b4b75fcbe6f Mon Sep 17 00:00:00 2001 From: Alexis Ballier Date: Mon, 26 Apr 2010 20:38:52 +0200 Subject: [PATCH] Detect and use libkvm. This gives support for grabbing the command line that triggered a violation on FreeBSD. Also, check for struct reg to avoid #erroring for nothing; we do not have ptrace support in sandbox (yet). --- configure.ac | 16 +++++++++++++++- headers.h | 9 +++++++++ libsandbox/Makefile.am | 2 +- libsandbox/libsandbox.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- localdecls.h | 2 ++ 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 86b2c3f..524ce1c 100644 --- a/configure.ac +++ b/configure.ac @@ -74,6 +74,7 @@ AC_CHECK_HEADERS_ONCE([ \ execinfo.h \ fcntl.h \ grp.h \ + kvm.h \ libgen.h \ limits.h \ memory.h \ @@ -99,12 +100,14 @@ AC_CHECK_HEADERS_ONCE([ \ sys/reg.h \ sys/stat.h \ sys/syscall.h \ + sys/sysctl.h \ sys/time.h \ sys/types.h \ sys/user.h \ sys/wait.h \ asm/ptrace.h \ linux/ptrace.h \ + machine/reg.h \ ]) dnl Checks for typedefs, structures, and compiler characteristics. @@ -119,7 +122,7 @@ AC_CHECK_TYPES([sighandler_t, sig_t, __sighandler_t],,,[#include ]) save_CPPFLAGS=$CPPFLAGS CPPFLAGS="-I$srcdir $CPPFLAGS" -AC_CHECK_TYPES([struct user_regs_struct, struct pt_regs],,,[#include "headers.h"]) +AC_CHECK_TYPES([struct user_regs_struct, struct pt_regs, struct reg],,,[#include "headers.h"]) CPPFLAGS=$save_CPPFLAGS dnl Checks for library functions. @@ -180,6 +183,17 @@ AC_CHECK_LIB([sigsegv], [stackoverflow_install_handler], [HAVE_LIBSIGSEGV=false]) AM_CONDITIONAL(HAVE_LIBSIGSEGV, $HAVE_LIBSIGSEGV) +have_libkvm="no" +AC_CHECK_LIB([kvm], [kvm_open], + [have_libkvm="yes"], + [have_libkvm="no"]) +LIBKVM="" +if test "x$have_libkvm" = xyes ; then + AC_DEFINE([HAVE_LIBKVM], [1], [libkvm is available]) + LIBKVM=-lkvm +fi +AC_SUBST(LIBKVM) + dnl Check for gcc atomic primitives AC_MSG_CHECKING([for __sync_lock_test_and_set]) sltas=no diff --git a/headers.h b/headers.h index ab9c17d..a6b0010 100644 --- a/headers.h +++ b/headers.h @@ -32,6 +32,9 @@ #ifdef HAVE_GRP_H # include #endif +#ifdef HAVE_KVM_H +# include +#endif #ifdef HAVE_LIBGEN_H # include #endif @@ -107,6 +110,9 @@ #ifdef HAVE_SYS_SYSCALL_H # include #endif +#ifdef HAVE_SYS_SYSCTL_H +# include +#endif #ifdef HAVE_SYS_TIME_H # include #endif @@ -119,6 +125,9 @@ #ifdef HAVE_SYS_WAIT_H # include #endif +#ifdef HAVE_MACHINE_REG_H +# include +#endif #ifdef __ia64__ /* what a pos */ # define ia64_fpreg FU_ia64_fpreg diff --git a/libsandbox/Makefile.am b/libsandbox/Makefile.am index 9edd466..0485626 100644 --- a/libsandbox/Makefile.am +++ b/libsandbox/Makefile.am @@ -14,7 +14,7 @@ libsandbox_la_CFLAGS = $(CFLAG_EXCEPTIONS) # $(top_builddir)/libsbutil/libsbutil.la libsandbox_la_LIBSBLIB = $(top_builddir)/libsbutil/.libs/libsbutil.a libsandbox_la_LIBADD = \ - -lc $(LIBDL) \ + -lc $(LIBDL) $(LIBKVM) \ $(libsandbox_la_LIBSBLIB) # Do not add -nostdlib or -nostartfiles, as then our constructor # and destructor will not be executed ... diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c index fd3d2ea..35c3870 100644 --- a/libsandbox/libsandbox.c +++ b/libsandbox/libsandbox.c @@ -124,6 +124,12 @@ static const char *sb_get_fd_dir(void) #endif } +#ifdef HAVE_LIBKVM +static const char *sb_get_cmdline(pid_t pid) +{ + return "libkvm"; /* we will get the command line directly later via libkvm */ +} +#else /* HAVE_LIBKVM */ static const char *sb_get_cmdline(pid_t pid) { #if !defined(SANDBOX_PROC_1_CMDLINE) && !defined(SANDBOX_PROC_SELF_CMDLINE) && !defined(SANDBOX_PROC_dd_CMDLINE) @@ -135,6 +141,7 @@ static const char *sb_get_cmdline(pid_t pid) sprintf(path, "/proc/%i/cmdline", pid); return path; } +#endif /* HAVE_LIBKVM */ int canonicalize(const char *path, char *resolved_path) { @@ -358,7 +365,39 @@ char *egetcwd(char *buf, size_t size) return tmpbuf; } -static int sb_copy_file_to_fd(const char *file, int ofd) +#ifdef HAVE_LIBKVM +static int sb_copy_file_or_pid_cmdline_to_fd(const char *file, pid_t pid, int ofd) +{ + int ret = -1; + int cnt = 0; + char **str; + + kvm_t *kt = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); + if (!kt) + return ret; + + struct kinfo_proc *proc = kvm_getprocs(kt, KERN_PROC_PID | KERN_PROC_ALL, pid ? pid : getpid(), &cnt); + if (!proc || !cnt) + goto error; + + str = kvm_getargv(kt, proc, 0); + if (!str) + goto error; + + for (cnt = 0; str[cnt]; cnt++) { + size_t len = strlen(str[cnt]); + if (sb_write(ofd, str[cnt], len) != len) + goto error; + if (str[cnt+1] && sb_write(ofd, " ", 1) != 1) + goto error; + } + ret = 0; +error: + kvm_close(kt); + return ret; +} +#else /* HAVE_LIBKVM */ +static int sb_copy_file_or_pid_cmdline_to_fd(const char *file, pid_t pid, int ofd) { int ret = -1; @@ -388,6 +427,7 @@ static int sb_copy_file_to_fd(const char *file, int ofd) free(buf); return ret; } +#endif /* HAVE_LIBKVM */ void sb_dump_backtrace(void) { @@ -399,7 +439,7 @@ void sb_dump_backtrace(void) #endif const char *cmdline = sb_get_cmdline(trace_pid); sb_printf("%s: ", cmdline); - sb_copy_file_to_fd(cmdline, STDERR_FILENO); + sb_copy_file_or_pid_cmdline_to_fd(cmdline, trace_pid, STDERR_FILENO); sb_printf("\n\n"); } @@ -493,7 +533,7 @@ static bool write_logfile(const char *logfile, const char *func, const char *pat _SB_WRITE_STR("\nC: "); const char *cmdline = sb_get_cmdline(trace_pid); - if (sb_copy_file_to_fd(cmdline, logfd)) { + if (sb_copy_file_or_pid_cmdline_to_fd(cmdline, trace_pid, logfd)) { _SB_WRITE_STR("unable to read "); _SB_WRITE_STR(cmdline); } diff --git a/localdecls.h b/localdecls.h index 83c01d6..206214f 100644 --- a/localdecls.h +++ b/localdecls.h @@ -67,6 +67,8 @@ typedef __sighandler_t sighandler_t; typedef struct pt_regs trace_regs; #elif defined(HAVE_STRUCT_USER_REGS_STRUCT) typedef struct user_regs_struct trace_regs; +#elif defined(HAVE_STRUCT_REG) +typedef struct reg trace_regs; #else # error "unable to find struct for tracing regs" #endif -- 1.7.0.4