From c5cdf8cee353a93737ee17e29c3ed1f305e062b8 Mon Sep 17 00:00:00 2001 From: "mingang.he" Date: Sat, 10 Jun 2023 21:37:58 +0800 Subject: [PATCH] Use libseccomp to filter syscalls --- Makefile | 6 ++++-- graftcp.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 39ebc2a..70b4ba3 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,8 @@ ifneq ($(shell echo $(VERSION) | head -c 1), v) endif CFLAGS += -DVERSION=\"$(VERSION)\" +LDFLAGS += -lseccomp + SRC := $(wildcard *.c) GRAFTCP_LOCAL_BIN = local/graftcp-local local/mgraftcp @@ -59,7 +61,7 @@ all:: $(TARGET) graftcp: main.o graftcp.o util.o string-set.o conf.o - $(CC) $^ -o $@ + $(CC) $^ -o $@ $(LDFLAGS) libgraftcp.a: graftcp.o util.o string-set.o conf.o $(AR) rcs $@ $^ @@ -78,7 +80,7 @@ uninstall:: -rm -f $(DESTDIR)$(BINDIR)/graftcp $(MAKE) -C local $@ -install_graftcp:: graftcp +install_graftcp:: graftcp $(INSTALL) $< $(DESTDIR)$(BINDIR)/$< uninstall_graftcp:: diff --git a/graftcp.c b/graftcp.c index 86b1a57..144d23e 100644 --- a/graftcp.c +++ b/graftcp.c @@ -14,6 +14,10 @@ */ #include #include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) +#include +#endif #include "graftcp.h" #include "conf.h" @@ -86,6 +90,41 @@ static bool is_ignore(const char *ip) return false; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) +static void install_seccomp() +{ + scmp_filter_ctx ctx; + ctx = seccomp_init(SCMP_ACT_ALLOW); + + if (ctx == NULL) { + fprintf(stderr, "seccomp_init failed\n"); + exit(1); + } + + if (seccomp_rule_add(ctx, SCMP_ACT_TRACE(1), SCMP_SYS(close), 0) < 0) { + perror("seccomp_rule_add"); + exit(1); + } + if (seccomp_rule_add(ctx, SCMP_ACT_TRACE(1), SCMP_SYS(socket), 0) < 0) { + perror("seccomp_rule_add"); + exit(1); + } + if (seccomp_rule_add(ctx, SCMP_ACT_TRACE(1), SCMP_SYS(connect), 0) < 0) { + perror("seccomp_rule_add"); + exit(1); + } + if (seccomp_rule_add(ctx, SCMP_ACT_TRACE(1), SCMP_SYS(clone), 0) < 0) { + perror("seccomp_rule_add"); + exit(1); + } + if (seccomp_load(ctx) < 0) { + perror("seccomp_load"); + exit(1); + } + seccomp_release(ctx); +} +#endif + void socket_pre_handle(struct proc_info *pinfp) { struct socket_info *si = calloc(1, sizeof(*si)); @@ -229,6 +268,9 @@ void init(int argc, char **argv) perror("fork"); exit(errno); } else if (child == 0) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) + install_seccomp(); +#endif do_child(argc, argv); } pi = alloc_proc_info(child); @@ -312,6 +354,9 @@ int do_trace() if (ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) + PTRACE_O_TRACESECCOMP | +#endif PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK) < 0) { perror("ptrace"); @@ -319,10 +364,17 @@ int do_trace() } } event = ((unsigned)status >> 16); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) + if (event != 0 && event != PTRACE_EVENT_SECCOMP) { + sig = 0; + goto end; + } +#else if (event != 0) { sig = 0; goto end; } +#endif if (WIFSIGNALED(status) || WIFEXITED(status) || !WIFSTOPPED(status)) { exit_code = WEXITSTATUS(status); @@ -353,11 +405,20 @@ int do_trace() * -1, the caller must clear errno before the call of ptrace(2). */ errno = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) + if (ptrace(exiting(pinfp) ? PTRACE_SYSCALL : PTRACE_CONT, + pinfp->pid, 0, sig) < 0) { + if (errno == ESRCH) + continue; + return -1; + } +#else if (ptrace(PTRACE_SYSCALL, pinfp->pid, 0, sig) < 0) { if (errno == ESRCH) continue; return -1; } +#endif } return 0; }