Skip to content

Commit 8cc8682

Browse files
committed
BIN: Update build/sandbox-venv
1 parent 874fd40 commit 8cc8682

File tree

1 file changed

+150
-8
lines changed

1 file changed

+150
-8
lines changed

build/sandbox-venv

Lines changed: 150 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,15 @@ wrap_all () (
8989
echo "$file"
9090
done
9191

92+
# Install $venv/bin/shell
9293
file="$(realpath "$bin/shell")"
9394
add_bin_shell "$file"
9495
chmod +x "$file"
9596
echo "$file"
97+
98+
# Install PYTHONPATH=$venv/sandbox with sitecustomize.py
99+
mkdir -p "$bin/../sandbox"
100+
extract_segment 3 "$@" > "$bin/../sandbox/sitecustomize.py"
96101
)
97102

98103
wrap_all "$@"
@@ -184,8 +189,10 @@ executables="
184189
/bin/env
185190
/bin/ls
186191
/bin/sh
192+
187193
/bin/uname
188-
"
194+
/sbin/ldconfig
195+
"
189196
190197
case $- in *x*) xtrace=-x ;; *) xtrace=+x ;; esac; set +x
191198
@@ -215,7 +222,12 @@ py_libs="
215222
/usr/include/python3*
216223
/usr/lib/python3*
217224
/usr/lib64/python3*
218-
/usr/local/lib/python3*"
225+
/usr/local/lib/python3*
226+
227+
/usr/lib/python3*/*/seccomp.*.so
228+
/usr/lib/*/libseccomp.so*
229+
/usr/lib64/libseccomp.so*
230+
"
219231
git_libs="
220232
/usr/lib*/git-core
221233
"
@@ -232,7 +244,7 @@ ro_bind_extra="
232244
/etc/pki
233245
/etc/ssl
234246
/usr/share/pki*
235-
"
247+
"
236248
237249
collect="
238250
$collect
@@ -291,11 +303,13 @@ set -- --bind "$proj_dir" "$proj_dir" "$@"
291303
home="${HOME:-"/home/$USER"}"
292304
pip_cache="$home/${XDG_CACHE_HOME:-.cache}/pip"
293305
mkdir -p "$venv/cache" "$pip_cache"
294-
mkdir -p "$venv/cache/pip" &&
295-
echo "This is an artefact of Bubblewrap bind mounting. Real pip cache is in \$HOME/.cache/pip" \
296-
> "$venv/cache/pip/note.txt"
297-
set -- --bind "$venv/cache" "$home/.cache" \
298-
--bind "$pip_cache" "$home/.cache/pip" "$@"
306+
[ ! "${SANDBOX_USE_PIP_CACHE-}" ] || {
307+
mkdir -p "$venv/cache/pip" &&
308+
echo "This dir is an artefact of Bubblewrap bind mounting. Real pip cache is in \$HOME/.cache/pip" \
309+
> "$venv/cache/pip/note.txt"
310+
set -- --bind "$pip_cache" "$home/.cache/pip" "$@"
311+
}
312+
set -- --bind "$venv/cache" "$home/.cache" "$@"
299313
300314
# Pass our own redacted copy of env
301315
for var in $(env | grep -E '^(USER|LOGNAME|UID|PATH|TERM|LANGUAGE|LANG|LC_.*?|HOSTNAME)='); do
@@ -328,4 +342,132 @@ exec bwrap \
328342
--setenv HOME "$home" \
329343
--setenv USER "user" \
330344
--setenv VIRTUAL_ENV "$venv" \
345+
--setenv PYTHONPATH "$venv/sandbox:${PYTHONPATH-}" \
331346
"$@"
347+
348+
349+
# CUT HERE ------------------- Appendix 3: sandbox-venv sitecustomize.py script
350+
#!/usr/bin/python3
351+
"""
352+
Importing this module inits seccomp/pyseccomp, restricting allowed syscalls to those
353+
listed in SANDBOX_SECCOMP_ALLOW environment variable (or, by default, the list below).
354+
The module is imported automatically upon startup when on PYTHONPATH.
355+
356+
https://docs.python.org/3/library/site.html#module-sitecustomize
357+
"""
358+
import os
359+
import re
360+
import sys
361+
362+
# XXX: You can debug this list (e.g. update missing items) by
363+
# looking for EPERM in `strace -f` output.
364+
ALLOW_SYSCALLS = [
365+
# Process & signals
366+
"clone", "clone3", "fork", "vfork", "execve", "exit", "exit_group",
367+
"kill", "tgkill", "tkill", "wait4", "getpid", "getppid", "gettid",
368+
"prctl", "arch_prctl", "getpgrp",
369+
"pidfd_open", "pidfd_send_signal",
370+
"sigaction", "sigreturn",
371+
"rt_sigaction", "rt_sigreturn",
372+
"rt_sigprocmask", "rt_sigpending", "rt_sigsuspend",
373+
"sigaltstack", "rseq", "process_madvise",
374+
375+
# File I/O
376+
"open", "openat", "close", "close_range", "read", "write",
377+
"name_to_handle_at",
378+
"pread64", "pwrite64", "preadv", "pwritev", "preadv2", "pwritev2",
379+
"lseek",
380+
"stat", "statx", "fstat", "lstat", "fstatat64", "newfstatat",
381+
"stat64", "lstat64", "fstat64", "fadvise64",
382+
"faccessat2", "getdents", "getdents64", "access",
383+
"unlink", "unlinkat", "mkdir", "mkdirat", "rmdir",
384+
"rename", "renameat", "renameat2",
385+
"readlink", "readlinkat", "symlink", "symlinkat", "link", "linkat",
386+
"truncate", "ftruncate", "utime", "utimes", "futimesat", "utimensat",
387+
"chown", "fchown", "lchown", "fchmod", "fchmodat", "chmod", "mknod", "mknodat",
388+
"getxattr", "setxattr", "listxattr", "removexattr",
389+
390+
# fd ops
391+
"dup", "dup2", "dup3", "pipe", "pipe2",
392+
"fcntl", "flock", "fsync", "fdatasync",
393+
"readahead",
394+
"splice", "tee", "vmsplice",
395+
396+
# mmap / mem / threads
397+
"brk", "mmap", "mmap2", "munmap", "mremap", "mprotect", "madvise", "mincore",
398+
"futex", "futex_time64", "futex_waitv", "set_tid_address", "set_robust_list", "get_robust_list",
399+
"sched_yield", "sched_getaffinity",
400+
"mlock", "munlock", "mlockall", "munlockall",
401+
"get_mempolicy", "set_mempolicy", "mbind", "migrate_pages", "move_pages",
402+
"membarrier",
403+
404+
# Time / clocks
405+
"nanosleep", "clock_gettime", "clock_getres", "gettimeofday", "time",
406+
"clock_nanosleep", "clock_gettime64",
407+
"timer_create", "timer_settime", "timer_gettime", "timer_delete",
408+
"setitimer", "getitimer", "times",
409+
"timerfd_create", "timerfd_settime", "timerfd_gettime",
410+
411+
# Networking
412+
"socket", "socketpair", "socketcall", "bind", "listen",
413+
"accept", "accept4", "connect",
414+
"getsockname", "getpeername",
415+
"sendto", "recvfrom", "sendmsg", "recvmsg", "shutdown",
416+
"setsockopt", "getsockopt",
417+
"recvmmsg", "sendmmsg",
418+
"sendfile", "sendfile64",
419+
420+
# epoll/poll/select
421+
"epoll_create", "epoll_create1", "epoll_ctl", "epoll_wait",
422+
"epoll_pwait", "epoll_pwait2",
423+
"poll", "ppoll", "ppoll_time64", "select", "pselect6",
424+
"eventfd", "eventfd2",
425+
426+
# Descriptors / metadata
427+
"ioctl", "readv", "writev",
428+
"getcwd", "chdir", "fchdir",
429+
"statfs", "fstatfs", "statfs64", "fstatfs64",
430+
431+
# UIDs/GIDs (read + drop privileges)
432+
"getuid", "geteuid", "getgid", "getegid", "getgroups",
433+
"getresuid", "getresgid", "setresuid", "setresgid", "setreuid", "setregid",
434+
"setuid", "setgid",
435+
436+
# Limits / info
437+
"getrlimit", "setrlimit", "prlimit64", "uname", "sysinfo", "getrusage", "umask",
438+
439+
# Random
440+
"getrandom",
441+
442+
# Misc
443+
"seccomp", "capget",
444+
"shmget", "shmat", "shmdt", "shmctl",
445+
]
446+
447+
448+
try:
449+
allow_syscalls = re.findall(r'\w+', os.environ['SANDBOX_SECCOMP_ALLOW'])
450+
except KeyError:
451+
allow_syscalls = ALLOW_SYSCALLS
452+
453+
if allow_syscalls:
454+
try:
455+
import seccomp
456+
except ImportError:
457+
try:
458+
import pyseccomp as seccomp
459+
except ImportError:
460+
seccomp = None
461+
if sys.platform.startswith('linux'):
462+
print("sandbox-venv/seccomp: Python package 'seccomp' (or 'pyseccomp') "
463+
"not available. If you want seccomp support, apt install python3-seccomp "
464+
"(requires venv created with --system-site-packages) "
465+
"or pip install pyseccomp.", file=sys.stderr)
466+
if seccomp:
467+
print(f'sandbox-venv/seccomp: allowing {len(allow_syscalls)} syscalls', file=sys.stderr)
468+
default_action = seccomp.ERRNO(seccomp.errno.EPERM) # EPERM, Operation not permitted
469+
filter = seccomp.SyscallFilter(default_action)
470+
for syscall in allow_syscalls:
471+
# print(syscall, file=sys.stderr)
472+
filter.add_rule(seccomp.ALLOW, syscall)
473+
filter.load()

0 commit comments

Comments
 (0)