From a34d5766c57de227b12d7e4093ac557e1f59ea57 Mon Sep 17 00:00:00 2001 From: Michael Santos Date: Tue, 31 Jan 2017 08:17:02 -0500 Subject: [PATCH] sandbox: basic rlimit sandbox The rlimit sandbox disables forking processes and opening files. The rlimit sandbox is not used by default yet. To compile it: XMPPIPE_SANDBOX=XMPPIPE_SANDBOX_RLIMIT make The rlimit sandbox should work on any platform. However the interaction of RLIMIT_NOFILE with poll(2) (and select(2)?) on some platforms (FreeBSD but really any OS besides Linux) is problematic: * opening a number of fd's, setting RLIMIT_NOFILE to 0, calling poll(2) on the fdset Linux: works FreeBSD: fails * opening a number of fd's, setting RLIMIT_NOFILE to maxfd+1, calling poll(2) on the fdset Linux: works FreeBSD: works The issue with the second option is that a library may have opened a sequence of file descriptors then closed the lower numbered fd's: open() => 3 open() => 4 open() => 5 close(3) close(4) maxfd = 5 RLIMIT_NOFILE would be set to 6 (stdin, stdout, stderr, 3, 4, 5) and the sandbox would allow re-opening fd's 3 and 4. One possible fix would be to run through the sequence of fd's before entering the rlimit sandbox: * test if the fd is closed * if the fd is closed, dup2(STDIN_FILENO, fd) Since the closed fd's are not part of the pollset, they will not be polled and should be ignored. Note we can't simply move maxfd to the lowest unused fd because libstrophe maintains the fd number as internal, opaque state. Empirically, the xmpp fd is always 3. Another option would be to abort the process if the fd does not equal 3. --- src/xmppipe.c | 2 +- src/xmppipe_sandbox_rlimit.c | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/xmppipe_sandbox_rlimit.c diff --git a/src/xmppipe.c b/src/xmppipe.c index ea06526..1c7ae9b 100644 --- a/src/xmppipe.c +++ b/src/xmppipe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, Michael Santos +/* Copyright (c) 2015-2017, Michael Santos * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/src/xmppipe_sandbox_rlimit.c b/src/xmppipe_sandbox_rlimit.c new file mode 100644 index 0000000..81bad85 --- /dev/null +++ b/src/xmppipe_sandbox_rlimit.c @@ -0,0 +1,38 @@ +/* Copyright (c) 2017, Michael Santos + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifdef XMPPIPE_SANDBOX_RLIMIT +#include +#include + +#include "xmppipe.h" + + int +xmppipe_sandbox_init(xmppipe_state_t *state) +{ + struct rlimit rl = {0}; + +#ifdef RLIMIT_NPROC + if (setrlimit(RLIMIT_NPROC, &rl) < 0) + return -1; +#endif + +#ifdef RLIMIT_NOFILE + if (setrlimit(RLIMIT_NOFILE, &rl) < 0) + return -1; +#endif + + return 0; +} +#endif