sydbox — ptrace & seccomp based sandbox
The following options are understood:
-h
-v
-c
pathspec
pathspec
to the configuration file, may be repeated.
See the section called “Configuration” for more information.
-m
magic
-E
var=val
var=val
in the environment for command, may be repeated
-E
var
var
from the environment for command, may be repeated
Sydbox is configured through the so-called magic commands. There are three ways to supply magic commands:
Sydbox may be configured using a configuration file. The path to the configuration file is
speficied using the -c
command line switch or the SYDBOX_CONFIG
environment variable. More than one configuration file may be specified this way. However, only the
initial configuration file can change the core
configuration. If path to the configuration file is prefixed with the character '@
',
Sydbox looks for this configuration file under
where $sharedir
/sydbox/$sharedir
is usually /usr/share
. The command line switch has precedence over the
SYDBOX_CONFIG
environment variable.
Sydbox may be configured using magic
stat(2) calls during runtime.
This is achieved by calling stat()
system call on the special path
/dev/sydbox
followed by the magic command. Note that runtime configuration is only
possible if the magic lock is unset. The system call stat()
was
chosen as the magic call because it is practical to invoke using builtin shell commands like:
test -e /dev/sydbox/core/sandbox/read:deny
which enables read sandboxing for a shell running under Sydbox. It is also possible to
query certain values using the return value of the magic stat
(2):
test -e '/dev/sydbox/core/sandbox/read?' && echo "read sandboxing on" || echo "read sandboxing off"
Some of these shell builtins may actually call
lstat(2) system call instead
of stat(2) thus
Sydbox makes sure to check lstat()
system calls for magic commands
as well.
Every magic command accepts an argument of a certain type. The available types are listed below:
boolean
A boolean type may have one of the two values,
true
or false
.
To specify boolean values when supplying magic commands to Sydbox, you may also use
true
or false
.
In addition you can use the short forms
t
or f
and you can also use
1
or 0
.
integer
This type represents the basic integer type.
string
This type represents the basic string type.
string-array
This type represents a list of strings. Other types aren't allowed within this type.
command
This is a special type which is used to make sydbox execute certain functions. It is meant to be used as a basic interprocess communication to workaround some tracing limitations.
Magic commands of this type can only be used with the magic
stat
(2) system call.
As mentioned in the section called “Configuration” Sydbox may be configured using the so-called magic commands. Format of the magic commands is simple:
${PREFIX}/section/of/option${OPERATION_CHARACTER}value
where ${PREFIX}
is /dev/sydbox
by default (may be altered at compile-time using SYDBOX_MAGIC_PREFIX
definition).
This prefix is only required for magic stat()
, not for -m
command line
switch.
${OPERATION_CHARACTER}
determines the operation of the magic command.
Possible values are listed below:
Configuration file format of sydbox is simple. It is just a way to supply many magic commands in a convenient
way. All empty lines and lines starting with the number sign '#
' are ignored. All the other
lines are treated as if they were supplied to Sydbox via the -m
command line switch.
Configuration file naming of sydbox follows a naming scheme which makes it possible to extract magic command API version from the file name. A sydbox configuration file must have the extension "syd-" followed by the API version (e.g. "syd-1" for API version 1).
Current magic command API of sydbox version is `1'.
Sydbox recognizes the following magic commands:
core/sandbox/exec
type: string
default: false
query: yes
A string specifying how execve
(2) system call should be sandboxed.
See the section called “execve(2) Sandboxing” for more information.
core/sandbox/read
type: string
default: false
query: yes
A string specifying how read sandboxing should be done. See the section called “Read Sandboxing” for more information.
core/sandbox/write
type: string
default: false
query: yes
A string specifying how write sandboxing should be done. See the section called “Write Sandboxing” for more information.
core/sandbox/network
type: string
default: false
query: yes
A string specifying how network sandboxing should be done. See the section called “Network Sandboxing” for more information.
core/restrict/file_control
type: boolean
default: false
A boolean specifying whether potentially dangerous options to
open
(2) and
fcntl
(2) should be forbidden.
These options include O_ASYNC
, O_DIRECT
and
O_SYNC
. In addition all
fcntl
(2) commands except
F_GETFL
,
F_SETFL
,
F_SETOWN
,
F_SETLK
,
F_SETLKW
,
F_SETLK64
,
F_SETLKW64
,
F_SETFD
,
F_GETFD
and
F_DUPFD
are forbidden as well.
core/restrict/shared_memory_writable
type: boolean
default: false
A boolean specifying whether writable shared memory mapping (
mmap2
(2) with
PROT_WRITE
& MAP_SHARED
combination )
should be forbidden.
This setting is meant as a protection against TOCTOU
attacks. However, it should
be noted that such attack vectors are relatively diverse under a ptrace() monitoring environment.
core/whitelist/per_process_directories
type: boolean
default: true
A boolean specifying whether per-process directories like
/proc/
should automatically be whitelisted.
$pid
core/whitelist/successful_bind
type: boolean
default: true
A boolean specifying whether the socket address arguments of successful
bind
(2) calls should be whitelisted
for connect
(2) and
sendto
(2) system calls.
These socket addresses are whitelisted globally and not per-process for
usability reasons. Thus, for example, a process which forks to call
bind
(2) will have its socket
address whitelisted for her parent as well.
core/whitelist/unsupported_socket_families
type: boolean
default: true
A boolean specifying whether unknown socket families should be allowed access when network sandboxing is on.
core/violation/decision
type: string
default: deny
A string specifying the decision to take when an access violation occurs. Possible values are
kill
, killall
and deny
.
Default is deny
which means to deny the system call and resume execution.
core/violation/exit_code
type: integer
default: -1
An integer specifying the exit code in case core/violation/decision
is
killall
. As a special case, if this integer is equal to zero, sydbox exits with
128
added to the eldest process' exit value in case an access violation has occured.
This special case is meant for program tests to check whether an access violation has occured using the
exit code.
core/violation/raise_fail
type: boolean
default: false
A boolean specifying whether certain failures like errors during path resolution should be treated as access violations. Note this is just a switch for reporting, the access to the system call is denied nevertheless.
core/violation/raise_safe
type: boolean
default: false
A boolean specifying whether certain violations which are considered safe should be reported. For
example, mkdir
(2) is a system call which fails when it can not
create an existant directory. In this special case, sydbox denies the system call with
EEXIST
for consistency and does not raise an access violation in case
core/violation/raise_safe
is set to false
. Other examples are, the
access
(2) system call which is silently denied with
EACCES
and
listxattr
(2), and
llistxattr
(2) system calls which are silently denied with
ENOTSUP
if this option is set to false.
core/trace/follow_fork
type: boolean
default: true
A boolean specifying whether Sydbox should follow forks, vforks and clones.
core/trace/exit_kill
type: boolean
default: false
A boolean specifying whether traced processes should be killed when Sydbox exits.
This is supported on Linux-3.8 or newer via PTRACE_O_EXITKILL
.
core/trace/magic_lock
type: string
default: off
A string specifying the state of the magic lock. Possible values are on
,
off
and exec
. If magic lock is on
no magic
commands are allowed. Note, the magic lock is tracked per-process. If exec
is
specified, the magic lock is set to on
when the process returns from the system call
execve
(2).
core/trace/use_seccomp
type: boolean
default: false
A boolean specifying whether seccomp user-mode filters should be used. This works only on Linux-3.5 or
newer and sydbox must be compiled with the --enable-seccomp
configure option.
core/trace/use_seize
type: boolean
default: false
A boolean specifying whether sydbox should use the new ptrace requests PTRACE_SEIZE
and PTRACE_INTERRUPT
to trace processes.
core/trace/use_toolong_hack
type: boolean
default: false
A boolean specifying whether sydbox should use a hack to determine working directories under a path longer
than PATH_MAX
.
core/match/case_sensitive
type: boolean
default: true
A boolean specifying the case sensitivity of pattern matching.
See the section called “Pattern Matching” for more information.
core/match/no_wildcard
type: string
default: literal
A string specifying how to match patterns with no
'*
' or '?
' characters in them.
Possible values are literal
and prefix
.
With literal
such patterns are matched literally, whereas
with prefix
Sydbox appends /***
to the
end of such patterns to make them a prefix match. Implemented mostly to provide
compatibility with sydbox-0 patterns.
See the section called “Pattern Matching” for more information.
exec/resume_if_match
type: string-array
default: [empty array]
This setting specifies a list of path patterns. If one of these patterns matches the resolved path of an
execve
(2) system call, the process in question is resumed. See
the section called “Pattern Matching” for more information on wildmatch patterns.
The initial execve
(2) is not checked.
Thus, if sydbox is called like:
$> sydbox -m exec/resume_if_match+/bin/sh -- /bin/sh
she will not execute the /bin/sh command.
This functionality does not work with seccomp because once enabled, seccomp mode
can not be disabled. If sydbox detaches from the process all observed system calls of the process will
fail with ENOSYS
. Due to this fact upon receiving this command when seccomp is
enabled sydbox goes on to trace the process but stops sandboxing and frees all sandboxing related data
structures of the process. The process is ignored. However, this workaround may not
be enough for some cases, for example, when the process in question is a daemon and must resume its
execution after sydbox exits. For such cases use cmd/exec.
exec/kill_if_match
type: string-array
default: [empty array]
This setting specifies a list of path patterns. If one of these patterns matches the resolved path of an
execve
(2) system call, the process in question is killed. See
the section called “Pattern Matching” for more information on wildmatch patterns.
The initial execve
(2) is not checked.
Thus, if sydbox is called like:
$> sydbox -m exec/kill_if_match+/bin/sh -- /bin/sh
she will execute the /bin/sh command.
filter/exec
type: string-array
default: [empty array]
Specifies a list of path patterns to filter for execve
(2)
sandboxing. See the section called “execve(2) Sandboxing” and the section called “Pattern Matching”.
filter/read
type: string-array
default: [empty array]
Specifies a list of path patterns to filter for read sandboxing. See the section called “Read Sandboxing” and the section called “Pattern Matching”.
filter/write
type: string-array
default: [empty array]
Specifies a list of path patterns to filter for write sandboxing. See the section called “Write Sandboxing” and the section called “Pattern Matching”.
filter/network
type: string-array
default: [empty array]
Specifies a list of network addresses to filter for network sandboxing. See the section called “Network Sandboxing” and the section called “Address Matching”.
whitelist/exec
type: string-array
default: [empty array]
Specifies a list of path patterns to whitelist for execve
(2)
sandboxing. See the section called “execve(2) Sandboxing” and the section called “Pattern Matching”.
whitelist/read
type: string-array
default: [empty array]
Specifies a list of path patterns to whitelist for read sandboxing. See the section called “Read Sandboxing” and the section called “Pattern Matching”.
whitelist/write
type: string-array
default: [empty array]
Specifies a list of path patterns to whitelist for write sandboxing. See the section called “Write Sandboxing” and the section called “Pattern Matching”.
whitelist/network/bind
type: string-array
default: [empty array]
Specifies a list of network addresses to whitelist for bind
(2)
network sandboxing. See the section called “Network Sandboxing” and
the section called “Address Matching”.
whitelist/network/connect
type: string-array
default: [empty array]
Specifies a list of network addresses to whitelist for
connect
(2) and
sendto
(2) network sandboxing.
See the section called “Network Sandboxing” and the section called “Address Matching”.
blacklist/exec
type: string-array
default: [empty array]
Specifies a list of path patterns to blacklist for execve
(2)
sandboxing. See the section called “execve(2) Sandboxing” and the section called “Pattern Matching”.
blacklist/read
type: string-array
default: [empty array]
Specifies a list of path patterns to blacklist for read sandboxing. See the section called “Read Sandboxing” and the section called “Pattern Matching”.
blacklist/write
type: string-array
default: [empty array]
Specifies a list of path patterns to blacklist for write sandboxing. See the section called “Write Sandboxing” and the section called “Pattern Matching”.
blacklist/network/bind
type: string-array
default: [empty array]
Specifies a list of network addresses to blacklist for bind
(2)
network sandboxing. See the section called “Network Sandboxing” and
the section called “Address Matching”.
blacklist/network/connect
type: string-array
default: [empty array]
Specifies a list of network addresses to blacklist for
connect
(2) and
connect
(2) network sandboxing.
See the section called “Network Sandboxing” and the section called “Address Matching”.
cmd/exec
type: command
default: none
Makes sydbox execute an external command without sandboxing. The program name and arguments must be
separated with the US
(unit separator, octal: 037) character.
sydfmt(1) may be used
to do this. Consult its manual page for more information.
This command can only be used with the magic stat
(2)
system call.
There are four sandboxing types:
Read sandboxing
Write sandboxing
execve(2) sandboxing
Network sandboxing
Sandboxing may have three states:
off
Sandboxing is off, none of the relevant system calls are checked and all access is allowed.
deny
Sandboxing defaults to deny, whitelists can be used to allow access.
allow
Sandboxing defaults to allow, blacklists can be used to deny access.
In addition, there are filters for every sandboxing to prevent Sydbox from reporting an access violation. Note, access is still denied in such cases.
This sandboxing checks certain system calls for filesystem write access. If a system call tries to write, modify or change attributes of a path, this attempt is reported and the system call is denied. There are two ways to customize this behaviour. Sydbox may be configured to "whitelist" some path patterns. If the path argument of the system call which is subject to be modified matches a pattern in the list of whitelisted path patterns, this attempt is not denied. Additionally, Sydbox may be configured to "filter" some path patterns. In this case a match will prevent Sydbox from reporting a warning about the access violation, the system call is still denied though.
List of observed system calls are:
access
(2),
faccessat
(2),
chmod
(2),
fchmodat
(2),
chown
(2),
chown32
(2),
lchown
(2),
lchown32
(2),
fchownat
(2),
open
(2),
openat
(2),
creat
(2),
mkdir
(2),
mkdirat
(2),
mknod
(2),
mknodat
(2),
rmdir
(2),
truncate
(2),
truncate64
(2),
mount
(2),
umount
(2),
umount2
(2),
utime
(2),
utimes
(2),
utimensat
(2),
futimesat
(2),
unlink
(2),
unlinkat
(2),
link
(2),
linkat
(2),
rename
(2),
renameat
(2),
symlink
(2),
symlinkat
(2),
setxattr
(2),
lsetxattr
(2),
removexattr
(2), and
lremovexattr
(2).
This sandboxing checks certain system calls for filesystem read access. If a system call tries to read a path, this attempt is reported and the system call is denied. See the section called “Write Sandboxing” for more information on how to customize this behaviour.
List of observed system calls are:
access
(2),
faccessat
(2),
open
(2),
openat
(2),
listxattr
(2), and
llistxattr
(2).
This sandboxing denies execve(2) calls in case the path argument does not match one of the whitelisted patterns. Note, all exec(3) family functions are sandboxed because these functions are just wrappers of the execve(2) system call.
This sandboxing exposes a way to prevent unwanted network calls. The observed system calls are:
bind
(2),
connect
(2), and
sendto
(2). To increase usability, these system calls are
observed in two groups: bind and connect.
bind
(2) belongs to the first group, whereas the other two
system calls belong to the connect group.
Sydbox uses shell-style pattern matching for whitelists and filters. The wildmatching code is borrowed from rsync and behaves like:
A '*' matches any path component, but it stops at slashes.
Use '**' to match anything, including slashes.
A '?' matches any character except a slash (/).
A "[" introduces a character class, such as [a-z] or [[:alpha:]].
In a wildcard pattern, a backslash can be used to escape a wildcard character, but it is matched literally when no wildcards are present.
A trailing "dir_name/***" will match both the directory (as if "dir_name/" had been specified) and everything in the directory (as if "dir_name/**" had been specified).
Sydbox checks patterns from multiple sources. There is no precedence between different sources, and the last matching pattern decides the outcome.
Sydbox has a simple address scheme to match network addresses. The addresses can be in the following forms:
Specifies a UNIX socket path, ${PATTERN}
specifies a path pattern.
See the section called “Pattern Matching” for more information on path patterns.
Specifies an abstract UNIX socket path, ${PATTERN}
specifies a path pattern.
See the section called “Pattern Matching” for more information on path patterns.
Specifies an IPV4 address. For more information, read the paragraph below.
Specifies an IPV6 address. For more information, read the paragraph below.
/${NETMASK}
may be omitted from inet:
and inet6:
addresses and ${PORT_RANGE}
can in two forms: either an integer or a service name from the
services(5) database. Either as
as a single entity or as a range in the form BEGIN-END.
In addition there are some aliases, you may use instead of specifying an address:
LOOPBACK
Expanded to inet:127.0.0.0/8
LOOPBACK6
Expanded to inet6:::1/8
LOCAL
Expanded to four addresses as defined in RFC1918:
inet:127.0.0.0/8
inet:10.0.0.0/8
inet:172.16.0.0/12
inet:192.168.0.0/16
LOCAL6
Expanded to four addresses:
inet6:::1
inet6:fe80::/7
inet6:fc00::/7
inet6:fec0::/7
Below are examples of invocation and configuration of Sydbox.
Below are some invocation examples:
Allow all reads, deny read access to /etc/shadow
:
$> sydbox -E LC_ALL=POSIX \ -m core/sandbox/read:allow \ -m blacklist/read+/etc/shadow \ -- /bin/sh -c 'cat /etc/shadow' sydbox@3141592653: -- Access Violation! -- sydbox@3141592653: process id=20926 (abi=0 name:`cat') sydbox@3141592653: cwd: `/home/alip' sydbox@3141592653: cmdline: `cat /etc/shadow' sydbox@3141592653: open(`/etc/shadow') cat: /etc/shadow: Operation not permitted $>
Deny all reads and writes, allow read access to /dev/zero
and write
access to /dev/full
. The executable dd is not static in this case thus
allow access to /lib64 where it will load its shared libraries from as well:
On the system of the author the dd binary links only to libraries under /lib64, use ldd to check the linked libraries on your system.
Note the quoting to escape shell expansion.
$> sydbox -E LC_ALL=POSIX \ -m core/sandbox/read:deny \ -m core/sandbox/write:deny \ -m 'whitelist/read+/lib64/***' \ -m whitelist/read+/dev/zero \ -m whitelist/read+/dev/full \ -- dd if=/dev/zero of=/dev/full count=1 dd: writing to '/dev/full': No space left on device 1+0 records in 0+0 records out 0 bytes (0 B) copied, 0.000447024 s, 0.0 kB/s $>
Kill common bittorrent applications:
The initial execve
is not checked.
$> sydbox -E LC_ALL=POSIX \ -m exec/kill_if_match+/usr/bin/ktorrent \ -m exec/kill_if_match+/usr/bin/rtorrent \ -- /bin/sh -c ktorrent sydbox@3141592653: callback_exec: kill_if_match pattern=`/usr/bin/ktorrent' matches execve path=`/usr/bin/ktorrent' sydbox@3141592653: callback_exec: killing process:3097 [abi:0 cwd:`/home/alip']
Execute a process without sandboxing so it will continue execution after sandboxing:
$> ./sydbox -- sh -c 'stat "$(./sydfmt exec echo hello world)"' hello world File: ‘/dev/sydbox/cmd/exec!echo\037hello\037world’ Size: 0 Blocks: 0 IO Block: 512 character special file Device: 0h/0d Inode: 0 Links: 0 Device type: 1,3 Access: (0666/crw-rw-rw-) Uid: ( 0/ root) Gid: ( 0/ root) $>
Sydbox dumps information about the traced process tree to standard error upon receiving the SIGUSR1 signal. Send SIGUSR2 signal for more verbose process information.
Report bugs by direct mail to <alip@exherbo.org>
Attaching poems encourages consideration tremendously.