aboutgitcodebugslistschat
path: root/passt.c
Commit message (Collapse)AuthorAgeFilesLines
* passt: Accurate error reporting for sandbox()Stefano Brivio2022-03-291-10/+26
| | | | | | | It's actually quite easy to make it fail depending on the environment, accurately report errors here. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* treewide: Fix android-cloexec-* clang-tidy warnings, re-enable checksStefano Brivio2022-03-291-4/+5
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* treewide: Mark constant references as constStefano Brivio2022-03-291-7/+7
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp_splice: Close sockets right away on high number of open filesStefano Brivio2022-03-291-1/+1
| | | | | | | | | | | | | We can't take for granted that the hard limit for open files is big enough as to allow to delay closing sockets to a timer. Store the value of RTLIMIT_NOFILE we set at start, and use it to understand if we're approaching the limit with pending, spliced TCP connections. If that's the case, close sockets right away as soon as they're not needed, instead of deferring this task to a timer. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Rework timers to use timerfd instead of periodic bitmap scanStefano Brivio2022-03-291-4/+8
| | | | | | | | | | | | | | | | | | With a lot of concurrent connections, the bitmap scan approach is not really sustainable. Switch to per-connection timerfd timers, set based on events and on two new flags, ACK_FROM_TAP_DUE and ACK_TO_TAP_DUE. Timers are added to the common epoll list, and implement the existing timeouts. While at it, drop the CONN_ prefix from flag names, otherwise they get quite long, and fix the logic to decide if a connection has a local, possibly unreachable endpoint: we shouldn't go through the rest of tcp_conn_from_tap() if we reset the connection due to a successful bind(2), and we'll get EACCES if the port number is low. Suggested by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Refactor to use events instead of states, split out spliced implementationStefano Brivio2022-03-281-2/+2
| | | | | | | | | | | | | | | | | | | | | Using events and flags instead of states makes the implementation much more straightforward: actions are mostly centered on events that occurred on the connection rather than states. An example is given by the ESTABLISHED_SOCK_FIN_SENT and FIN_WAIT_1_SOCK_FIN abominations: we don't actually care about which side started closing the connection to handle closing of connection halves. Split out the spliced implementation, as it has very little in common with the "regular" TCP path. Refactor things here and there to improve clarity. Add helpers to trace where resets and flag settings come from. No functional changes intended. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf, util, tap: Implement --trace option for extra verbose loggingStefano Brivio2022-03-251-1/+2
| | | | | | | | --debug can be a bit too noisy, especially as single packets or socket messages are logged: implement a new option, --trace, implying --debug, that enables all debug messages. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Run-time selection of AVX2 buildStefano Brivio2022-02-281-0/+3
| | | | | | | | | | | | | Build-time selection of AVX2 flags and routines is not practical for distributions, but limiting AVX2 usage to checksum routines with specific run-time detection doesn't allow for easy performance gains from auto-vectorisation of batched packet handling routines. For x86_64, build non-AVX2 and AVX2 binaries, and implement a simple wrapper replacing the current executable with the AVX2 build if it's available, and if AVX2 is supported by the current CPU. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* seccomp: Adjust list of allowed syscalls for armv6l, armv7lStefano Brivio2022-02-261-3/+5
| | | | | | | | | | | It looks like glibc commonly implements clock_gettime(2) with clock_gettime64(), and uses recv() instead of recvfrom(), send() instead of sendto(), and sigreturn() instead of rt_sigreturn() on armv6l and armv7l. Adjust the list of system calls for armv6l and armv7l accordingly. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Don't warn on failed madvise()Stefano Brivio2022-02-261-2/+1
| | | | | | | | A kernel might not be configured with CONFIG_TRANSPARENT_HUGEPAGE, especially on embedded systems. Ignore the error, it doesn't affect functionality. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Explicitly check return value of chdir()Stefano Brivio2022-02-251-1/+3
| | | | | | | | ...it doesn't actually matter as we're checking errno at the very end, but, depending on build flags, chdir() might be declared with warn_unused_result and the compiler issues a warning. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Drop PASST_LEGACY_NO_OPTIONS sectionsStefano Brivio2022-02-221-2/+0
| | | | | | ...nobody uses those builds anymore. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: By default, quit if filesystem-bound net namespace goes awayStefano Brivio2022-02-211-1/+6
| | | | | | | | | | | | This should be convenient for users managing filesystem-bound network namespaces: monitor the base directory of the namespace and exit if the namespace given as PATH or NAME target is deleted. We can't add an inotify watch directly on the namespace directory, that won't work with nsfs. Add an option to disable this behaviour, --no-netns-quit. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* Makefile, conf, passt: Drop passt4netns references, explicit argc checkStefano Brivio2022-02-211-2/+7
| | | | | | | | | | | Nobody currently calls this as passt4netns, that was the name I used before 'pasta', drop any reference before it's too late. While at it, explicitly check that argc is bigger than or equal to one, just as a defensive measure: argv[0] being NULL is not an issue anyway. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Make process not dumpable after sandboxingStefano Brivio2022-02-211-0/+2
| | | | | | | | | | | | | Two effects: - ptrace() on passt and pasta can only be done by root, so that even if somebody gains access to the same user, they won't be able to check data passed in syscalls anyway. No core dumps allowed either - /proc/PID files are owned by root:root, and they can't be read by the same user as the one passt or pasta are running with Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Namespace-based sandboxing, defer seccomp policy applicationStefano Brivio2022-02-211-47/+79
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | To reach (at least) a conceptually equivalent security level as implemented by --enable-sandbox in slirp4netns, we need to create a new mount namespace and pivot_root() into a new (empty) mountpoint, so that passt and pasta can't access any filesystem resource after initialisation. While at it, also detach IPC, PID (only for passt, to prevent vulnerabilities based on the knowledge of a target PID), and UTS namespaces. With this approach, if we apply the seccomp filters right after the configuration step, the number of allowed syscalls grows further. To prevent this, defer the application of seccomp policies after the initialisation phase, before the main loop, that's where we expect bad things to happen, potentially. This way, we get back to 22 allowed syscalls for passt and 34 for pasta, on x86_64. While at it, move #syscalls notes to specific code paths wherever it conceptually makes sense. We have to open all the file handles we'll ever need before sandboxing: - the packet capture file can only be opened once, drop instance numbers from the default path and use the (pre-sandbox) PID instead - /proc/net/tcp{,v6} and /proc/net/udp{,v6}, for automatic detection of bound ports in pasta mode, are now opened only once, before sandboxing, and their handles are stored in the execution context - the UNIX domain socket for passt is also bound only once, before sandboxing: to reject clients after the first one, instead of closing the listening socket, keep it open, accept and immediately discard new connection if we already have a valid one Clarify the (unchanged) behaviour for --netns-only in the man page. To actually make passt and pasta processes run in a separate PID namespace, we need to unshare(CLONE_NEWPID) before forking to background (if configured to do so). Introduce a small daemon() implementation, __daemon(), that additionally saves the PID file before forking. While running in foreground, the process itself can't move to a new PID namespace (a process can't change the notion of its own PID): mention that in the man page. For some reason, fork() in a detached PID namespace causes SIGTERM and SIGQUIT to be ignored, even if the handler is still reported as SIG_DFL: add a signal handler that just exits. We can now drop most of the pasta_child_handler() implementation, that took care of terminating all processes running in the same namespace, if pasta started a shell: the shell itself is now the init process in that namespace, and all children will terminate once the init process exits. Issuing 'echo $$' in a detached PID namespace won't return the actual namespace PID as seen from the init namespace: adapt demo and test setup scripts to reflect that. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, tap: Daemonise once socket is ready without waiting for connectionStefano Brivio2022-01-281-2/+4
| | | | | | | | | | | | | The existing behaviour is not really practical: an automated agent in charge of starting both qemu and passt would need to fork itself to start passt, because passt won't fork to background until qemu connects, and the agent needs to unblock to start qemu. Instead of waiting for a connection to daemonise, do it right away as soon as a socket is available: that can be considered an initialised state already. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* seccomp: Add a number of alternate and per-arch syscallsStefano Brivio2022-01-261-5/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Depending on the C library, but not necessarily in all the functions we use, statx() might be used instead of stat(), getdents() instead of getdents64(), readlinkat() instead of readlink(), openat() instead of open(). On aarch64, it's clone() and not fork(), and dup3() instead of dup2() -- just allow the existing alternative instead of dealing with per-arch selections. Since glibc commit 9a7565403758 ("posix: Consolidate fork implementation"), we need to allow set_robust_list() for fork()/clone(), even in a single-threaded context. On some architectures, epoll_pwait() is provided instead of epoll_wait(), but never both. Same with newfstat() and fstat(), sigreturn() and rt_sigreturn(), getdents64() and getdents(), readlink() and readlinkat(), unlink() and unlinkat(), whereas pipe() might not be available, but pipe2() always is, exclusively or not. Seen on Fedora 34: newfstatat() is used on top of fstat(). syslog() is an actual system call on some glibc/arch combinations, instead of a connect()/send() implementation. On ppc64 and ppc64le, _llseek(), recv(), send() and getuid() are used. For ppc64 only: ugetrlimit() for the getrlimit() implementation, plus sigreturn() and fcntl64(). On s390x, additionally, we need to allow socketcall() (on top of socket()), and sigreturn() also for passt (not just for pasta). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* Makefile, seccomp: Fix build for i386, ppc64, ppc64leStefano Brivio2022-01-261-1/+1
| | | | | | | | | | | | | | | | | On some distributions, on ppc64, ulimit -s returns 'unlimited': add a reasonable default, and also make sure ulimit is invoked using the default shell, which should ensure ulimit is actually implemented. Also note that AUDIT_ARCH doesn't follow closely the naming reported by 'uname -m': convert for i386 and ppc as needed. While at it, move inclusion of seccomp.h after util.h, the former is less generic (cosmetic/clang-tidy only). Older kernel headers might lack a definition for AUDIT_ARCH_PPC64LE: define that explicitly if it's not available. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Drop <linux/ipv6.h> include, carry own ipv6hdr and opt_hdr definitionsStefano Brivio2022-01-261-1/+0
| | | | | | | This is the only remaining Linux-specific include -- drop it to avoid clang-tidy warnings and to make code more portable. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* seccomp: Add newfstatat to list of allowed syscallsStefano Brivio2021-10-211-1/+1
| | | | | | | ...it looks like, on a recent Fedora installation, daemon() uses it. Reported-by: Giuseppe Scrivano <gscrivan@redhat.com> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Fork into background also if not running from a terminalStefano Brivio2021-10-211-1/+1
| | | | | | | | | This is actually annoying: there's no way to make it fork into background when running from a script. However, it's always possible to keep it in foreground with -f. Make it simpler, and always fork into background if -f is not given. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Add cppcheck target, test, and address resulting warningsStefano Brivio2021-10-211-3/+1
| | | | | | | ...mostly false positives, but a number of very relevant ones too, in tcp_get_sndbuf(), tcp_conn_from_tap(), and siphash PREAMBLE(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Fix build with gcc 7, use std=c99, enable some more Clang checkersStefano Brivio2021-10-211-18/+15
| | | | | | | | | | | | | | Unions and structs, you all have names now. Take the chance to enable bugprone-reserved-identifier, cert-dcl37-c, and cert-dcl51-cpp checkers in clang-tidy. Provide a ffsl() weak declaration using gcc built-in. Start reordering includes, but that's not enough for the llvm-include-order checker yet. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Address gcc 11 warningsStefano Brivio2021-10-201-4/+9
| | | | | | | | | A mix of unchecked return values, a missing permission mask for open(2) with O_CREAT, and some false positives from -Wstringop-overflow and -Wmaybe-uninitialized. Reported-by: Martin Hauke <mardnh@gmx.de> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Include linux/seccomp.h and linux/audit.h instead of seccomp.hStefano Brivio2021-10-191-1/+2
| | | | | | | We don't use libseccomp. Reported-by: Martin Hauke <mardnh@gmx.de> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Add clock_gettime to list of allowed syscallsStefano Brivio2021-10-161-0/+1
| | | | | | | ...depending on the system clock source, glibc might use it to fetch the wall time. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Static builds: don't redefine __vsyslog(), skip getpwnam() and ↵Stefano Brivio2021-10-161-5/+10
| | | | | | initgroups() Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Check if a PID file was actually requested before creating itStefano Brivio2021-10-151-1/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Don't refuse to run if UID is 0 in non-init namespaceStefano Brivio2021-10-141-1/+14
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf: Add -P, --pid, to specify a file where own PID is written toStefano Brivio2021-10-141-1/+24
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Warn if we're running as root, abort if we can't change to nobody:nobodyStefano Brivio2021-10-141-0/+29
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Drop all capabilities that we might have, except for CAP_NET_BIND_SERVICEStefano Brivio2021-10-141-0/+18
| | | | | | | | While it's not recommended to give passt any capability, drop all the ones we might have got by mistake, except for the only sensible one, CAP_NET_BIND_SERVICE. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Completely avoid dynamic memory allocationStefano Brivio2021-10-141-8/+8
| | | | | | | | | Replace libc functions that might dynamically allocate memory with own implementations or wrappers. Drop brk(2) from list of allowed syscalls in seccomp profile. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Add seccomp supportStefano Brivio2021-10-141-0/+36
| | | | | | | | | | | | | | | | | | List of allowed syscalls comes from comments in the form: #syscalls <list> for syscalls needed both in passt and pasta mode, and: #syscalls:pasta <list> #syscalls:passt <list> for syscalls specifically needed in pasta or passt mode only. seccomp.sh builds a list of BPF statements from those comments, prefixed by a binary search tree to keep lookup fast. While at it, clean up a bit the Makefile using wildcards. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* conf, tap: Split netlink and pasta functions, allow interface configurationStefano Brivio2021-10-141-181/+2
| | | | | | | | | | Move netlink routines to their own file, and use netlink to configure or fetch all the information we need, except for the TUNSETIFF ioctl. Move pasta-specific functions to their own file as well, add parameters and calls to configure the tap interface in the namespace. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: Add second waitid() in pasta_child_handler()Stefano Brivio2021-10-071-0/+1
| | | | | | | | We usually have up to one additional child exiting while we receive a SIGCHLD, instead of complicating this with tracking PIDs, just add a second waitid() call. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: Allow specifying paths and names of namespacesGiuseppe Scrivano2021-10-071-20/+39
| | | | | | | | | | | | | | | | | | Based on a patch from Giuseppe Scrivano, this adds the ability to: - specify paths and names of target namespaces to join, instead of a PID, also for user namespaces, with --userns - request to join or create a network namespace only, without entering or creating a user namespace, with --netns-only - specify the base directory for netns mountpoints, with --nsrun-dir Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> [sbrivio: reworked logic to actually join the given namespaces when they're not created, implemented --netns-only and --nsrun-dir, updated pasta demo script and man page] Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Shrink binary size by dropping static initialisersStefano Brivio2021-10-051-2/+6
| | | | | | ...from 11MiB to 155KiB for 'make avx2', 95KiB with -Os and stripped. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, tap: Turn tcp_probe_mem() into sock_probe_mem(), use for AF_UNIX socket tooStefano Brivio2021-10-051-0/+1
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Add handler for optional deferred tasksStefano Brivio2021-10-051-20/+26
| | | | | | | | We'll need this for TCP ACK coalescing on tap/guest-side. For convenience, allow _handler() functions to be undefined, courtesy of __attribute__((weak)). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Actually initialise timers for protocol handlersStefano Brivio2021-09-271-2/+16
| | | | | | | The initial timestamp was not initialised, so timers for protocol handlers wouldn't run at all sometimes. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Align pkt_buf to PAGE_SIZE (start and size), try to fit in huge pagesStefano Brivio2021-09-271-2/+6
| | | | | | | | | If transparent huge pages are available, madvise() will do the trick. While at it, decrease EPOLL_EVENTS for the main loop from 10 to 8, for slightly better socket fairness. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: Clean up namespace processes on exit, reap zombies from clone()Stefano Brivio2021-09-151-9/+83
| | | | | | | | | | | | If pasta created the namespace, it's probably expected that processes started in the same namespace are terminated once pasta exits. Scan procfs namespace links for corresponding processes, send SIGQUIT and SIGKILL (after one second) if found. While at it, make the signal handler reap otherwise-zombies resulting from clone(). Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: Set ping_group_range upon namespace creationStefano Brivio2021-09-091-0/+4
| | | | | | | ...this allows processes running as the only group available in the namespace to create ICMP Echo sockets. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt: Add epoll event indication and passt/pasta mode in socket debug messageStefano Brivio2021-09-091-1/+3
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* pasta: If a new namespace is created, wait for it to be ready before proceedingStefano Brivio2021-09-011-1/+15
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* passt, pasta: Introduce command-line options and port re-mappingStefano Brivio2021-09-011-423/+101
| | | | Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp: Introduce scatter-gather IO path from socket to tapStefano Brivio2021-07-261-0/+1
| | | | | | | | | | | | | | | | | ...similarly to what was done for UDP. Quick performance test with 32KiB buffers, host to VM: $ iperf3 -c 192.0.2.2 -N [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 8.47 GBytes 7.27 Gbits/sec 0 sender [ 5] 0.00-10.00 sec 8.45 GBytes 7.26 Gbits/sec receiver $ iperf3 -c 2a01:598:88ba:a056:271f:473a:c0d9:abc1 [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 8.43 GBytes 7.24 Gbits/sec 0 sender [ 5] 0.00-10.00 sec 8.41 GBytes 7.22 Gbits/sec receiver Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
* tcp, udp: Allow binding ports in init namespace to both tap and loopbackStefano Brivio2021-07-261-0/+15
| | | | | | | | Traffic with loopback source address will be forwarded to the direct loopback connection in the namespace, and the tap interface is used for the rest. Signed-off-by: Stefano Brivio <sbrivio@redhat.com>