#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
+#include "autoconf.h"
+
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/sysinfo.h>
#include <sys/resource.h>
+#include <sys/utsname.h>
#include <linux/ptrace.h>
#if defined(CONFIG_BOX_KERNEL_AMD64) && !defined(CONFIG_BOX_USER_AMD64)
S(get_thread_area) = A_YES,
S(set_tid_address) = A_YES,
S(exit_group) = A_YES | A_SAMPLE_MEM,
-#ifndef CONFIG_BOX_USER_AMD64
+#ifdef CONFIG_BOX_USER_AMD64
+ S(arch_prctl) = A_YES,
+#else
S(oldfstat) = A_YES,
S(ftruncate64) = A_YES,
S(_llseek) = A_YES,
{ "/proc/meminfo", A_YES },
{ "/proc/self/stat", A_YES },
{ "/proc/self/exe", A_YES }, // Needed by FPC 2.0.x runtime
+ { "/proc/self/maps", A_YES }, // Needed by glibc when it reports arena corruption
};
static struct path_rule *user_path_rules;
struct user user;
};
+static int user_mem_fd;
+
static int read_user_mem(arg_t addr, char *buf, int len)
{
- static int mem_fd;
-
- if (!mem_fd)
+ if (!user_mem_fd)
{
char memname[64];
sprintf(memname, "/proc/%d/mem", (int) box_pid);
- mem_fd = open(memname, O_RDONLY);
- if (mem_fd < 0)
+ user_mem_fd = open(memname, O_RDONLY);
+ if (user_mem_fd < 0)
die("open(%s): %m", memname);
}
- if (lseek64(mem_fd, addr, SEEK_SET) < 0)
+ if (lseek64(user_mem_fd, addr, SEEK_SET) < 0)
die("lseek64(mem): %m");
- return read(mem_fd, buf, len);
+ return read(user_mem_fd, buf, len);
+}
+
+static void close_user_mem(void)
+{
+ if (user_mem_fd)
+ {
+ close(user_mem_fd);
+ user_mem_fd = 0;
+ }
}
#ifdef CONFIG_BOX_KERNEL_AMD64
die("ptrace(PTRACE_SETREGS): %m");
}
+static void
+sanity_check(void)
+{
+}
+
#else
static void
die("ptrace(PTRACE_SETREGS): %m");
}
+static void
+sanity_check(void)
+{
+#if !defined(CONFIG_BOX_ALLOW_INSECURE)
+ struct utsname uts;
+ if (uname(&uts) < 0)
+ die("uname() failed: %m");
+
+ if (!strcmp(uts.machine, "x86_64"))
+ die("Running 32-bit sandbox on 64-bit kernels is inherently unsafe. Please get a 64-bit version.");
+#endif
+}
+
#endif
/*** Syscall checks ***/
{
msg("[master] ");
if (sys == NATIVE_NR_execve)
- exec_seen = 1;
+ {
+ exec_seen = 1;
+ close_user_mem();
+ }
}
else if ((act = valid_syscall(&a)) >= 0)
{
if (optind >= argc)
usage();
+ sanity_check();
uid = geteuid();
if (setreuid(uid, uid) < 0)
die("setreuid: %m");