Use a seccomp filter on Linux to disable execve(2) and execveat(2).
This still relies on LD_PRELOAD to work so it has the same issues as the existing mether with respect to running 32-bit binaries on a 64-bit kernel.
This commit is contained in:
@@ -526,6 +526,9 @@
|
|||||||
/* Define to 1 if you have the `posix_spawnp' function. */
|
/* Define to 1 if you have the `posix_spawnp' function. */
|
||||||
#undef HAVE_POSIX_SPAWNP
|
#undef HAVE_POSIX_SPAWNP
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `prctl' function. */
|
||||||
|
#undef HAVE_PRCTL
|
||||||
|
|
||||||
/* Define to 1 if you have the `pread' function. */
|
/* Define to 1 if you have the `pread' function. */
|
||||||
#undef HAVE_PREAD
|
#undef HAVE_PREAD
|
||||||
|
|
||||||
|
17
configure
vendored
17
configure
vendored
@@ -15223,6 +15223,23 @@ fi
|
|||||||
*-*-linux*|*-*-k*bsd*-gnu)
|
*-*-linux*|*-*-k*bsd*-gnu)
|
||||||
shadow_funcs="getspnam"
|
shadow_funcs="getspnam"
|
||||||
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
||||||
|
# Check for linux/filter.h and prctl to use seccomp(2)
|
||||||
|
ac_fn_c_check_header_mongrel "$LINENO" "linux/filter.h" "ac_cv_header_linux_filter_h" "$ac_includes_default"
|
||||||
|
if test "x$ac_cv_header_linux_filter_h" = xyes; then :
|
||||||
|
for ac_func in prctl
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl"
|
||||||
|
if test "x$ac_cv_func_prctl" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_PRCTL 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
*-*-gnu*)
|
*-*-gnu*)
|
||||||
# lockf() is broken on the Hurd
|
# lockf() is broken on the Hurd
|
||||||
|
@@ -1962,6 +1962,8 @@ case "$host" in
|
|||||||
*-*-linux*|*-*-k*bsd*-gnu)
|
*-*-linux*|*-*-k*bsd*-gnu)
|
||||||
shadow_funcs="getspnam"
|
shadow_funcs="getspnam"
|
||||||
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
test -z "$with_pam" && AUTH_EXCL_DEF="PAM"
|
||||||
|
# Check for linux/filter.h and prctl to use seccomp(2)
|
||||||
|
AC_CHECK_HEADER([linux/filter.h], [AC_CHECK_FUNCS([prctl])])
|
||||||
;;
|
;;
|
||||||
*-*-gnu*)
|
*-*-gnu*)
|
||||||
# lockf() is broken on the Hurd
|
# lockf() is broken on the Hurd
|
||||||
|
@@ -18,6 +18,14 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(__linux__) && defined(HAVE_PRCTL)
|
||||||
|
# include <sys/prctl.h>
|
||||||
|
# include <asm/unistd.h>
|
||||||
|
# include <linux/audit.h>
|
||||||
|
# include <linux/filter.h>
|
||||||
|
# include <linux/seccomp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -204,3 +212,43 @@ FN_NAME(wordexp)(const char *words, wordexp_t *we, int flags)
|
|||||||
#endif /* HAVE___INTERPOSE */
|
#endif /* HAVE___INTERPOSE */
|
||||||
}
|
}
|
||||||
INTERPOSE(wordexp)
|
INTERPOSE(wordexp)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On Linux we can use a seccomp() filter to disable exec.
|
||||||
|
*/
|
||||||
|
#if defined(__linux) && defined(HAVE_PRCTL)
|
||||||
|
|
||||||
|
/* Older systems may not support execveat(2). */
|
||||||
|
#ifndef __NR_execveat
|
||||||
|
# define __NR_execveat -1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void noexec_ctor(void) __attribute__((constructor));
|
||||||
|
|
||||||
|
static void
|
||||||
|
noexec_ctor(void)
|
||||||
|
{
|
||||||
|
struct sock_filter exec_filter[] = {
|
||||||
|
/* Load syscall number into the accumulator */
|
||||||
|
BPF_STMT(BPF_LD | BPF_ABS, offsetof(struct seccomp_data, nr)),
|
||||||
|
/* Jump to deny for execve/execveat */
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execve, 2, 0),
|
||||||
|
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_execveat, 1, 0),
|
||||||
|
/* Allow non-matching syscalls */
|
||||||
|
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||||
|
/* Deny execve/execveat syscall */
|
||||||
|
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EACCES & SECCOMP_RET_DATA))
|
||||||
|
};
|
||||||
|
const struct sock_fprog exec_fprog = {
|
||||||
|
nitems(exec_filter),
|
||||||
|
exec_filter
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SECCOMP_MODE_FILTER will fail unless the process has
|
||||||
|
* CAP_SYS_ADMIN or the no_new_privs bit is set.
|
||||||
|
*/
|
||||||
|
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0)
|
||||||
|
(void)prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &exec_fprog);
|
||||||
|
}
|
||||||
|
#endif /* __linux__ && HAVE_PRCTL */
|
||||||
|
Reference in New Issue
Block a user