summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-08-04 15:58:54 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-08-04 15:58:54 +0100
commit21efd074399894bd9b924177f8c6fde874bb036a (patch)
tree0a333bb468f7ce80023f22b6fbc03e6a022f19b5
parent789f4fb4f3b9a916a0609616e222ecfa0af86a5f (diff)
downloadsupple-21efd074399894bd9b924177f8c6fde874bb036a.tar.gz
CAPI: rlimit the process HARD so even if it evades soft limits, it's pretty stuffed
-rw-r--r--lib/supple/capi.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/supple/capi.c b/lib/supple/capi.c
index 0eaa372..97802ec 100644
--- a/lib/supple/capi.c
+++ b/lib/supple/capi.c
@@ -14,6 +14,8 @@
#include <lauxlib.h>
#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
@@ -173,6 +175,7 @@ supple_capi_lockdown(lua_State *L)
{
bool rootly = (geteuid() == 0);
char *tempdir;
+ struct rlimit lim;
lua_settop(L, 0); /* Discard any arguments */
/* Prepare a copy of the tempdir template ready */
@@ -231,6 +234,46 @@ supple_capi_lockdown(lua_State *L)
return 2;
}
+ /* Cap our limits down as far as we can */
+#define CAP_AT(lval,cap) lval = (lval < cap) ? lval : cap
+#define CAP_LIMIT(resource, soft, hard) \
+ do { \
+ if (rootly && getrlimit(resource, &lim) != 0) { \
+ int saved_errno = errno; \
+ lua_pushliteral(L, "getrlimit(" #resource ")"); \
+ lua_pushnumber(L, saved_errno); \
+ return 2; \
+ } \
+ CAP_AT(lim.rlim_cur,soft); \
+ CAP_AT(lim.rlim_max,hard); \
+ if (rootly && setrlimit(resource, &lim) != 0) { \
+ int saved_errno = errno; \
+ lua_pushliteral(L, "setrlimit(" #resource ")"); \
+ lua_pushnumber(L, saved_errno); \
+ return 2; \
+ } \
+ } while (0)
+
+ /* Limit the virtual memory arena to 50 megs.
+ * While this might seem a lot, a bare lua5.1 interpreter plus Supple
+ * and deps seems to come to around 28MB VMSZ (although only 2MB res)
+ * because of shared libraries and the ilk. 50MB allows for up to
+ * 22MB of allocations beyond that, which seems fair.
+ */
+ CAP_LIMIT(RLIMIT_AS, (50 * 1024 * 1024), (50 * 1024 * 1024));
+ /* And limit CPU to 15 seconds, 30 if not otherwise handled */
+ CAP_LIMIT(RLIMIT_CPU, 15, 30);
+ /* Cap output file size at 0 bytes, so even if we managed to open
+ * a file, writes would fail.
+ */
+ CAP_LIMIT(RLIMIT_FSIZE, 0, 0);
+ /* Do not allow core files to be created */
+ CAP_LIMIT(RLIMIT_CORE, 0, 0);
+ /* And the attackers would have to close their only FD to the outside
+ * world in order to open anything anyway.
+ */
+ CAP_LIMIT(RLIMIT_NOFILE, 1, 1);
+
/* Drop privs */
if (rootly && setuid(getuid()) != 0) {
int saved_errno = errno;