|
|
|
/* Copyright (c) 2017-2023, Michael Santos <michael.santos@gmail.com>
|
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.
7 years ago
|
|
|
*
|
|
|
|
* 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 RESTRICT_PROCESS_rlimit
|
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.
7 years ago
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <unistd.h>
|
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.
7 years ago
|
|
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
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.
7 years ago
|
|
|
#include "xmppipe.h"
|
|
|
|
|
|
|
|
int restrict_process_init(xmppipe_state_t *state) {
|
|
|
|
struct rlimit rl_zero = {0};
|
|
|
|
struct stat sb;
|
|
|
|
|
|
|
|
if (fstat(STDOUT_FILENO, &sb) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!S_ISREG(sb.st_mode)) {
|
|
|
|
if (setrlimit(RLIMIT_FSIZE, &rl_zero) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return setrlimit(RLIMIT_NPROC, &rl_zero);
|
|
|
|
}
|
|
|
|
|
|
|
|
int restrict_process_stdin(xmppipe_state_t *state) {
|
|
|
|
struct rlimit rl;
|
|
|
|
|
|
|
|
rl.rlim_cur = RESTRICT_PROCESS_RLIMIT_NOFILE;
|
|
|
|
rl.rlim_max = RESTRICT_PROCESS_RLIMIT_NOFILE;
|
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.
7 years ago
|
|
|
|
|
|
|
if (rl.rlim_cur == (rlim_t)-1) {
|
|
|
|
int fd = xmppipe_conn_fd(state);
|
|
|
|
if (fd < 0)
|
|
|
|
return -1;
|
|
|
|
rl.rlim_cur = rl.rlim_max = fd + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return setrlimit(RLIMIT_NOFILE, &rl);
|
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.
7 years ago
|
|
|
}
|
|
|
|
#endif
|