Skip to content

Commit

Permalink
Add preliminary support for Seccomp
Browse files Browse the repository at this point in the history
Seccomp makes bugs in jq harder to exploit by imposing limits on the
behaviour of the binary. On transgressions the Linux kernel will kill
it, and print "Bad system call" (or similar). (The kernel's audit log
will contain more details.)

This patch comes with a prelimiary ruleset. That is, I might have missed
some legal syscalls.
  • Loading branch information
mark-kubacki committed Aug 4, 2017
1 parent 7b81a83 commit 1b310de
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
25 changes: 25 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,31 @@ if test "$USE_MAINTAINER_MODE" = yes; then
AC_CHECK_PROGS(LEX, flex lex)
fi

AC_ARG_WITH([seccomp],
[AS_HELP_STRING([--with-seccomp=prefix],
[try this for a non-standard install prefix of libseccomp2])],
[],
[with_seccomp=yes])

AS_IF([test "x$with_seccomp" != xno], [
AS_IF([test "x$with_seccomp" != xyes], [
CFLAGS="$CFLAGS -I${with_seccomp}/include"
LDFLAGS="$LDFLAGS -L${with_seccomp}/lib"
])
# check for libseccomp2
have_seccomp=0
AC_CHECK_HEADER("seccomp.h",
AC_CHECK_LIB([seccomp],[seccomp_init],[LIBS="$LIBS -lseccomp"; have_seccomp=1;],
[AC_MSG_ERROR([You must install libseccomp-dev.])]))
# handle check results
AS_IF([test $have_seccomp = 1], [
AC_DEFINE([HAVE_SECCOMP], 1, [Define to 1 if libseccomp2 is installed])
], [
AC_MSG_NOTICE([libseccomp2 was not found.])
AC_MSG_NOTICE([Try setting the location using '--with-seccomp=PREFIX'])
])
])

dnl Check for valgrind
AC_CHECK_PROGS(valgrind_cmd, valgrind)
if test "x$valgrind_cmd" = "x" ; then
Expand Down
75 changes: 75 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
#include <wtypes.h>
#endif

#ifdef HAVE_SECCOMP
#include <sys/prctl.h>
#include <seccomp.h>
#endif

#if !defined(HAVE_ISATTY) && defined(HAVE__ISATTY)
#undef isatty
#define isatty _isatty
Expand Down Expand Up @@ -241,6 +246,76 @@ int main(int argc, char* argv[]) {
jv ARGS = jv_array(); /* positional arguments */
jv program_arguments = jv_object(); /* named arguments */

#if defined(__gnu_linux__) && defined(HAVE_SECCOMP) /* seccomp */
prctl(PR_SET_NO_NEW_PRIVS, 1);
prctl(PR_SET_DUMPABLE, 0);

scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_KILL); // default action: kill, SIGSYS, entry in the system's log
if (ctx == NULL) {
perror("this system does not have Seccomp");
ret = 71; goto out;
}
/* the "Seccomp preamble" */
int rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
#ifndef __GLIBC__
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SYS_writev, 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SYS_brk, 0);
#endif
if (rc != 0) {
perror("a rule in the Seccomp preamble has been rejected");
ret = 77; goto out;
}

/* writing - but to no regular file unless FD swapped for stdout or stderr */
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
SCMP_CMP(0, SCMP_CMP_EQ, STDOUT_FILENO));
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
SCMP_CMP(0, SCMP_CMP_EQ, STDERR_FILENO));

/* opening and reading files */
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);

rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 2,
SCMP_A0(SCMP_CMP_EQ, (size_t)NULL),
SCMP_A5(SCMP_CMP_EQ, 0)
);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 2,
SCMP_A0(SCMP_CMP_NE, (size_t)NULL),
SCMP_A1(SCMP_CMP_GE, 0)
);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0);
#ifndef __GLIBC__
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SYS_madvise, 0);
#endif
if (rc != 0) {
perror("a rule in the Seccomp read/write block has been rejected");
ret = 77; goto out;
}

/* called indirectly by jq */
rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0);
if (rc != 0) {
perror("a rule of the last Seccomp block has been rejected");
ret = 77; goto out;
}

/* apply the ruleset */
rc = seccomp_load(ctx);
if (rc != 0) {
perror("cannot apply the Seccomp ruleset");
ret = 77; goto out;
}
#endif /* seccomp */

#ifdef WIN32
fflush(stdout);
fflush(stderr);
Expand Down

0 comments on commit 1b310de

Please sign in to comment.