forked from ochko/safeexec
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathREADME
123 lines (94 loc) · 4.46 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
safeexec (safe execution environment)
A general-purpose lightweight sandbox for safely executing user programs
https://github.com/cemc/safeexec
History: see below. License: AGPL 3 (http://www.gnu.org/licenses/agpl.html)
safeexec provides a sandbox environment which prevents
malicious users from causing trouble, and user mistakes from blowing up
your server. However, running code on your server should be taken at
__your own risk__.
You should take these additional precautions:
- check whether safeexec default gid (1000)/uids (10000-42768) are in use!
- assuming not, you may name the group, but you won't name the users; the
whole user range is treated as "unpriviliged" ("other" for all files)
- this code doesn't block network access. Use iptables to do this, e.g.:
/sbin/iptables -A OUTPUT -m owner --gid-owner 1000 -j DROP
- the max number of file handles (nfile) needs to be nonzero in order to
read libraries, but even if the maximum file size (fsize) is 0, the code
can go around creating size-0 files. Use file permissions to avoid this,
and to avoid reads as well. Chroot can limit how much of a "file system"
they can see at all.
The general plan:
- fork into two processes
- safeexec should have its setuid bit on, and uid root
- one fork will be a supervisor running as root
- other fork runs program as unprivileged user, with rlimits & nice
- supervisor will measure total memory by looking in /proc/
- wall clock limit enforced with alarm() & signal()
- return EXIT_SUCCESS (0) if all went ok, EXIT_FAILURE otherwise
Standard input to safeexec is passed on to the exec'd process.
The non-supervisor user number is determined by the supervisor process:
<non-supervisor uid #> = 10000 + <supervisor pid #>
or, you can replace 10000 with something else using uidplus.
Since pids are unique, so are the resulting uids.
(Sanity check: max value of pids is in /proc/sys/kernel/pid_max)
Among other things, this should prevent simultaneous safeexec'ed
programs from kill()ing each other, which they could do if they had
the same user id.
INSTALLATION
make # requires sudo access
USAGE
./safeexec # run with no options to see arguments
EXAMPLES
See the file EXAMPLES. For a basic test, run:
cd tests; make; cd .. # compile "hello world" etc
./safeexec --exec tests/hello
Expected result (stdout + stderr mixed):
Hello World
OK
elapsed time: 0 seconds
memory usage: 0 kbytes
cpu usage: 0.000 seconds
See EXAMPLES-CHROOT and EXAMPLES-ETC for more examples and tests.
USAGE NOTES AND TROUBLESHOOTING
Chroot is powerful stuff: it makes a given directory (say, /jail)
appear to be the root directory of the file system, as far as
the child process can see. However, the jail directory might
need to be given further files, in order for the child process
to operate correctly. For example, a Python3 jail needs to include
some unexpected things like /lib/libcrypt-2.5.so.
Make sure that you set the file and memory limits big enough that
your language can load. Python can give you all manner of strange
errors if it doesn't get enough memory.
Note: A user who had been utilizing proxmox containers/LXC reported
that installing safeexec was not possible until they switched to a KVM.
PARANOID DISCLAIMER
You can get more fine-grained supervision if you ptrace, which
interrupts every system call (at a cost of more overhead). Use
a VM if you are more paranoid. Use separate machines if you want
to avoid timing attacks.
TODO
Linux provides, in principle, two ways to measure the time used
by a process. According to "Security of Programming Contest Systems"
by Michal Fori\v{s}ek, only one of these is suitable. It seems
we should use prctl() to change
PR_SET_TIMING
to
PR_TIMING_TIMESTAMP
but, this is apparently just defined, and not yet implemented, in
linux.
HISTORY
Originally part of Mooshak (http://mooshak.dcc.fc.up.pt/)
Revised in 2009 by http://github.com/ochko/safeexec
This version revised in 2011-13 by David Pritchard ([email protected])
http://github.com/daveagp
Mooshak released the files under "The Artistic License".
The main changes made to safeexec.c are
- how are uids calculated (pid + a constant)
which avoids two different web users getting the same uid
- allow setting group id
- bugfix: remove all supplemental groups
- command-line argument for niceness
- command-line argument for environment variables
This changed version is released under the GNU Affero
General Public License, versions 3 or later. See LICENSE or visit:
http://www.gnu.org/licenses/agpl.html