public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH v2 00/32] Improve handling of test temporary files
@ 2022-09-08  6:15 David Gibson
  2022-09-08  6:15 ` [PATCH v2 01/32] test: Correctly match "background" with "wait" commands David Gibson
                   ` (31 more replies)
  0 siblings, 32 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5688 bytes --]

The tests create temporary files and fifos in a number of places.
Some of them can interfere with later test runs, and are awkward to
clean up.  Consolidate them in a single per-run directory in /tmp
which gets cleaned up automatically.

This is based on the earlier userns cleanup series.

Chances since v1:
 * Fixed a number of straightforward bugs where things were missed
 * Also removed files we're no longer putting into the source tree
   from .gitignore
 * Added an extra patch moving the video processing files

David Gibson (32):
  test: Correctly match "background" with "wait" commands
  test: Context execution helpers
  test: Allow a tmux pane to watch commands executed in contexts
  test: Integration of old-style pane execution and new context
    execution
  test: Issue host commands via context for most tests
  test: Use new-style contexts for passt pane in the pasta and passt
    tests
  test: Add nsholder utility
  test: Extend context system to run commands in namespace for pasta
    tests
  test: Use context system for guest commands
  test: Use context system for two_guests tests
  test: Use new-style command issue for passt_in_ns tests
  Don't store UID & GID persistently in the context structure
  Split checking for root from dropping root privilege
  Consolidate determination of UID/GID to run as
  Safer handling if we can't open /proc/self/uid_map
  Move self-isolation code into a separate file
  Consolidate validation of pasta namespace options
  Clean up and rename conf_ns_open()
  Correctly handle --netns-only in pasta_start_ns()
  Handle userns isolation and dropping root at the same time
  Allow --userns when pasta spawns a command
  test: Group tests by context then protocol, rather than the reverse
  test: Remove unused variable FFMPEG_PID_FILE
  test: Actually run cleanup function
  test: Create common state directories for temporary files
  test: Move context temporary files to state dir
  test: Dont regnerate small test file in pasta/tcp
  test: Use paths in __STATEDIR__ instead of 'temp' and 'tempdir'
    directives
  test: Move pause temporary file to state directory
  test: Store pcap files in $LOGDIR instead of /tmp
  test: Move pidfiles and nsholder sockets into state directory
  test: Move video processing files to $STATEBASE

 .gitignore                                    |   1 -
 Makefile                                      |   8 +-
 conf.c                                        | 236 +++++++-------
 isolation.c                                   | 210 +++++++++++++
 isolation.h                                   |  15 +
 passt.1                                       |   5 +-
 passt.c                                       | 116 +------
 passt.h                                       |   9 -
 pasta.c                                       |  91 ++++--
 pasta.h                                       |   1 +
 test/.gitignore                               |   6 +-
 test/Makefile                                 |  13 +-
 test/build/all                                |  31 +-
 test/demo/passt                               |   9 +-
 test/demo/pasta                               |  12 +-
 test/demo/podman                              |  11 +-
 test/distro/debian                            |   2 +-
 test/distro/fedora                            |   2 +-
 test/distro/opensuse                          |  16 +-
 test/distro/ubuntu                            |   8 +-
 test/lib/context                              | 128 ++++++++
 test/lib/layout                               |  61 ++--
 test/lib/setup                                | 296 +++++++++---------
 test/lib/term                                 |  98 +++++-
 test/lib/test                                 | 152 ++++-----
 test/lib/video                                |  20 +-
 test/nsholder.c                               | 117 +++++++
 test/passt.mbuto                              |  32 +-
 test/{dhcp/passt => passt/dhcp}               |   2 +-
 test/{ndp/passt => passt/ndp}                 |   2 +-
 test/{shutdown/passt => passt/shutdown}       |   8 +-
 test/{tcp/passt => passt/tcp}                 |   8 +-
 test/{udp/passt => passt/udp}                 |   9 +-
 test/{icmp/passt_in_ns => passt_in_ns/icmp}   |   2 +-
 .../passt_in_ns => passt_in_ns/shutdown}      |   8 +-
 test/{tcp/passt_in_ns => passt_in_ns/tcp}     |  27 +-
 test/{udp/passt_in_ns => passt_in_ns/udp}     |  13 +-
 test/{dhcp/pasta => pasta/dhcp}               |   2 +-
 test/{ndp/pasta => pasta/ndp}                 |   2 +-
 test/{tcp/pasta => pasta/tcp}                 |  14 +-
 test/{udp/pasta => pasta/udp}                 |  21 +-
 test/run                                      |  42 +--
 util.c                                        |  83 -----
 util.h                                        |   2 -
 44 files changed, 1159 insertions(+), 792 deletions(-)
 create mode 100644 isolation.c
 create mode 100644 isolation.h
 create mode 100644 test/lib/context
 create mode 100644 test/nsholder.c
 rename test/{dhcp/passt => passt/dhcp} (98%)
 rename test/{ndp/passt => passt/ndp} (95%)
 rename test/{shutdown/passt => passt/shutdown} (75%)
 rename test/{tcp/passt => passt/tcp} (95%)
 rename test/{udp/passt => passt/udp} (88%)
 rename test/{icmp/passt_in_ns => passt_in_ns/icmp} (94%)
 rename test/{shutdown/passt_in_ns => passt_in_ns/shutdown} (75%)
 rename test/{tcp/passt_in_ns => passt_in_ns/tcp} (97%)
 rename test/{udp/passt_in_ns => passt_in_ns/udp} (97%)
 rename test/{dhcp/pasta => pasta/dhcp} (96%)
 rename test/{ndp/pasta => pasta/ndp} (95%)
 rename test/{tcp/pasta => pasta/tcp} (95%)
 rename test/{udp/pasta => pasta/udp} (74%)

-- 
2.37.3


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 01/32] test: Correctly match "background" with "wait" commands
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 02/32] test: Context execution helpers David Gibson
                   ` (30 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 4021 bytes --]

Our test DSL has a number of paired commands to run something in the
background in a pane, then later to wait for it to complete.  However, in
some of the tests we have these mismatched - starting a command in one
pane, then waiting for it in another.

We appear to get away with this for some reason, but it's not correct and
future changes make it cause more problems.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/tcp/passt_in_ns | 8 ++++----
 test/tcp/pasta       | 1 -
 test/udp/passt_in_ns | 4 ++--
 test/udp/pasta       | 1 -
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index ab22485..976e4e9 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -44,7 +44,7 @@ check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 test	TCP/IPv4: guest to ns: big transfer
 nsb	socat -u TCP4-LISTEN:10002 OPEN:__TEMP_BIG__,create,trunc
 guest	socat -u OPEN:test_big.bin TCP4:__GW__:10002
-hostw
+nsw
 hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
@@ -108,7 +108,7 @@ check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 test	TCP/IPv4: guest to ns: small transfer
 nsb	socat -u TCP4-LISTEN:10002 OPEN:__TEMP_SMALL__,create,trunc
 guest	socat -u OPEN:test_small.bin TCP4:__GW__:10002
-hostw
+nsw
 hout	HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
 check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
@@ -167,7 +167,7 @@ check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 test	TCP/IPv6: guest to ns: big transfer
 nsb	socat -u TCP6-LISTEN:10002 OPEN:__TEMP_BIG__,create,trunc
 guest	socat -u OPEN:test_big.bin TCP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
 hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
@@ -227,7 +227,7 @@ check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 test	TCP/IPv6: guest to ns: small transfer
 nsb	socat -u TCP6-LISTEN:10002 OPEN:__TEMP_SMALL__
 guest	socat -u OPEN:test_small.bin TCP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
 hout	HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
 check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
diff --git a/test/tcp/pasta b/test/tcp/pasta
index 0d6c729..a13a2ff 100644
--- a/test/tcp/pasta
+++ b/test/tcp/pasta
@@ -80,7 +80,6 @@ ns	socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10003
 hostw
 hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
-nsw
 
 test	TCP/IPv6: ns to host (via tap): big transfer
 hostb	socat -u TCP6-LISTEN:10003 OPEN:__TEMP_BIG__,create,trunc
diff --git a/test/udp/passt_in_ns b/test/udp/passt_in_ns
index 8f8090b..f5ea402 100644
--- a/test/udp/passt_in_ns
+++ b/test/udp/passt_in_ns
@@ -45,7 +45,7 @@ check	[ "__HOST_MD5__" = "__MD5__" ]
 test	UDP/IPv4: guest to ns
 nsb	(socat -u UDP4-LISTEN:10002 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 guest	socat -u OPEN:test.bin UDP4:__GW__:10002
-hostw
+nsw
 hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
@@ -106,7 +106,7 @@ check	[ "__HOST_MD5__" = "__MD5__" ]
 test	UDP/IPv6: guest to ns
 nsb	(socat -u UDP6-LISTEN:10002 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 guest	socat -u OPEN:test.bin UDP6:[__GW6__%__IFNAME__]:10002
-hostw
+nsw
 hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
diff --git a/test/udp/pasta b/test/udp/pasta
index 25063ea..0767e0b 100644
--- a/test/udp/pasta
+++ b/test/udp/pasta
@@ -58,7 +58,6 @@ ns	socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
 hostw
 hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
-nsw
 
 test	UDP/IPv6: ns to host (via tap)
 hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
-- 
@@ -58,7 +58,6 @@ ns	socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
 hostw
 hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
-nsw
 
 test	UDP/IPv6: ns to host (via tap)
 hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 02/32] test: Context execution helpers
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
  2022-09-08  6:15 ` [PATCH v2 01/32] test: Correctly match "background" with "wait" commands David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 03/32] test: Allow a tmux pane to watch commands executed in contexts David Gibson
                   ` (29 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 3448 bytes --]

For the tests, we need to run commands in various contexts: in the host,
in a guest or in a namespace.  Currently we do this by running each context
in a tmux pane, and using tmux commands to type the commands into the
relevant pane, then screen-scrape the output for the results if we need
them.

This is very fragile, because we have to make various assumptions to parse
the output.  Those can break if a shell doesn't have the prompt we expect,
if the tmux pane is too small or in various other conditions.

This starts some library functions for a new "context" system, that
provides a common way to invoke commands in a given context, in a way that
properly preserves stdout, stderr and the process return code.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/context | 80 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 test/lib/context

diff --git a/test/lib/context b/test/lib/context
new file mode 100644
index 0000000..babf59a
--- /dev/null
+++ b/test/lib/context
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# PASST - Plug A Simple Socket Transport
+#  for qemu/UNIX domain socket mode
+#
+# PASTA - Pack A Subtle Tap Abstraction
+#  for network namespace/tap device mode
+#
+# test/lib/context - Run commands in different contexts (host, guest, namespace etc.)
+#
+# Copyright Red Hat
+# Author: David Gibson <david(a)gibson.dropbear.id.au>
+
+# context_setup_host() - Create a new context for running commands on the host
+# $1:	Context name
+context_setup_host() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	echo sh -c > "${__prefix}.enter"
+	echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_teardown() - Remove a context (leave log files intact)
+# $1:	Context name
+context_teardown() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	rm -f "${__prefix}.enter"
+}
+
+# context_exists() - Test if a context currently exists
+# $1:	Context name
+context_exists() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	[ -f "${__prefix}.enter" ]
+}
+
+# context_run() - Run a shell command in a context, and wait for it to finish
+# $1:	Context name
+# $*:	Command to start
+context_run() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	__enter="$(cat "${__prefix}.enter")"
+	shift
+	echo "$*" >> "${__prefix}.log"
+	mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
+	tee -a "${__prefix}.log" < "${__prefix}.stdout" &
+	tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
+	${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+	rc=$?
+	rm "${__prefix}.stdout" "${__prefix}.stderr"
+	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
+	echo -n "${__name}$ " >> "${__prefix}.log"
+	return $rc
+}
+
+# context_run_bg() - Start a shell command in a context
+# $1:	Context name
+# $*:	Command to start
+context_run_bg() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	context_run "$@" &
+	echo $! > "${__prefix}.pid"
+}
+
+# context_wait() - Wait for background command in a context to complete
+# $1:	Context name
+# Returns the status of the completed command
+context_wait() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	__pid=$(cat "${__prefix}.pid")
+	rm "${__prefix}.pid"
+	wait ${__pid}
+}
-- 
@@ -0,0 +1,80 @@
+#! /bin/sh
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# PASST - Plug A Simple Socket Transport
+#  for qemu/UNIX domain socket mode
+#
+# PASTA - Pack A Subtle Tap Abstraction
+#  for network namespace/tap device mode
+#
+# test/lib/context - Run commands in different contexts (host, guest, namespace etc.)
+#
+# Copyright Red Hat
+# Author: David Gibson <david(a)gibson.dropbear.id.au>
+
+# context_setup_host() - Create a new context for running commands on the host
+# $1:	Context name
+context_setup_host() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	echo sh -c > "${__prefix}.enter"
+	echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_teardown() - Remove a context (leave log files intact)
+# $1:	Context name
+context_teardown() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	rm -f "${__prefix}.enter"
+}
+
+# context_exists() - Test if a context currently exists
+# $1:	Context name
+context_exists() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	[ -f "${__prefix}.enter" ]
+}
+
+# context_run() - Run a shell command in a context, and wait for it to finish
+# $1:	Context name
+# $*:	Command to start
+context_run() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	__enter="$(cat "${__prefix}.enter")"
+	shift
+	echo "$*" >> "${__prefix}.log"
+	mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
+	tee -a "${__prefix}.log" < "${__prefix}.stdout" &
+	tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
+	${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+	rc=$?
+	rm "${__prefix}.stdout" "${__prefix}.stderr"
+	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
+	echo -n "${__name}$ " >> "${__prefix}.log"
+	return $rc
+}
+
+# context_run_bg() - Start a shell command in a context
+# $1:	Context name
+# $*:	Command to start
+context_run_bg() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	context_run "$@" &
+	echo $! > "${__prefix}.pid"
+}
+
+# context_wait() - Wait for background command in a context to complete
+# $1:	Context name
+# Returns the status of the completed command
+context_wait() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	__pid=$(cat "${__prefix}.pid")
+	rm "${__prefix}.pid"
+	wait ${__pid}
+}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 03/32] test: Allow a tmux pane to watch commands executed in contexts
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
  2022-09-08  6:15 ` [PATCH v2 01/32] test: Correctly match "background" with "wait" commands David Gibson
  2022-09-08  6:15 ` [PATCH v2 02/32] test: Context execution helpers David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 04/32] test: Integration of old-style pane execution and new context execution David Gibson
                   ` (28 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 1614 bytes --]

We're moving to a new way of the tests dispatching commands to running in
contexts (host, guest, namespace, etc.).  As we make this transition,
though, we still want the user to be able to watch the commands running
in a context, as they previously could from the commands issued in the
pane.

Add a helper to set up a pane to watch a context's log to allow this.  In
some cases we currently issue commands from several different logical
contexts in the same pane, so allow a pane to watch several contexts at
once.  Also use tail's --retry option to allow starting the watch before
we've initialized the context which will be useful in some cases.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/term | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/test/lib/term b/test/lib/term
index ddabf8d..fa34873 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -241,6 +241,24 @@ pane_status() {
 	return ${__status}
 }
 
+# pane_watch_context() - Set up pane to watch commands executing in context(s)
+# $1:	Pane number
+# $2:	Description (for pane label)
+# $@:	Context name or names
+pane_watch_contexts() {
+	__pane_number="${1}"
+	__desc="${2}"
+	shift 2
+	__name="${2}"
+
+	tmux select-pane -t ${__pane_number} -T "${__desc}"
+	__cmd="tail -f --retry"
+	for c; do
+	    __cmd="${__cmd} ${LOGDIR}/context_${c}.log"
+	done
+	cmd_write ${__pane_number} "${__cmd}"
+}
+
 # status_file_end() - Display and log messages when tests from one file are done
 status_file_end() {
 	[ -z "${STATUS_FILE}" ] && return
-- 
@@ -241,6 +241,24 @@ pane_status() {
 	return ${__status}
 }
 
+# pane_watch_context() - Set up pane to watch commands executing in context(s)
+# $1:	Pane number
+# $2:	Description (for pane label)
+# $@:	Context name or names
+pane_watch_contexts() {
+	__pane_number="${1}"
+	__desc="${2}"
+	shift 2
+	__name="${2}"
+
+	tmux select-pane -t ${__pane_number} -T "${__desc}"
+	__cmd="tail -f --retry"
+	for c; do
+	    __cmd="${__cmd} ${LOGDIR}/context_${c}.log"
+	done
+	cmd_write ${__pane_number} "${__cmd}"
+}
+
 # status_file_end() - Display and log messages when tests from one file are done
 status_file_end() {
 	[ -z "${STATUS_FILE}" ] && return
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 04/32] test: Integration of old-style pane execution and new context execution
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (2 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 03/32] test: Allow a tmux pane to watch commands executed in contexts David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 05/32] test: Issue host commands via context for most tests David Gibson
                   ` (27 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 12123 bytes --]

We're creating a system for tests to more reliably execute commands in
various contexts (e.g. host, guest, namespace).  That transition is going
to happen over a number of steps though, so in the meantime we need to deal
with both the old-style issuing of commands via typing into and screen
scraping tmux panels, and the new-style system for executing commands in
context.

Introduce some transitional helpers which will issue a command via context
if the requested context is initialized, but will otherwise fall back to
the old style tmux panel based method.  Re-implement the various test DSL
commands in terms of these new helpers.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/term |  63 +++++++++++++++++++++++
 test/lib/test | 138 +++++++++++++++++++++-----------------------------
 test/run      |   1 +
 3 files changed, 121 insertions(+), 81 deletions(-)

diff --git a/test/lib/term b/test/lib/term
index fa34873..a06c80b 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -259,6 +259,69 @@ pane_watch_contexts() {
 	cmd_write ${__pane_number} "${__cmd}"
 }
 
+# pane_or_context_run() - Issue a command in given context or pane
+# $1:	Context or lower-case pane name
+# $@:	Command to issue
+pane_or_context_run() {
+	__name="${1}"
+	shift
+	if context_exists "${__name}"; then
+		context_run "${__name}" "$@" >/dev/null 2>&1
+	else
+		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+		pane_run "${__uc}" "$@"
+		pane_status "${__uc}"
+	fi
+}
+
+# pane_or_context_run_bg() - Issue a background command in given context or pane
+# $1:	Context or lower-case pane name
+# $@:	Command to issue
+pane_or_context_run_bg() {
+	__name="${1}"
+	shift
+	if context_exists "${__name}"; then
+		context_run_bg "${__name}" "$@" >/dev/null 2>&1
+	else
+		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+		pane_run "${__uc}" "$@"
+	fi
+}
+
+# pane_or_context_output() - Get output from a command in a context or pane
+# $1:	Context or lower-case pane name
+# $@:	Command to issue
+pane_or_context_output() {
+	__name="${1}"
+	shift
+	if context_exists "${__name}"; then
+		__output=$(context_run "${__name}" "$@" 2>/dev/null)
+		if [ -z "${__output}" ]; then
+			echo "@EMPTY@"
+		else
+			echo "${__output}"
+		fi
+	else
+		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+		pane_run "${__uc}" "$@"
+		pane_wait "${__uc}"
+		pane_parse "${__uc}"
+	fi
+}
+
+# pane_or_context_wait() - Wait for a command to be done in a context or pane
+# $1:	Context or lower-case pane name
+pane_or_context_wait() {
+	__name="${1}"
+	shift
+	if context_exists "${__name}"; then
+		context_wait "${__name}"
+	else
+		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
+		pane_wait "${__uc}"
+	fi
+}
+
 # status_file_end() - Display and log messages when tests from one file are done
 status_file_end() {
 	[ -z "${STATUS_FILE}" ] && return
diff --git a/test/lib/test b/test/lib/test
index 5a6c01c..0d06afd 100755
--- a/test/lib/test
+++ b/test/lib/test
@@ -15,8 +15,8 @@
 
 # test_iperf3() - Ugly helper for iperf3 directive
 # $1:	Variable name: to put the measure bandwidth into
-# $2:	Source/client pane name, can be lowercase
-# $3:	Destination/server pane name, can be lowercase
+# $2:	Source/client context
+# $3:	Destination/server context
 # $4:	Destination name or address for client
 # $5:	Port number, ${i} is translated to process index
 # $6:	Number of processes to run in parallel
@@ -24,14 +24,14 @@
 # $@:	Client options
 test_iperf3() {
 	__var="${1}"; shift
-	__cpane="$(echo "${1}" | tr [a-z] [A-Z])"; shift
-	__spane="$(echo "${1}" | tr [a-z] [A-Z])"; shift
+	__cctx="${1}"; shift
+	__sctx="${1}"; shift
 	__dest="${1}"; shift
 	__port="${1}"; shift
 	__procs="$((${1} - 1))"; shift
 	__time="${1}"; shift
 
-	pane_run "${__spane}" 						\
+	pane_or_context_run_bg "${__sctx}" 				\
 		 '('							\
 		 '	for i in $(seq 0 '${__procs}'); do'		\
 		 '		iperf3 -s1J -p'${__port}' -i'${__time}	\
@@ -40,7 +40,9 @@ test_iperf3() {
 		 '	wait'						\
 		 ')'
 
-	pane_run "${__cpane}" 						\
+	sleep 1		# Wait for server to be ready
+
+	pane_or_context_run "${__cctx}" 				\
 		 '('							\
 		 '	for i in $(seq 0 '${__procs}'); do'		\
 		 '		iperf3 -c '${__dest}' -p '${__port}	\
@@ -49,8 +51,7 @@ test_iperf3() {
 		 '	wait'						\
 		 ')'
 
-	pane_status "${__cpane}"
-	pane_status "${__spane}"
+	pane_or_context_wait "${__sctx}"
 
 	__jval=".end.sum_received.bits_per_second"
 	for __opt in ${@}; do
@@ -58,14 +59,10 @@ test_iperf3() {
 		[ "${__opt}" = "-u" ] && __jval=".intervals[0].sum.bits_per_second"
 	done
 
-	pane_run "${__spane}"						\
-		 'cat s*.json | jq -rMs "map('${__jval}') | add"'
-	pane_wait "${__spane}"
-	__bw="$(pane_parse "${__spane}")"
-
-	pane_run "${__spane}"						\
+	__bw=$(pane_or_context_output "${__sctx}"			\
+		 'cat s*.json | jq -rMs "map('${__jval}') | add"')
+	pane_or_context_run "${__sctx}"					\
 		'for i in $(seq 0 '${__procs}'); do rm s${i}.json; done'
-	pane_status "${__spane}"
 
 	TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__var}__" "${__bw}" )"
 }
@@ -122,155 +119,134 @@ test_one_line() {
 		TEST_ONE_perf_nok=0
 		;;
 	"host")
-		pane_run HOST "${__arg}"
-		pane_status HOST || TEST_ONE_nok=1
+		pane_or_context_run host "${__arg}" || TEST_ONE_nok=1
 		;;
 	"hostb")
-		pane_run HOST "${__arg}"
+		pane_or_context_run_bg host "${__arg}"
 		;;
 	"hostw")
-		pane_status HOST || TEST_ONE_nok=1
+		pane_or_context_wait host || TEST_ONE_nok=1
 		;;
 	"hint")
 		tmux send-keys -t ${PANE_HOST} "C-c"
 		;;
 	"htools")
-		pane_run HOST 'which '"${__arg}"' >/dev/null'
-		pane_status HOST || TEST_ONE_skip=1
+		pane_or_context_run host 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
 		;;
 	"passt")
-		pane_run PASST "${__arg}"
-		pane_status PASST || TEST_ONE_nok=1
+		pane_or_context_run passt "${__arg}" || TEST_ONE_nok=1
 		;;
 	"passtb")
-		pane_run PASST "${__arg}"
+		pane_or_context_run_bg passt "${__arg}"
 		;;
 	"passtw")
-		pane_status PASST || TEST_ONE_nok=1
+		pane_or_context_wait passt || TEST_ONE_nok=1
 		;;
 	"pout")
 		__varname="${__arg%% *}"
-		pane_run PASST "${__arg#* }"
-		pane_wait PASST
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse PASST)")"
+		__output="$(pane_or_context_output passt "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"guest")
-		pane_run GUEST "${__arg}"
-		pane_status GUEST || TEST_ONE_nok=1
+		pane_or_context_run guest "${__arg}" || TEST_ONE_nok=1
 		;;
 	"guestb")
-		pane_run GUEST "${__arg}"
+		pane_or_context_run_bg guest "${__arg}"
 		;;
 	"guestw")
-		pane_status GUEST || TEST_ONE_nok=1
+		pane_or_context_wait guest || TEST_ONE_nok=1
 		;;
 	"guest1")
-		pane_run GUEST_1 "${__arg}"
-		pane_status GUEST_1 || TEST_ONE_nok=1
+		pane_or_context_run guest_1 "${__arg}" || TEST_ONE_nok=1
 		;;
 	"guest1b")
-		pane_run GUEST_1 "${__arg}"
+		pane_or_context_run_bg guest_1 "${__arg}"
 		;;
 	"guest1w")
-		pane_status GUEST_1 || TEST_ONE_nok=1
+		pane_or_context_wait guest_1 || TEST_ONE_nok=1
 		;;
 	"gtools")
-		pane_run GUEST 'which '"${__arg}"' >/dev/null'
-		pane_status GUEST || TEST_ONE_skip=1
+		pane_or_context_run guest 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
 		;;
 	"g1tools")
-		pane_run GUEST_1 'which '"${__arg}"' >/dev/null'
-		pane_status GUEST_1 || TEST_ONE_skip=1
+		pane_or_context_run guest_1 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
 		;;
 	"g2tools")
-		pane_run GUEST_2 'which '"${__arg}"' >/dev/null'
-		pane_status GUEST_2 || TEST_ONE_skip=1
+		pane_or_context_run guest_2 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
 		;;
 	"guest2")
-		pane_run GUEST_2 "${__arg}"
-		pane_status GUEST_2 || TEST_ONE_nok=1
+		pane_or_context_run guest_2 "${__arg}" || TEST_ONE_nok=1
 		;;
 	"guest2b")
-		pane_run GUEST_2 "${__arg}"
+		pane_or_context_run_bg guest_2 "${__arg}"
 		;;
 	"guest2w")
-		pane_status GUEST_2 || TEST_ONE_nok=1
+		pane_or_context_wait guest_2 || TEST_ONE_nok=1
 		;;
 	"ns")
-		pane_run NS "${__arg}"
-		pane_status NS || TEST_ONE_nok=1
+		pane_or_context_run ns "${__arg}" || TEST_ONE_nok=1
 		;;
 	"ns1")
-		pane_run NS1 "${__arg}"
-		pane_status NS1 || TEST_ONE_nok=1
+		pane_or_context_run ns1 "${__arg}" || TEST_ONE_nok=1
 		;;
 	"ns2")
-		pane_run NS2 "${__arg}"
-		pane_status NS2 || TEST_ONE_nok=1
+		pane_or_context_run ns2 "${__arg}" || TEST_ONE_nok=1
 		;;
 	"nsb")
-		pane_run NS "${__arg}"
+		pane_or_context_run_bg ns "${__arg}"
 		;;
 	"ns1b")
-		pane_run NS1 "${__arg}"
+		pane_or_context_run_bg ns1 "${__arg}"
 		;;
 	"ns2b")
-		pane_run NS2 "${__arg}"
+		pane_or_context_run_bg ns2 "${__arg}"
 		;;
 	"nsw")
-		pane_status NS || TEST_ONE_nok=1
+		pane_or_context_wait ns || TEST_ONE_nok=1
 		;;
 	"ns1w")
-		pane_status NS1 || TEST_ONE_nok=1
+		pane_or_context_wait ns1 || TEST_ONE_nok=1
 		;;
 	"ns2w")
-		pane_status NS2 || TEST_ONE_nok=1
+		pane_or_context_wait ns2 || TEST_ONE_nok=1
 		;;
 	"nstools")
-		pane_run NS 'which '"${__arg}"' >/dev/null'
-		pane_status NS || TEST_ONE_skip=1
+		pane_or_context_run ns 'which '"${__arg}"' >/dev/null' || TEST_ONE_skip=1
 		;;
 	"gout")
 		__varname="${__arg%% *}"
-		pane_run GUEST "${__arg#* }"
-		pane_wait GUEST
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST)")"
+		__output="$(pane_or_context_output guest "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"g1out")
 		__varname="${__arg%% *}"
-		pane_run GUEST_1 "${__arg#* }"
-		pane_wait GUEST_1
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST_1)")"
+		__output="$(pane_or_context_output guest_1 "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"g2out")
 		__varname="${__arg%% *}"
-		pane_run GUEST_2 "${__arg#* }"
-		pane_wait GUEST_2
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse GUEST_2)")"
+		__output="$(pane_or_context_output guest_2 "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"hout")
 		__varname="${__arg%% *}"
-		pane_run HOST "${__arg#* }"
-		pane_wait HOST
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse HOST)")"
+		__output="$(pane_or_context_output host "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"nsout")
 		__varname="${__arg%% *}"
-		pane_run NS "${__arg#* }"
-		pane_wait NS
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS)")"
+		__output="$(pane_or_context_output ns "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"ns1out")
 		__varname="${__arg%% *}"
-		pane_run NS1 "${__arg#* }"
-		pane_wait NS1
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS1)")"
+		__output="$(pane_or_context_output ns1 "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"ns2out")
 		__varname="${__arg%% *}"
-		pane_run NS2 "${__arg#* }"
-		pane_wait NS2
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "$(pane_parse NS2)")"
+		__output="$(pane_or_context_output ns2 "${__arg#* }")"
+		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__varname}__" "${__output}")"
 		;;
 	"check")
 		info_check "${__arg}"
diff --git a/test/run b/test/run
index aa9a380..0ec1334 100755
--- a/test/run
+++ b/test/run
@@ -39,6 +39,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
 
 . lib/util
 . lib/setup
+. lib/context
 . lib/term
 . lib/perf_report
 . lib/layout
-- 
@@ -39,6 +39,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
 
 . lib/util
 . lib/setup
+. lib/context
 . lib/term
 . lib/perf_report
 . lib/layout
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 05/32] test: Issue host commands via context for most tests
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (3 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 04/32] test: Integration of old-style pane execution and new context execution David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 06/32] test: Use new-style contexts for passt pane in the pasta and passt tests David Gibson
                   ` (26 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 6198 bytes --]

Convert most of the tests to use the new-style system for issuing commands
for all host commands.  We leave the distro tests for now: they use
the same pane for both host and guest commands which we'll need some more
things to deal with.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/layout | 20 ++++++++++----------
 test/lib/setup  | 47 ++++++++++++++++++++++++++++++++---------------
 2 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/test/lib/layout b/test/lib/layout
index 2d6b197..09c213a 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -31,8 +31,12 @@ layout_host() {
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
-	tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
-	tmux select-pane -t ${PANE_HOST} -T "host"
+	if context_exists host; then
+	    pane_watch_contexts 0 host host
+	else
+	    tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
+	    tmux select-pane -t ${PANE_HOST} -T "host"
+	fi
 
 	info_layout "host commands only"
 
@@ -64,8 +68,7 @@ layout_pasta() {
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
-	tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
-	tmux select-pane -t ${PANE_HOST} -T "host"
+	pane_watch_contexts ${PANE_HOST} host host
 
 	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
 	tmux select-pane -t ${PANE_PASST} -T "pasta"
@@ -100,8 +103,7 @@ layout_passt() {
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
-	tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
-	tmux select-pane -t ${PANE_HOST} -T "host"
+	pane_watch_contexts ${PANE_HOST} host host
 
 	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
 	tmux select-pane -t ${PANE_PASST} -T "passt"
@@ -141,8 +143,7 @@ layout_passt_in_pasta() {
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
-	tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
-	tmux select-pane -t ${PANE_HOST} -T "host"
+	pane_watch_contexts ${PANE_HOST} host host
 
 	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
 	tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
@@ -189,8 +190,7 @@ layout_two_guests() {
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
-	tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
-	tmux select-pane -t ${PANE_HOST} -T "host"
+	pane_watch_contexts ${PANE_HOST} host host
 
 	tmux pipe-pane -O -t ${PANE_PASST_1} "cat >> ${LOGDIR}/pane_passt_1.log"
 	tmux select-pane -t ${PANE_PASST_1} -T "passt #1 in namespace #1"
diff --git a/test/lib/setup b/test/lib/setup
index 42f03c1..9b5e9ff 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -20,6 +20,8 @@ VMEM="$((${__mem_kib} / 1024 / 4))"
 
 # setup_build() - Set up pane layout for build tests
 setup_build() {
+	context_setup_host host
+
 	layout_host
 }
 
@@ -30,6 +32,8 @@ setup_distro() {
 
 # setup_passt() - Start qemu and passt
 setup_passt() {
+	context_setup_host host
+
 	layout_passt
 
 	# Ports:
@@ -63,17 +67,12 @@ setup_passt() {
 		" -netdev socket,fd=5,id=hostnet0"			   \
 		' -pidfile passt_qemu.pid'
 	pane_status GUEST
-
-	# Set things up to reduce problems parsing host command output
-	pane_run HOST "PS1='$ '"
-	pane_wait HOST
-	# Non-bash shells will fail this, but also don't need it, so ignore errors
-	pane_run HOST "bind 'set enable-bracketed-paste off'"
-	pane_wait HOST
 }
 
 # setup_pasta() - Create a network and user namespace, connect pasta to it
 setup_pasta() {
+	context_setup_host host
+
 	layout_pasta
 
 	pane_run NS 'echo $$'
@@ -105,6 +104,8 @@ setup_pasta() {
 
 # setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
 setup_passt_in_ns() {
+	context_setup_host host
+
 	layout_passt_in_pasta
 
 	# Ports:
@@ -182,17 +183,12 @@ setup_passt_in_ns() {
 		" -netdev socket,fd=5,id=hostnet0"			   \
 		' -pidfile passt_in_ns_qemu.pid'
 	pane_status GUEST
-
-	# Set things up to reduce problems parsing host command output
-	pane_run HOST "PS1='$ '"
-	pane_wait HOST
-	# Non-bash shells will fail this, but also don't need it, so ignore errors
-	pane_run HOST "bind 'set enable-bracketed-paste off'"
-	pane_wait HOST
 }
 
 # setup_two_guests() - Set up two namespace, run qemu and passt in both of them
 setup_two_guests() {
+	context_setup_host host
+
 	layout_two_guests
 
 	# Ports:
@@ -290,9 +286,21 @@ setup_two_guests() {
 	pane_status GUEST_2
 }
 
+# teardown_context_watch() - Remove contexts and stop panes watching them
+# $1:	Pane number watching
+# $@:	Context names
+teardown_context_watch() {
+	__pane="$1"
+	shift
+	for __c ; do
+		context_teardown "${__c}"
+	done
+	tmux send-keys -t ${__pane} "C-c"
+}
+
 # teardown_build() - Nothing to do, yet
 teardown_build() {
-    :
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_distro() - Nothing to do, yet
@@ -303,14 +311,19 @@ teardown_distro() {
 # teardown_passt() - Kill qemu, remove passt PID file
 teardown_passt() {
 	kill $(cat passt_qemu.pid)
+
 	pane_wait GUEST
 	rm passt.pid
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_passt() - Exit namespace, kill pasta process
 teardown_pasta() {
 	tmux send-keys -t ${PANE_NS} "C-d"
 	pane_wait NS
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
@@ -326,6 +339,8 @@ teardown_passt_in_ns() {
 	pane_wait PASST
 
 	rm passt.pid
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
@@ -350,6 +365,8 @@ teardown_two_guests() {
 	pane_wait GUEST_2
 	pane_wait PASST_1
 	pane_wait PASST_2
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
-- 
@@ -20,6 +20,8 @@ VMEM="$((${__mem_kib} / 1024 / 4))"
 
 # setup_build() - Set up pane layout for build tests
 setup_build() {
+	context_setup_host host
+
 	layout_host
 }
 
@@ -30,6 +32,8 @@ setup_distro() {
 
 # setup_passt() - Start qemu and passt
 setup_passt() {
+	context_setup_host host
+
 	layout_passt
 
 	# Ports:
@@ -63,17 +67,12 @@ setup_passt() {
 		" -netdev socket,fd=5,id=hostnet0"			   \
 		' -pidfile passt_qemu.pid'
 	pane_status GUEST
-
-	# Set things up to reduce problems parsing host command output
-	pane_run HOST "PS1='$ '"
-	pane_wait HOST
-	# Non-bash shells will fail this, but also don't need it, so ignore errors
-	pane_run HOST "bind 'set enable-bracketed-paste off'"
-	pane_wait HOST
 }
 
 # setup_pasta() - Create a network and user namespace, connect pasta to it
 setup_pasta() {
+	context_setup_host host
+
 	layout_pasta
 
 	pane_run NS 'echo $$'
@@ -105,6 +104,8 @@ setup_pasta() {
 
 # setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
 setup_passt_in_ns() {
+	context_setup_host host
+
 	layout_passt_in_pasta
 
 	# Ports:
@@ -182,17 +183,12 @@ setup_passt_in_ns() {
 		" -netdev socket,fd=5,id=hostnet0"			   \
 		' -pidfile passt_in_ns_qemu.pid'
 	pane_status GUEST
-
-	# Set things up to reduce problems parsing host command output
-	pane_run HOST "PS1='$ '"
-	pane_wait HOST
-	# Non-bash shells will fail this, but also don't need it, so ignore errors
-	pane_run HOST "bind 'set enable-bracketed-paste off'"
-	pane_wait HOST
 }
 
 # setup_two_guests() - Set up two namespace, run qemu and passt in both of them
 setup_two_guests() {
+	context_setup_host host
+
 	layout_two_guests
 
 	# Ports:
@@ -290,9 +286,21 @@ setup_two_guests() {
 	pane_status GUEST_2
 }
 
+# teardown_context_watch() - Remove contexts and stop panes watching them
+# $1:	Pane number watching
+# $@:	Context names
+teardown_context_watch() {
+	__pane="$1"
+	shift
+	for __c ; do
+		context_teardown "${__c}"
+	done
+	tmux send-keys -t ${__pane} "C-c"
+}
+
 # teardown_build() - Nothing to do, yet
 teardown_build() {
-    :
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_distro() - Nothing to do, yet
@@ -303,14 +311,19 @@ teardown_distro() {
 # teardown_passt() - Kill qemu, remove passt PID file
 teardown_passt() {
 	kill $(cat passt_qemu.pid)
+
 	pane_wait GUEST
 	rm passt.pid
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_passt() - Exit namespace, kill pasta process
 teardown_pasta() {
 	tmux send-keys -t ${PANE_NS} "C-d"
 	pane_wait NS
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
@@ -326,6 +339,8 @@ teardown_passt_in_ns() {
 	pane_wait PASST
 
 	rm passt.pid
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
@@ -350,6 +365,8 @@ teardown_two_guests() {
 	pane_wait GUEST_2
 	pane_wait PASST_1
 	pane_wait PASST_2
+
+	teardown_context_watch ${PANE_HOST} host
 }
 
 # teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 06/32] test: Use new-style contexts for passt pane in the pasta and passt tests
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (4 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 05/32] test: Issue host commands via context for most tests David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 07/32] test: Add nsholder utility David Gibson
                   ` (25 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 4308 bytes --]

Convert the pasta and passt tests to use new-style context execution
for the things that run in the "passt" frame.  Don't touch the
passt_in_ns or two_guests tests yet, because they run passt inside a
namespace which introduces some additional complications we have yet
to handle.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/layout     |  8 ++------
 test/lib/setup      | 19 +++++++++----------
 test/shutdown/passt |  4 +---
 3 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/test/lib/layout b/test/lib/layout
index 09c213a..95bd035 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -69,9 +69,7 @@ layout_pasta() {
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
 	pane_watch_contexts ${PANE_HOST} host host
-
-	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
-	tmux select-pane -t ${PANE_PASST} -T "pasta"
+	pane_watch_contexts ${PANE_PASST} pasta passt
 
 	info_layout "single pasta instance with namespace"
 
@@ -104,9 +102,7 @@ layout_passt() {
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
 	pane_watch_contexts ${PANE_HOST} host host
-
-	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
-	tmux select-pane -t ${PANE_PASST} -T "passt"
+	pane_watch_contexts ${PANE_PASST} passt passt
 
 	info_layout "single passt instance with guest"
 
diff --git a/test/lib/setup b/test/lib/setup
index 9b5e9ff..8430f4f 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -33,6 +33,7 @@ setup_distro() {
 # setup_passt() - Start qemu and passt
 setup_passt() {
 	context_setup_host host
+	context_setup_host passt
 
 	layout_passt
 
@@ -48,11 +49,9 @@ setup_passt() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	pane_run PASST "make clean"
-	pane_status PASST
-	pane_run PASST "make valgrind"
-	pane_status PASST
-	pane_run PASST "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
+	context_run passt "make clean"
+	context_run passt "make valgrind"
+	context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
 	sleep 5
 
 	pane_run GUEST './qrap 5 qemu-system-$(uname -m)'                  \
@@ -72,6 +71,7 @@ setup_passt() {
 # setup_pasta() - Create a network and user namespace, connect pasta to it
 setup_pasta() {
 	context_setup_host host
+	context_setup_host passt
 
 	layout_pasta
 
@@ -82,9 +82,7 @@ setup_pasta() {
 	pane_run NS "unshare -rUnpf /bin/sh"
 	pane_status NS
 
-	pane_run PASST "pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p'"
-	pane_wait PASST
-	__target_pid="$(pane_parse PASST)"
+	__target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
 
 	# Ports:
 	#
@@ -98,7 +96,7 @@ setup_pasta() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	pane_run PASST "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P passt.pid ${__target_pid}"
+	context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P passt.pid ${__target_pid}"
 	sleep 1
 }
 
@@ -311,11 +309,11 @@ teardown_distro() {
 # teardown_passt() - Kill qemu, remove passt PID file
 teardown_passt() {
 	kill $(cat passt_qemu.pid)
-
 	pane_wait GUEST
 	rm passt.pid
 
 	teardown_context_watch ${PANE_HOST} host
+	teardown_context_watch ${PANE_PASST} passt
 }
 
 # teardown_passt() - Exit namespace, kill pasta process
@@ -324,6 +322,7 @@ teardown_pasta() {
 	pane_wait NS
 
 	teardown_context_watch ${PANE_HOST} host
+	teardown_context_watch ${PANE_PASST} passt
 }
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
diff --git a/test/shutdown/passt b/test/shutdown/passt
index 4a7b702..ac8ff08 100644
--- a/test/shutdown/passt
+++ b/test/shutdown/passt
@@ -17,6 +17,4 @@ test	shutdown: exit code
 hout	PASST_PID cat passt.pid
 host	kill __PASST_PID__
 sleep	1
-
-pout	EXIT echo $?
-check	[ "__EXIT__" = "0" ]
+passtw
-- 
@@ -17,6 +17,4 @@ test	shutdown: exit code
 hout	PASST_PID cat passt.pid
 host	kill __PASST_PID__
 sleep	1
-
-pout	EXIT echo $?
-check	[ "__EXIT__" = "0" ]
+passtw
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 07/32] test: Add nsholder utility
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (5 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 06/32] test: Use new-style contexts for passt pane in the pasta and passt tests David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 08/32] test: Extend context system to run commands in namespace for pasta tests David Gibson
                   ` (24 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5043 bytes --]

In our test scripts we need to do some ugly parsing of /proc and/or pstree
output in order to get the PIDs of processes running in namespaces so that
we can connect to those namespaces with nsenter or pasta.

This is actually a pretty tricky problem with standard tools.  To determine
the PID from the outside of the namespace we need to know how the process
of interest is related to the unshare or pasta process (child? one of
several children? grandchild?) as well as then parsing /proc or ps output.
This is slightly awkward now, and will get worse with future changes I'd
like to make to have processes are dispatched.

The obvious solution would be to have the process of interest (which we
control) report its own PID, but that doesn't work easily, because it is in
a PID namepace and sees only its local PID not the global PID we need to
address it from outside.

To handle this, add a small custom tool, "nsholder".  This takes a path
and a mode parameter.  In "hold" mode it will create a unix domain socket
bound to the path and listening.  In "pid" mode it will get the "hold"ing
process's pid via the unix socket using SO_PEERCRED, which translates
between PID namespaces.  In "stop" mode it will send a message to the
socket causing the "hold"ing process to clean up and exit.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/.gitignore |   1 +
 test/Makefile   |   8 +++-
 test/nsholder.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 test/nsholder.c

diff --git a/test/.gitignore b/test/.gitignore
index 129ddc0..d477a42 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -10,3 +10,4 @@ QEMU_EFI.fd
 *.start
 *.stop
 *.js
+nsholder
diff --git a/test/Makefile b/test/Makefile
index f11c4b5..e0dc7ac 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -56,10 +56,13 @@ DOWNLOAD_ASSETS = mbuto \
 	$(DEBIAN_IMGS) $(FEDORA_IMGS) $(OPENSUSE_IMGS) $(UBUNTU_IMGS)
 LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \
 	$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
-	$(UBUNTU_NEW_IMGS:%=prepared-%)
+	$(UBUNTU_NEW_IMGS:%=prepared-%) \
+	nsholder
 
 ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
 
+CFLAGS = -Wall -Werror
+
 assets: $(ASSETS)
 
 mbuto:
@@ -68,6 +71,9 @@ mbuto:
 mbuto.img: passt.mbuto mbuto
 	./mbuto/mbuto -p ./$< -c lz4 -f $@
 
+nsholder: nsholder.c
+	$(CC) $(CFLAGS) -o $@ $^
+
 QEMU_EFI.fd:
 	./find-arm64-firmware.sh $@
 
diff --git a/test/nsholder.c b/test/nsholder.c
new file mode 100644
index 0000000..bfe3611
--- /dev/null
+++ b/test/nsholder.c
@@ -0,0 +1,117 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#define die(...)				\
+	do {					\
+		fprintf(stderr, __VA_ARGS__);	\
+		exit(1);			\
+	} while (0)
+
+static void usage(void)
+{
+	die("Usage: holder <socket path> hold|pid\n");
+}
+
+static void hold(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+
+	rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+	if (rc < 0)
+		die("bind(): %s\n", strerror(errno));
+
+	rc = listen(fd, 0);
+	if (rc < 0)
+		die("listen(): %s\n", strerror(errno));
+
+	printf("nsholder: local PID=%d  local UID=%d  local GID=%d\n",
+	       getpid(), getuid(), getgid());
+	do {
+		int afd = accept(fd, NULL, NULL);
+		char buf;
+
+		if (afd < 0)
+			die("accept(): %s\n", strerror(errno));
+
+		rc = read(afd, &buf, sizeof(buf));
+		if (rc < 0)
+			die("read(): %s\n", strerror(errno));
+	} while (rc == 0);
+
+	unlink(addr->sun_path);
+}
+
+static void pid(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+	struct ucred peercred;
+	socklen_t optlen = sizeof(peercred);
+
+	do {
+		rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+		if (rc < 0 && errno != ENOENT && errno != ECONNREFUSED)
+			die("connect(): %s\n", strerror(errno));
+	} while (rc < 0);
+
+	rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+			&peercred, &optlen);
+	if (rc < 0)
+		die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+
+	close(fd);
+
+	printf("%d\n", peercred.pid);
+}
+
+static void stop(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+	char buf = 'Q';
+
+	rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+	if (rc < 0)
+		die("connect(): %s\n", strerror(errno));
+
+	rc = write(fd, &buf, sizeof(buf));
+	if (rc < 0)
+		die("write(): %s\n",  strerror(errno));
+
+	close(fd);
+}
+
+int main(int argc, char *argv[])
+{
+	int fd;
+	const char *sockname;
+	struct sockaddr_un sockaddr = {
+		.sun_family = AF_UNIX,
+	};
+
+	if (argc != 3)
+		usage();
+
+	sockname = argv[1];
+	strncpy(sockaddr.sun_path, sockname, UNIX_PATH_MAX);
+
+	fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+	if (fd < 0)
+		die("socket(): %s\n", strerror(errno));
+
+	if (strcmp(argv[2], "hold") == 0)
+		hold(fd, &sockaddr);
+	else if (strcmp(argv[2], "pid") == 0)
+		pid(fd, &sockaddr);
+	else if (strcmp(argv[2], "stop") == 0)
+		stop(fd, &sockaddr);
+	else
+		usage();
+
+	exit(0);
+}
-- 
@@ -0,0 +1,117 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#define die(...)				\
+	do {					\
+		fprintf(stderr, __VA_ARGS__);	\
+		exit(1);			\
+	} while (0)
+
+static void usage(void)
+{
+	die("Usage: holder <socket path> hold|pid\n");
+}
+
+static void hold(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+
+	rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+	if (rc < 0)
+		die("bind(): %s\n", strerror(errno));
+
+	rc = listen(fd, 0);
+	if (rc < 0)
+		die("listen(): %s\n", strerror(errno));
+
+	printf("nsholder: local PID=%d  local UID=%d  local GID=%d\n",
+	       getpid(), getuid(), getgid());
+	do {
+		int afd = accept(fd, NULL, NULL);
+		char buf;
+
+		if (afd < 0)
+			die("accept(): %s\n", strerror(errno));
+
+		rc = read(afd, &buf, sizeof(buf));
+		if (rc < 0)
+			die("read(): %s\n", strerror(errno));
+	} while (rc == 0);
+
+	unlink(addr->sun_path);
+}
+
+static void pid(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+	struct ucred peercred;
+	socklen_t optlen = sizeof(peercred);
+
+	do {
+		rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+		if (rc < 0 && errno != ENOENT && errno != ECONNREFUSED)
+			die("connect(): %s\n", strerror(errno));
+	} while (rc < 0);
+
+	rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+			&peercred, &optlen);
+	if (rc < 0)
+		die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+
+	close(fd);
+
+	printf("%d\n", peercred.pid);
+}
+
+static void stop(int fd, const struct sockaddr_un *addr)
+{
+	int rc;
+	char buf = 'Q';
+
+	rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
+	if (rc < 0)
+		die("connect(): %s\n", strerror(errno));
+
+	rc = write(fd, &buf, sizeof(buf));
+	if (rc < 0)
+		die("write(): %s\n",  strerror(errno));
+
+	close(fd);
+}
+
+int main(int argc, char *argv[])
+{
+	int fd;
+	const char *sockname;
+	struct sockaddr_un sockaddr = {
+		.sun_family = AF_UNIX,
+	};
+
+	if (argc != 3)
+		usage();
+
+	sockname = argv[1];
+	strncpy(sockaddr.sun_path, sockname, UNIX_PATH_MAX);
+
+	fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+	if (fd < 0)
+		die("socket(): %s\n", strerror(errno));
+
+	if (strcmp(argv[2], "hold") == 0)
+		hold(fd, &sockaddr);
+	else if (strcmp(argv[2], "pid") == 0)
+		pid(fd, &sockaddr);
+	else if (strcmp(argv[2], "stop") == 0)
+		stop(fd, &sockaddr);
+	else
+		usage();
+
+	exit(0);
+}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 08/32] test: Extend context system to run commands in namespace for pasta tests
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (6 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 07/32] test: Add nsholder utility David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 09/32] test: Use context system for guest commands David Gibson
                   ` (23 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 3762 bytes --]

Extend the context system to allow commands to be run in a namespace
created with unshare, and use it for the namespace used in the pasta tests.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/context | 21 ++++++++++++++++++++-
 test/lib/layout  |  4 +---
 test/lib/setup   | 17 ++++++++---------
 3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/test/lib/context b/test/lib/context
index babf59a..0d92d8f 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -13,13 +13,32 @@
 # Copyright Red Hat
 # Author: David Gibson <david(a)gibson.dropbear.id.au>
 
+# context_setup_common() - Create outline of a new context
+# $1:	Context name
+context_setup_common() {
+	__name="$1"
+	__prefix="${LOGDIR}/context_${__name}"
+	echo -n "${__name}$ " > "${__prefix}.log"
+}
+
 # context_setup_host() - Create a new context for running commands on the host
 # $1:	Context name
 context_setup_host() {
 	__name="$1"
 	__prefix="${LOGDIR}/context_${__name}"
+	context_setup_common "${__name}"
 	echo sh -c > "${__prefix}.enter"
-	echo -n "${__name}$ " > "${__prefix}.log"
+}
+
+# context_setup_nsenter() - Create a new context for running commands in a namespace
+# $1:	Context name
+# $2:	Namespace PID
+context_setup_nsenter() {
+	__name="$1"
+	shift
+	__prefix="${LOGDIR}/context_${__name}"
+	context_setup_common "${__name}"
+	echo "nsenter $@ sh -c" > "${__prefix}.enter"
 }
 
 # context_teardown() - Remove a context (leave log files intact)
diff --git a/test/lib/layout b/test/lib/layout
index 95bd035..1401955 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -61,15 +61,13 @@ layout_pasta() {
 
 	get_info_cols
 
-	tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
-	tmux select-pane -t ${PANE_NS} -T "namespace"
-
 	tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
 	pane_watch_contexts ${PANE_HOST} host host
 	pane_watch_contexts ${PANE_PASST} pasta passt
+	pane_watch_contexts ${PANE_NS} "namespace" unshare ns
 
 	info_layout "single pasta instance with namespace"
 
diff --git a/test/lib/setup b/test/lib/setup
index 8430f4f..ac36ac3 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -17,6 +17,7 @@ INITRAMFS="${BASEPATH}/mbuto.img"
 VCPUS="$( [ $(nproc) -ge 8 ] && echo 6 || echo $(( $(nproc) / 2 + 1 )) )"
 __mem_kib="$(sed -n 's/MemTotal:[ ]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
 VMEM="$((${__mem_kib} / 1024 / 4))"
+NSHOLDER="${BASEPATH}/nsholder"
 
 # setup_build() - Set up pane layout for build tests
 setup_build() {
@@ -72,17 +73,14 @@ setup_passt() {
 setup_pasta() {
 	context_setup_host host
 	context_setup_host passt
+	context_setup_host unshare
 
 	layout_pasta
 
-	pane_run NS 'echo $$'
-	pane_wait NS
-	__tty_pid="$(pane_parse NS)"
-
-	pane_run NS "unshare -rUnpf /bin/sh"
-	pane_status NS
+	context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ns.hold hold"
+	__target_pid=$(${NSHOLDER} ns.hold pid)
 
-	__target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
+	context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
 
 	# Ports:
 	#
@@ -318,11 +316,12 @@ teardown_passt() {
 
 # teardown_passt() - Exit namespace, kill pasta process
 teardown_pasta() {
-	tmux send-keys -t ${PANE_NS} "C-d"
-	pane_wait NS
+	${NSHOLDER} ns.hold stop
+	context_wait unshare
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_PASST} passt
+	teardown_context_watch ${PANE_NS} unshare ns
 }
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
-- 
@@ -17,6 +17,7 @@ INITRAMFS="${BASEPATH}/mbuto.img"
 VCPUS="$( [ $(nproc) -ge 8 ] && echo 6 || echo $(( $(nproc) / 2 + 1 )) )"
 __mem_kib="$(sed -n 's/MemTotal:[ ]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
 VMEM="$((${__mem_kib} / 1024 / 4))"
+NSHOLDER="${BASEPATH}/nsholder"
 
 # setup_build() - Set up pane layout for build tests
 setup_build() {
@@ -72,17 +73,14 @@ setup_passt() {
 setup_pasta() {
 	context_setup_host host
 	context_setup_host passt
+	context_setup_host unshare
 
 	layout_pasta
 
-	pane_run NS 'echo $$'
-	pane_wait NS
-	__tty_pid="$(pane_parse NS)"
-
-	pane_run NS "unshare -rUnpf /bin/sh"
-	pane_status NS
+	context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ns.hold hold"
+	__target_pid=$(${NSHOLDER} ns.hold pid)
 
-	__target_pid=$(pstree -p ${__tty_pid} | sed -n 's/.*(\([0-9].*\))$/\1/p')
+	context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
 
 	# Ports:
 	#
@@ -318,11 +316,12 @@ teardown_passt() {
 
 # teardown_passt() - Exit namespace, kill pasta process
 teardown_pasta() {
-	tmux send-keys -t ${PANE_NS} "C-d"
-	pane_wait NS
+	${NSHOLDER} ns.hold stop
+	context_wait unshare
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_PASST} passt
+	teardown_context_watch ${PANE_NS} unshare ns
 }
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 09/32] test: Use context system for guest commands
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (7 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 08/32] test: Extend context system to run commands in namespace for pasta tests David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:15 ` [PATCH v2 10/32] test: Use context system for two_guests tests David Gibson
                   ` (22 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 12809 bytes --]

Extends the context system in the test scripts to allow executing commands
within a guest.  Do this without requiring an existing network in the guest
by using socat to run ssh via a vsock connection.

We do need some additional "sleep"s in the tests, because the new
faster dispatch means that sometimes we attempt to connect before
socat has managed to listen.

For now, only use this for the plain "passt" tests.  The "passt_in_ns" and
other tests have additional complications we still need to deal with.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/.gitignore      |  2 ++
 test/Makefile        |  7 +++++--
 test/lib/context     | 28 +++++++++++++++++++++++++++-
 test/lib/layout      |  4 +---
 test/lib/setup       | 13 +++++++++----
 test/lib/term        |  9 ++++++---
 test/passt.mbuto     | 32 +++++++++++++++++++++++++++++---
 test/tcp/passt       |  2 ++
 test/tcp/passt_in_ns |  8 ++++++++
 test/udp/passt       |  1 +
 10 files changed, 90 insertions(+), 16 deletions(-)

diff --git a/test/.gitignore b/test/.gitignore
index d477a42..0f91c7d 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -11,3 +11,5 @@ QEMU_EFI.fd
 *.stop
 *.js
 nsholder
+guest-key
+guest-key.pub
diff --git a/test/Makefile b/test/Makefile
index e0dc7ac..cc1a818 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -57,7 +57,7 @@ DOWNLOAD_ASSETS = mbuto \
 LOCAL_ASSETS = mbuto.img QEMU_EFI.fd \
 	$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
 	$(UBUNTU_NEW_IMGS:%=prepared-%) \
-	nsholder
+	nsholder guest-key guest-key.pub
 
 ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
 
@@ -68,7 +68,10 @@ assets: $(ASSETS)
 mbuto:
 	git clone git://mbuto.sh/mbuto
 
-mbuto.img: passt.mbuto mbuto
+guest-key guest-key.pub:
+	ssh-keygen -f guest-key -N ''
+
+mbuto.img: passt.mbuto mbuto guest-key.pub
 	./mbuto/mbuto -p ./$< -c lz4 -f $@
 
 nsholder: nsholder.c
diff --git a/test/lib/context b/test/lib/context
index 0d92d8f..ccb0004 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -41,12 +41,38 @@ context_setup_nsenter() {
 	echo "nsenter $@ sh -c" > "${__prefix}.enter"
 }
 
+# context_setup_guest() - Create a new context for running commands in a guest
+# $1:        Context name
+# $2:        CID to use for vsock
+context_setup_guest() {
+	__name="$1"
+	__cid="$2"
+	__prefix="${LOGDIR}/context_${__name}"
+	context_setup_common "${__name}"
+
+	cat > "${__prefix}.ssh" <<EOF
+Host ${__name}
+	User root
+	UserKnownHostsFile ${__prefix}.hosts
+	StrictHostKeyChecking no
+	IdentityFile ${BASEPATH}/guest-key
+	IdentityAgent none
+	ProxyCommand socat - VSOCK-CONNECT:${__cid}:22
+EOF
+	echo "ssh -F ${__prefix}.ssh ${__name}" > "${__prefix}.enter"
+
+	# Wait for the guest to be booted and accepting connections
+	while ! ssh -F "${__prefix}.ssh" "${__name}" :; do
+		sleep 0.1
+	done
+}
+
 # context_teardown() - Remove a context (leave log files intact)
 # $1:	Context name
 context_teardown() {
 	__name="$1"
 	__prefix="${LOGDIR}/context_${__name}"
-	rm -f "${__prefix}.enter"
+	rm -f "${__prefix}.enter" "${__prefix}.ssh" "${__prefix}.hosts"
 }
 
 # context_exists() - Test if a context currently exists
diff --git a/test/lib/layout b/test/lib/layout
index 1401955..985d31b 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -92,15 +92,13 @@ layout_passt() {
 
 	get_info_cols
 
-	tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
-	tmux select-pane -t ${PANE_GUEST} -T "guest"
-
 	tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
 	pane_watch_contexts ${PANE_HOST} host host
 	pane_watch_contexts ${PANE_PASST} passt passt
+	pane_watch_contexts ${PANE_GUEST} guest qemu guest
 
 	info_layout "single passt instance with guest"
 
diff --git a/test/lib/setup b/test/lib/setup
index ac36ac3..4d8c81f 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -35,6 +35,7 @@ setup_distro() {
 setup_passt() {
 	context_setup_host host
 	context_setup_host passt
+	context_setup_host qemu
 
 	layout_passt
 
@@ -55,7 +56,8 @@ setup_passt() {
 	context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
 	sleep 5
 
-	pane_run GUEST './qrap 5 qemu-system-$(uname -m)'                  \
+	GUEST_CID=94557
+	context_run_bg qemu './qrap 5 qemu-system-$(uname -m)'		   \
 		' -machine accel=kvm'                                      \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                    \
 		' -kernel ' "/boot/vmlinuz-$(uname -r)"			   \
@@ -65,8 +67,10 @@ setup_passt() {
 		'virtio-net.napi_tx=1"'					   \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"  \
 		" -netdev socket,fd=5,id=hostnet0"			   \
-		' -pidfile passt_qemu.pid'
-	pane_status GUEST
+		" -pidfile passt_qemu.pid"				   \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_CID"
+
+	context_setup_guest guest $GUEST_CID
 }
 
 # setup_pasta() - Create a network and user namespace, connect pasta to it
@@ -307,11 +311,12 @@ teardown_distro() {
 # teardown_passt() - Kill qemu, remove passt PID file
 teardown_passt() {
 	kill $(cat passt_qemu.pid)
-	pane_wait GUEST
+
 	rm passt.pid
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_PASST} passt
+	teardown_context_watch ${PANE_GUEST} qemu guest
 }
 
 # teardown_passt() - Exit namespace, kill pasta process
diff --git a/test/lib/term b/test/lib/term
index a06c80b..ae99010 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -266,7 +266,8 @@ pane_or_context_run() {
 	__name="${1}"
 	shift
 	if context_exists "${__name}"; then
-		context_run "${__name}" "$@" >/dev/null 2>&1
+		# Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+		context_run "${__name}" "$@" >/dev/null 2>&1 < /dev/null
 	else
 		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
 		pane_run "${__uc}" "$@"
@@ -281,7 +282,8 @@ pane_or_context_run_bg() {
 	__name="${1}"
 	shift
 	if context_exists "${__name}"; then
-		context_run_bg "${__name}" "$@" >/dev/null 2>&1
+		# Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+		context_run_bg "${__name}" "$@" >/dev/null 2>&1 < /dev/null
 	else
 		__uc="$(echo "${__name}" | tr [a-z] [A-Z])"
 		pane_run "${__uc}" "$@"
@@ -295,7 +297,8 @@ pane_or_context_output() {
 	__name="${1}"
 	shift
 	if context_exists "${__name}"; then
-		__output=$(context_run "${__name}" "$@" 2>/dev/null)
+		# Redirect stdin to stop ssh from eating the test instructions file we have on stdin
+		__output=$(context_run "${__name}" "$@" 2>/dev/null </dev/null)
 		if [ -z "${__output}" ]; then
 			echo "@EMPTY@"
 		else
diff --git a/test/passt.mbuto b/test/passt.mbuto
index 8b41674..d29f456 100755
--- a/test/passt.mbuto
+++ b/test/passt.mbuto
@@ -13,15 +13,15 @@
 PROGS="${PROGS:-ash,dash,bash ip mount ls insmod mkdir ln cat chmod lsmod
        modprobe find grep mknod mv rm umount jq iperf3 dhclient hostname
        sed tr chown sipcalc cut md5sum socat dd strace ping tail killall sleep
-       sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc}"
+       sysctl nproc tcp_rr tcp_crr udp_rr which tee seq bc sshd ssh-keygen}"
 
-KMODS="${KMODS:- virtio_net virtio_pci}"
+KMODS="${KMODS:- virtio_net virtio_pci vmw_vsock_virtio_transport}"
 
 LINKS="${LINKS:-
 	 ash,dash,bash		/init
 	 ash,dash,bash		/bin/sh}"
 
-DIRS="${DIRS} /tmp /sbin /var/log /var/run /var/lib"
+DIRS="${DIRS} /tmp /sbin /usr/share /var/log /var/lib /etc/ssh /run/sshd /root/.ssh"
 
 FIXUP="${FIXUP}"'
 	cat > /sbin/dhclient-script << EOF
@@ -46,7 +46,33 @@ exit 0
 EOF
 	chmod 755 /sbin/dhclient-script
 	ln -s /sbin /usr/sbin
+	ln -s /bin /usr/bin
+	ln -s /run /var/run
 	:> /etc/fstab
+
+	# sshd(dropbear) via vsock
+	cat > /etc/passwd << EOF
+root:x:0:0:root:/root:/bin/sh
+sshd:x:100:100:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
+EOF
+	cat > /etc/shadow << EOF
+root:::0:99999:7:::
+EOF
+	chmod 000 /etc/shadow
+
+	:> /etc/ssh/sshd_config
+	ssh-keygen -A
+	chmod 700 /root/.ssh
+	chmod 700 /run/sshd
+	# Alternative location for the priv separation dir
+	ln -s /run/sshd /usr/share/empty.sshd
+
+	cat > /root/.ssh/authorized_keys <<EOF
+'"$(cat guest-key.pub)"'
+EOF
+	chmod 600 /root/.ssh/authorized_keys
+	chmod 700 /root
+	socat VSOCK-LISTEN:22,fork EXEC:"sshd -i -e" 2> /var/log/vsock-ssh.log &
 	sh +m
 '
 
diff --git a/test/tcp/passt b/test/tcp/passt
index 6e65137..265f270 100644
--- a/test/tcp/passt
+++ b/test/tcp/passt
@@ -17,6 +17,7 @@ htools	dd socat ip jq md5sum cut
 test	TCP/IPv4: host to guest: big transfer
 temp	TEMP_BIG
 guestb	socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_big.bin,create,trunc
+sleep	1
 host	dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
 host	socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
 guestw
@@ -35,6 +36,7 @@ check	[ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
 test	TCP/IPv4: host to guest: small transfer
 temp	TEMP_SMALL
 guestb	socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_small.bin,create,trunc
+sleep	1
 host	dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
 host	socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
 guestw
diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index 976e4e9..cb01781 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -18,6 +18,7 @@ nstools	socat ip jq md5sum cut
 test	TCP/IPv4: host to guest: big transfer
 temp	TEMP_BIG
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep	1
 host	dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__
 host	socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10001
 guestw
@@ -82,6 +83,7 @@ check	[ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
 test	TCP/IPv4: host to guest: small transfer
 temp	TEMP_SMALL
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep	1
 host	dd if=/dev/urandom bs=2k count=100 of=__TEMP_SMALL__
 host	socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10001
 guestw
@@ -129,6 +131,7 @@ check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
 test	TCP/IPv4: ns to guest (using loopback address): small transfer
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep	1
 ns	socat -u OPEN:__TEMP_NS_SMALL__ TCP4:127.0.0.1:10001
 guestw
 gout	GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -136,6 +139,7 @@ check	[ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
 test	TCP/IPv4: ns to guest (using namespace address): small transfer
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep	1
 ns	socat -u OPEN:__TEMP_NS_SMALL__ TCP4:__ADDR__:10001
 guestw
 gout	GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -143,6 +147,7 @@ check	[ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
 test	TCP/IPv6: host to guest: big transfer
 guestb	socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep	1
 host	socat -u OPEN:__TEMP_BIG__ TCP6:[::1]:10001
 guestw
 gout	GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@@ -188,6 +193,7 @@ check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv6: ns to guest (using loopback address): big transfer
 guestb	socat -u TCP6-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep	1
 ns	socat -u OPEN:__TEMP_NS_BIG__ TCP6:[::1]:10001
 guestw
 gout	GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
@@ -203,6 +209,7 @@ check	[ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv6: host to guest: small transfer
 guestb	socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep	1
 host	socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10001
 guestw
 gout	GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
@@ -248,6 +255,7 @@ check	[ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
 test	TCP/IPv6: ns to guest (using loopback address): small transfer
 guestb	socat -u TCP6-LISTEN:10001 OPEN:test_small.bin,create,trunc
+sleep	1
 ns	socat -u OPEN:__TEMP_NS_SMALL__ TCP6:[::1]:10001
 guestw
 gout	GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
diff --git a/test/udp/passt b/test/udp/passt
index 7c58648..a14e6d2 100644
--- a/test/udp/passt
+++ b/test/udp/passt
@@ -18,6 +18,7 @@ test	UDP/IPv4: host to guest
 temp	TEMP
 temp	SC_PID
 guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
+sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
 guestw
-- 
@@ -18,6 +18,7 @@ test	UDP/IPv4: host to guest
 temp	TEMP
 temp	SC_PID
 guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
+sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
 guestw
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 10/32] test: Use context system for two_guests tests
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (8 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 09/32] test: Use context system for guest commands David Gibson
@ 2022-09-08  6:15 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 11/32] test: Use new-style command issue for passt_in_ns tests David Gibson
                   ` (21 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:15 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 9175 bytes --]

Now that we have all the pieces we need for issuing commands both into
namespaces and into guests, we can use those to convert the two_guests to
using only the new style context command issue.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/layout |  15 ++-----
 test/lib/setup  | 115 ++++++++++++++++++++++--------------------------
 2 files changed, 57 insertions(+), 73 deletions(-)

diff --git a/test/lib/layout b/test/lib/layout
index 985d31b..b9d30e9 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -172,23 +172,16 @@ layout_two_guests() {
 
 	get_info_cols
 
-	tmux pipe-pane -O -t ${PANE_GUEST_1} "cat >> ${LOGDIR}/pane_guest_1.log"
-	tmux select-pane -t ${PANE_GUEST_1} -T "guest #1 in namespace #1"
-
-	tmux pipe-pane -O -t ${PANE_GUEST_2} "cat >> ${LOGDIR}/pane_guest_2.log"
-	tmux select-pane -t ${PANE_GUEST_2} -T "guest #2 in namespace #2"
+	pane_watch_contexts ${PANE_GUEST_1} "guest #1 in namespace #1" qemu_1 guest_1
+	pane_watch_contexts ${PANE_GUEST_2} "guest #2 in namespace #2" qemu_2 guest_2
 
 	tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
 	tmux select-pane -t ${PANE_INFO} -T "test log"
 
 	pane_watch_contexts ${PANE_HOST} host host
-
-	tmux pipe-pane -O -t ${PANE_PASST_1} "cat >> ${LOGDIR}/pane_passt_1.log"
-	tmux select-pane -t ${PANE_PASST_1} -T "passt #1 in namespace #1"
-
-	tmux pipe-pane -O -t ${PANE_PASST_2} "cat >> ${LOGDIR}/pane_passt_2.log"
-	tmux select-pane -t ${PANE_PASST_2} -T "passt #2 in namespace #2"
+	pane_watch_contexts ${PANE_PASST_1} "passt #1 in namespace #1" pasta_1 passt_1
+	pane_watch_contexts ${PANE_PASST_2} "passt #2 in namespace #2" pasta_2 passt_2
 
 	info_layout "two guests, two passt instances, in namespaces"
 
diff --git a/test/lib/setup b/test/lib/setup
index 4d8c81f..6eccd8c 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -188,6 +188,8 @@ setup_passt_in_ns() {
 # setup_two_guests() - Set up two namespace, run qemu and passt in both of them
 setup_two_guests() {
 	context_setup_host host
+	context_setup_host pasta_1
+	context_setup_host pasta_2
 
 	layout_two_guests
 
@@ -201,66 +203,49 @@ setup_two_guests() {
 	#  10004            | as server |  to init  |  to guest  |  to ns #2
 	#  10005            |           |           |  as server |  to ns #2
 
-	__pid1_file="$(mktemp)"
-	__pid2_file="$(mktemp)"
-
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_1 "./pasta ${__opts} -P ${__pid1_file} -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004"
+	context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
+	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
+	context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_2 "./pasta ${__opts} -P ${__pid2_file} -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001"
+	context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
+	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
+	context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
 
-	sleep 1
-	pane_run PASST_1 ''
-	pane_run PASST_2 ''
-
-	pane_status PASST_1
-	pane_status PASST_2
-	__pasta1_pid="$(cat "${__pid1_file}")"
-	__ns1_pid="$(cat /proc/${__pasta1_pid}/task/${__pasta1_pid}/children | cut -f1 -d' ')"
-	rm "${__pid1_file}"
-	__pasta2_pid="$(cat "${__pid2_file}")"
-	__ns2_pid="$(cat /proc/${__pasta2_pid}/task/${__pasta2_pid}/children | cut -f1 -d' ')"
-	rm "${__pid2_file}"
-
-	pane_run GUEST_1 "nsenter -t ${__ns1_pid} -U -n --preserve-credentials"
-	pane_run GUEST_2 "nsenter -t ${__ns2_pid} -U -n --preserve-credentials"
-
-	pane_run PASST_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
-	pane_wait PASST_1
-	__ifname="$(pane_parse PASST_1)"
-
-	pane_run GUEST_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
-	pane_run GUEST_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
-	pane_status GUEST_1
-	pane_status GUEST_2
-	sleep 2
-	pane_run GUEST_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
-	pane_run GUEST_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
-	pane_status GUEST_1
-	pane_status GUEST_2
+	context_setup_nsenter qemu_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
+	context_setup_nsenter qemu_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
+
+	__ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
+
+	context_run qemu_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
+	context_run qemu_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
+	context_run qemu_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
+	context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	pane_run PASST_1 "./passt -f ${__opts} -t 10001 -u 10001"
+	context_run_bg passt_1 "./passt -P passt_1.pid -f ${__opts} -t 10001 -u 10001"
 	sleep 1
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_2 "./passt -f ${__opts} -t 10004 -u 10004"
 
-	pane_run GUEST_1 './qrap 5 qemu-system-$(uname -m)'                  \
+	context_run_bg passt_2 "./passt -P passt_2.pid -f ${__opts} -t 10004 -u 10004"
+
+	GUEST_1_CID=94557
+	context_run_bg qemu_1 './qrap 5 qemu-system-$(uname -m)'             \
 		' -M accel=kvm:tcg'                                          \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                      \
 		' -kernel ' "/boot/vmlinuz-$(uname -r)"			     \
@@ -270,8 +255,11 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_1.pid'
-	pane_run GUEST_2 './qrap 5 qemu-system-$(uname -m)'                  \
+		' -pidfile two_guests_qemu_1.pid'			     \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_1_CID"
+
+	GUEST_2_CID=94558
+	context_run_bg qemu_2 './qrap 5 qemu-system-$(uname -m)'             \
 		' -M accel=kvm:tcg'                                          \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                      \
 		' -kernel ' "/boot/vmlinuz-$(uname -r)"			     \
@@ -281,9 +269,11 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_2.pid'
-	pane_status GUEST_1
-	pane_status GUEST_2
+		' -pidfile two_guests_qemu_2.pid'			     \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_2_CID"
+
+	context_setup_guest guest_1 ${GUEST_1_CID}
+	context_setup_guest guest_2 ${GUEST_2_CID}
 }
 
 # teardown_context_watch() - Remove contexts and stop panes watching them
@@ -348,28 +338,29 @@ teardown_passt_in_ns() {
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
 teardown_two_guests() {
-	kill $(cat two_guests_qemu_1.pid)
-	pane_wait GUEST_1
-	tmux send-keys -t ${PANE_GUEST_1} "C-d"
-
-	kill $(cat two_guests_qemu_2.pid)
-	pane_wait GUEST_2
-	tmux send-keys -t ${PANE_GUEST_2} "C-d"
-
-	tmux send-keys -t ${PANE_PASST_1} "C-c"
-	pane_wait PASST_1
-	tmux send-keys -t ${PANE_PASST_1} "C-d"
-
-	tmux send-keys -t ${PANE_PASST_2} "C-c"
-	pane_wait PASST_2
-	tmux send-keys -t ${PANE_PASST_2} "C-d"
-
-	pane_wait GUEST_1
-	pane_wait GUEST_2
-	pane_wait PASST_1
-	pane_wait PASST_2
+	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
+	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat two_guests_qemu_1.pid)
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat two_guests_qemu_2.pid)
+	context_wait qemu_1
+	context_wait qemu_2
+
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat passt_1.pid)
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat passt_2.pid)
+	context_wait passt_1
+	context_wait passt_2
+	${NSHOLDER} ns1.hold stop
+	${NSHOLDER} ns2.hold stop
+	context_wait pasta_1
+	context_wait pasta_2
+
+	rm -f passt_[12].pid pasta_[12].pid
 
 	teardown_context_watch ${PANE_HOST} host
+	teardown_context_watch ${PANE_GUEST_1} qemu_1 guest_1
+	teardown_context_watch ${PANE_GUEST_2} qemu_2 guest_2
+	teardown_context_watch ${PANE_PASST_1} pasta_1 passt_1
+	teardown_context_watch ${PANE_PASST_2} pasta_2 passt_2
 }
 
 # teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
-- 
@@ -188,6 +188,8 @@ setup_passt_in_ns() {
 # setup_two_guests() - Set up two namespace, run qemu and passt in both of them
 setup_two_guests() {
 	context_setup_host host
+	context_setup_host pasta_1
+	context_setup_host pasta_2
 
 	layout_two_guests
 
@@ -201,66 +203,49 @@ setup_two_guests() {
 	#  10004            | as server |  to init  |  to guest  |  to ns #2
 	#  10005            |           |           |  as server |  to ns #2
 
-	__pid1_file="$(mktemp)"
-	__pid2_file="$(mktemp)"
-
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_1 "./pasta ${__opts} -P ${__pid1_file} -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004"
+	context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
+	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
+	context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_2 "./pasta ${__opts} -P ${__pid2_file} -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001"
+	context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
+	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
+	context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
 
-	sleep 1
-	pane_run PASST_1 ''
-	pane_run PASST_2 ''
-
-	pane_status PASST_1
-	pane_status PASST_2
-	__pasta1_pid="$(cat "${__pid1_file}")"
-	__ns1_pid="$(cat /proc/${__pasta1_pid}/task/${__pasta1_pid}/children | cut -f1 -d' ')"
-	rm "${__pid1_file}"
-	__pasta2_pid="$(cat "${__pid2_file}")"
-	__ns2_pid="$(cat /proc/${__pasta2_pid}/task/${__pasta2_pid}/children | cut -f1 -d' ')"
-	rm "${__pid2_file}"
-
-	pane_run GUEST_1 "nsenter -t ${__ns1_pid} -U -n --preserve-credentials"
-	pane_run GUEST_2 "nsenter -t ${__ns2_pid} -U -n --preserve-credentials"
-
-	pane_run PASST_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
-	pane_wait PASST_1
-	__ifname="$(pane_parse PASST_1)"
-
-	pane_run GUEST_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
-	pane_run GUEST_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
-	pane_status GUEST_1
-	pane_status GUEST_2
-	sleep 2
-	pane_run GUEST_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
-	pane_run GUEST_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
-	pane_status GUEST_1
-	pane_status GUEST_2
+	context_setup_nsenter qemu_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
+	context_setup_nsenter qemu_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
+
+	__ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
+
+	context_run qemu_1 "/sbin/dhclient -4 --no-pid ${__ifname}"
+	context_run qemu_2 "/sbin/dhclient -4 --no-pid ${__ifname}"
+	context_run qemu_1 "/sbin/dhclient -6 --no-pid ${__ifname}"
+	context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	pane_run PASST_1 "./passt -f ${__opts} -t 10001 -u 10001"
+	context_run_bg passt_1 "./passt -P passt_1.pid -f ${__opts} -t 10001 -u 10001"
 	sleep 1
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	pane_run PASST_2 "./passt -f ${__opts} -t 10004 -u 10004"
 
-	pane_run GUEST_1 './qrap 5 qemu-system-$(uname -m)'                  \
+	context_run_bg passt_2 "./passt -P passt_2.pid -f ${__opts} -t 10004 -u 10004"
+
+	GUEST_1_CID=94557
+	context_run_bg qemu_1 './qrap 5 qemu-system-$(uname -m)'             \
 		' -M accel=kvm:tcg'                                          \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                      \
 		' -kernel ' "/boot/vmlinuz-$(uname -r)"			     \
@@ -270,8 +255,11 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_1.pid'
-	pane_run GUEST_2 './qrap 5 qemu-system-$(uname -m)'                  \
+		' -pidfile two_guests_qemu_1.pid'			     \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_1_CID"
+
+	GUEST_2_CID=94558
+	context_run_bg qemu_2 './qrap 5 qemu-system-$(uname -m)'             \
 		' -M accel=kvm:tcg'                                          \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                      \
 		' -kernel ' "/boot/vmlinuz-$(uname -r)"			     \
@@ -281,9 +269,11 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_2.pid'
-	pane_status GUEST_1
-	pane_status GUEST_2
+		' -pidfile two_guests_qemu_2.pid'			     \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_2_CID"
+
+	context_setup_guest guest_1 ${GUEST_1_CID}
+	context_setup_guest guest_2 ${GUEST_2_CID}
 }
 
 # teardown_context_watch() - Remove contexts and stop panes watching them
@@ -348,28 +338,29 @@ teardown_passt_in_ns() {
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
 teardown_two_guests() {
-	kill $(cat two_guests_qemu_1.pid)
-	pane_wait GUEST_1
-	tmux send-keys -t ${PANE_GUEST_1} "C-d"
-
-	kill $(cat two_guests_qemu_2.pid)
-	pane_wait GUEST_2
-	tmux send-keys -t ${PANE_GUEST_2} "C-d"
-
-	tmux send-keys -t ${PANE_PASST_1} "C-c"
-	pane_wait PASST_1
-	tmux send-keys -t ${PANE_PASST_1} "C-d"
-
-	tmux send-keys -t ${PANE_PASST_2} "C-c"
-	pane_wait PASST_2
-	tmux send-keys -t ${PANE_PASST_2} "C-d"
-
-	pane_wait GUEST_1
-	pane_wait GUEST_2
-	pane_wait PASST_1
-	pane_wait PASST_2
+	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
+	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat two_guests_qemu_1.pid)
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat two_guests_qemu_2.pid)
+	context_wait qemu_1
+	context_wait qemu_2
+
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat passt_1.pid)
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat passt_2.pid)
+	context_wait passt_1
+	context_wait passt_2
+	${NSHOLDER} ns1.hold stop
+	${NSHOLDER} ns2.hold stop
+	context_wait pasta_1
+	context_wait pasta_2
+
+	rm -f passt_[12].pid pasta_[12].pid
 
 	teardown_context_watch ${PANE_HOST} host
+	teardown_context_watch ${PANE_GUEST_1} qemu_1 guest_1
+	teardown_context_watch ${PANE_GUEST_2} qemu_2 guest_2
+	teardown_context_watch ${PANE_PASST_1} pasta_1 passt_1
+	teardown_context_watch ${PANE_PASST_2} pasta_2 passt_2
 }
 
 # teardown_demo_passt() - Exit namespace, kill qemu, passt and pasta
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 11/32] test: Use new-style command issue for passt_in_ns tests
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (9 preceding siblings ...)
  2022-09-08  6:15 ` [PATCH v2 10/32] test: Use context system for two_guests tests David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 12/32] Don't store UID & GID persistently in the context structure David Gibson
                   ` (20 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 7808 bytes --]

Put the pieces together to use the new style context based dispatch for
the passt_in_pasta tests.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/layout           | 10 ++----
 test/lib/setup            | 73 +++++++++++++++++----------------------
 test/shutdown/passt_in_ns |  4 +--
 test/tcp/passt_in_ns      |  1 +
 test/udp/passt_in_ns      |  1 +
 5 files changed, 37 insertions(+), 52 deletions(-)

diff --git a/test/lib/layout b/test/lib/layout
index b9d30e9..cc7c688 100644
--- a/test/lib/layout
+++ b/test/lib/layout
@@ -125,11 +125,8 @@ layout_passt_in_pasta() {
 
 	get_info_cols
 
-	tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
-	tmux select-pane -t ${PANE_GUEST} -T "guest"
-
-	tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
-	tmux select-pane -t ${PANE_NS} -T "namespace"
+	pane_watch_contexts ${PANE_GUEST} "guest" qemu guest
+	pane_watch_contexts ${PANE_NS} "namespace" ns
 
 	tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
 	tmux send-keys -t ${PANE_INFO} -N 100 C-m
@@ -137,8 +134,7 @@ layout_passt_in_pasta() {
 
 	pane_watch_contexts ${PANE_HOST} host host
 
-	tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
-	tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
+	pane_watch_contexts ${PANE_PASST} "passt in pasta (namespace)" pasta passt
 
 	info_layout "passt and guest in namespace, connected by pasta"
 
diff --git a/test/lib/setup b/test/lib/setup
index 6eccd8c..957a9cc 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -105,6 +105,7 @@ setup_pasta() {
 # setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
 setup_passt_in_ns() {
 	context_setup_host host
+	context_setup_host pasta
 
 	layout_passt_in_pasta
 
@@ -127,28 +128,18 @@ setup_passt_in_ns() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	__pid_file="$(mktemp)"
-	pane_run PASST "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P ${__pid_file}"
+	context_run_bg pasta "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P pasta.pid ${NSHOLDER} ns.hold hold"
 	sleep 1
-	pane_run PASST ''
-	pane_status PASST
-	__pasta_pid="$(cat "${__pid_file}")"
-	__ns_pid="$(cat /proc/${__pasta_pid}/task/${__pasta_pid}/children | cut -f1 -d' ')"
-	rm "${__pid_file}"
-
-	pane_run GUEST "nsenter -t ${__ns_pid} -U -n --preserve-credentials"
-	pane_run NS "nsenter -t ${__ns_pid} -U -n -p --preserve-credentials"
-	pane_status GUEST
-	pane_status NS
-
-	pane_run NS "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
-	pane_wait NS
-	__ifname="$(pane_parse NS)"
-	pane_run NS "/sbin/dhclient -4 --no-pid ${__ifname}"
-	pane_status NS
+	__ns_pid=$(${NSHOLDER} ns.hold pid)
+
+	context_setup_nsenter qemu "-t ${__ns_pid} -U -n -p --preserve-credentials"
+	context_setup_nsenter ns "-t ${__ns_pid} -U -n -p --preserve-credentials"
+	context_setup_nsenter passt "-t ${__ns_pid} -U -n -p --preserve-credentials"
+
+	__ifname=$(context_run ns "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")
+	context_run ns "/sbin/dhclient -4 --no-pid ${__ifname}"
 	sleep 2
-	pane_run NS "/sbin/dhclient -6 --no-pid ${__ifname}"
-	pane_status NS
+	context_run ns "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_in_pasta.pcap"
@@ -156,21 +147,18 @@ setup_passt_in_ns() {
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
 	if [ ${VALGRIND} -eq 1 ]; then
-		pane_run PASST "make clean"
-		pane_status PASST
-		pane_run PASST "make valgrind"
-		pane_status PASST
-		pane_run PASST "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+		context_run passt "make clean"
+		context_run passt "make valgrind"
+		context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
 	else
-		pane_run PASST "make clean"
-		pane_status PASST
-		pane_run PASST "make"
-		pane_status PASST
-		pane_run PASST "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+		context_run passt "make clean"
+		context_run passt "make"
+		context_run_bg passt "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
 	fi
 	sleep 5
 
-	pane_run GUEST './qrap 5 qemu-system-$(uname -m)'                  \
+	GUEST_CID=94557
+	context_run_bg qemu './qrap 5 qemu-system-$(uname -m)'                \
 		' -machine accel=kvm'                                      \
 		' -M accel=kvm:tcg'                                        \
 		' -m '${VMEM}' -cpu host -smp '${VCPUS}                    \
@@ -181,8 +169,10 @@ setup_passt_in_ns() {
 		'virtio-net.napi_tx=1"'					   \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=524288" \
 		" -netdev socket,fd=5,id=hostnet0"			   \
-		' -pidfile passt_in_ns_qemu.pid'
-	pane_status GUEST
+		' -pidfile passt_in_ns_qemu.pid'			   \
+		" -device vhost-vsock-pci,guest-cid=$GUEST_CID"
+
+	context_setup_guest guest $GUEST_CID
 }
 
 # setup_two_guests() - Set up two namespace, run qemu and passt in both of them
@@ -321,19 +311,18 @@ teardown_pasta() {
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
 teardown_passt_in_ns() {
-	kill $(cat passt_in_ns_qemu.pid)
-	pane_wait GUEST
-	tmux send-keys -t ${PANE_GUEST} "C-d"
-
-	tmux send-keys -t ${PANE_PASST} "C-d"
+	context_run ns kill $(cat passt_in_ns_qemu.pid)
+	context_wait qemu
 
-	pane_wait GUEST
-	pane_wait NS
-	pane_wait PASST
+	${NSHOLDER} ns.hold stop
+	context_wait pasta
 
-	rm passt.pid
+	rm passt.pid pasta.pid
 
 	teardown_context_watch ${PANE_HOST} host
+	teardown_context_watch ${PANE_PASST} pasta passt
+	teardown_context_watch ${PANE_NS} ns
+	teardown_context_watch ${PANE_GUEST} qemu guest
 }
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
diff --git a/test/shutdown/passt_in_ns b/test/shutdown/passt_in_ns
index a427bf4..3808adb 100644
--- a/test/shutdown/passt_in_ns
+++ b/test/shutdown/passt_in_ns
@@ -17,6 +17,4 @@ test	shutdown: exit code
 nsout	PASST_PID cat passt.pid
 ns	kill __PASST_PID__
 sleep	1
-
-pout	EXIT echo $?
-check	[ "__EXIT__" = "0" ]
+passtw
diff --git a/test/tcp/passt_in_ns b/test/tcp/passt_in_ns
index cb01781..a248f00 100644
--- a/test/tcp/passt_in_ns
+++ b/test/tcp/passt_in_ns
@@ -66,6 +66,7 @@ check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv4: ns to guest (using loopback address): big transfer
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
+sleep	1
 ns	socat -u OPEN:__TEMP_NS_BIG__ TCP4:127.0.0.1:10001
 guestw
 gout	GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
diff --git a/test/udp/passt_in_ns b/test/udp/passt_in_ns
index f5ea402..d5f08fe 100644
--- a/test/udp/passt_in_ns
+++ b/test/udp/passt_in_ns
@@ -19,6 +19,7 @@ test	UDP/IPv4: host to guest
 temp	TEMP
 temp	SC_PID
 guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
+sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
 guestw
-- 
@@ -19,6 +19,7 @@ test	UDP/IPv4: host to guest
 temp	TEMP
 temp	SC_PID
 guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
+sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
 guestw
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 12/32] Don't store UID & GID persistently in the context structure
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (10 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 11/32] test: Use new-style command issue for passt_in_ns tests David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 13/32] Split checking for root from dropping root privilege David Gibson
                   ` (19 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 3803 bytes --]

c->uid and c->gid are first set in conf(), and last used in check_root()
itself called from conf().  Therefore these don't need to be fields in the
long lived context structure and can instead be locals in conf().

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c  |  8 +++++---
 passt.h |  5 -----
 util.c  | 12 ++++++------
 util.h  |  2 +-
 4 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/conf.c b/conf.c
index 2edb4ae..0fe5266 100644
--- a/conf.c
+++ b/conf.c
@@ -1086,6 +1086,8 @@ void conf(struct ctx *c, int argc, char **argv)
 	uint32_t *dns4 = c->ip4.dns;
 	int name, ret, mask, b, i;
 	unsigned int ifi = 0;
+	uid_t uid = 0;
+	gid_t gid = 0;
 
 	if (c->mode == MODE_PASTA)
 		c->no_dhcp_dns = c->no_dhcp_dns_search = 1;
@@ -1208,12 +1210,12 @@ void conf(struct ctx *c, int argc, char **argv)
 			c->trace = c->debug = c->foreground = 1;
 			break;
 		case 12:
-			if (c->uid || c->gid) {
+			if (uid || gid) {
 				err("Multiple --runas options given");
 				usage(argv[0]);
 			}
 
-			if (conf_runas(optarg, &c->uid, &c->gid)) {
+			if (conf_runas(optarg, &uid, &gid)) {
 				err("Invalid --runas option: %s", optarg);
 				usage(argv[0]);
 			}
@@ -1497,7 +1499,7 @@ void conf(struct ctx *c, int argc, char **argv)
 		}
 	} while (name != -1);
 
-	check_root(c);
+	check_root(&uid, &gid);
 
 	if (c->mode == MODE_PASTA) {
 		if (*netns && optind != argc) {
diff --git a/passt.h b/passt.h
index 347e7c1..3035430 100644
--- a/passt.h
+++ b/passt.h
@@ -144,8 +144,6 @@ struct ip6_ctx {
  * @sock_path:		Path for UNIX domain socket
  * @pcap:		Path for packet capture file
  * @pid_file:		Path to PID file, empty string if not configured
- * @uid:		UID we should drop to, if started as root
- * @gid:		GID we should drop to, if started as root
  * @pasta_netns_fd:	File descriptor for network namespace in pasta mode
  * @pasta_userns_fd:	Descriptor for user namespace to join, -1 once joined
  * @netns_only:		In pasta mode, don't join or create a user namespace
@@ -198,9 +196,6 @@ struct ctx {
 	char pcap[PATH_MAX];
 	char pid_file[PATH_MAX];
 
-	uid_t uid;
-	uid_t gid;
-
 	int pasta_netns_fd;
 	int pasta_userns_fd;
 	int netns_only;
diff --git a/util.c b/util.c
index 7e10deb..b2ccb3d 100644
--- a/util.c
+++ b/util.c
@@ -485,7 +485,7 @@ void drop_caps(void)
 /**
  * check_root() - Check if root in init ns, exit if we can't drop to user
  */
-void check_root(struct ctx *c)
+void check_root(uid_t *uid, gid_t *gid)
 {
 	const char root_uid_map[] = "         0          0 4294967295";
 	struct passwd *pw;
@@ -506,7 +506,7 @@ void check_root(struct ctx *c)
 
 	close(fd);
 
-	if (!c->uid) {
+	if (!*uid) {
 		fprintf(stderr, "Don't run as root. Changing to nobody...\n");
 #ifndef GLIBC_NO_STATIC_NSS
 		pw = getpwnam("nobody");
@@ -515,17 +515,17 @@ void check_root(struct ctx *c)
 			exit(EXIT_FAILURE);
 		}
 
-		c->uid = pw->pw_uid;
-		c->gid = pw->pw_gid;
+		*uid = pw->pw_uid;
+		*gid = pw->pw_gid;
 #else
 		(void)pw;
 
 		/* Common value for 'nobody', not really specified */
-		c->uid = c->gid = 65534;
+		*uid = *gid = 65534;
 #endif
 	}
 
-	if (!setgroups(0, NULL) && !setgid(c->gid) && !setuid(c->uid))
+	if (!setgroups(0, NULL) && !setgid(*gid) && !setuid(*uid))
 		return;
 
 	fprintf(stderr, "Can't change user/group, exiting");
diff --git a/util.h b/util.h
index 8297bec..58312fb 100644
--- a/util.h
+++ b/util.h
@@ -234,7 +234,7 @@ char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
-void check_root(struct ctx *c);
+void check_root(uid_t *uid, gid_t *gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
@@ -234,7 +234,7 @@ char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
-void check_root(struct ctx *c);
+void check_root(uid_t *uid, gid_t *gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 13/32] Split checking for root from dropping root privilege
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (11 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 12/32] Don't store UID & GID persistently in the context structure David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 14/32] Consolidate determination of UID/GID to run as David Gibson
                   ` (18 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 4294 bytes --]

check_root() both checks to see if we are root (in the init namespace),
and if we are drops to an unprivileged user.  To make future cleanups
simpler, split the checking for root (now in check_root()) from the actual
dropping of privilege (now in drop_root()).

Note that this does slightly alter semantics.  Previously we would only
setuid() if we were originally root (in the init namespace).  Now we will
always setuid() and setgid(), though it won't actually change anything if
we weren't privileged to begin with.  This also means that we will now
always attempt to switch to the user specified with --runas, even if we
aren't (init namespace) root to begin with.  Obviously this will fail with
an error if we weren't privileged to start with.  --help and the man page
are updated accordingly.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c  |  5 +++--
 passt.1 |  5 +++--
 util.c  | 27 ++++++++++++++++++++++++---
 util.h  |  1 +
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/conf.c b/conf.c
index 0fe5266..545f61d 100644
--- a/conf.c
+++ b/conf.c
@@ -747,8 +747,8 @@ static void usage(const char *name)
 	info(   "    default: run in background if started from a TTY");
 	info(   "  -e, --stderr		Log to stderr too");
 	info(   "    default: log to system logger only if started from a TTY");
-	info(   "  --runas UID|UID:GID 	Use given UID, GID if started as root");
-	info(   "    UID and GID can be numeric, or login and group names");
+	info(   "  --runas UID|UID:GID 	Run as given UID, GID, which can be");
+	info(   "    numeric, or login and group names");
 	info(   "    default: drop to user \"nobody\"");
 	info(   "  -h, --help		Display this help message and exit");
 
@@ -1500,6 +1500,7 @@ void conf(struct ctx *c, int argc, char **argv)
 	} while (name != -1);
 
 	check_root(&uid, &gid);
+	drop_root(uid, gid);
 
 	if (c->mode == MODE_PASTA) {
 		if (*netns && optind != argc) {
diff --git a/passt.1 b/passt.1
index 61f0e4c..0a1593b 100644
--- a/passt.1
+++ b/passt.1
@@ -104,9 +104,10 @@ terminal, and to both system logger and standard error otherwise.
 
 .TP
 .BR \-\-runas " " \fIUID\fR|\fIUID:GID\fR|\fILOGIN\fR|\fILOGIN:GROUP\fR
-If started as root, change to given UID and corresponding group if UID is given,
+Attempt to change to given UID and corresponding group if UID is given,
 or to given UID and given GID if both are given. Alternatively, login name, or
-login name and group name can be passed.
+login name and group name can be passed.  This requires privilege (either
+initial effective UID 0 or CAP_SETUID capability) to work.
 Default is to change to user \fInobody\fR if started as root.
 
 .TP
diff --git a/util.c b/util.c
index b2ccb3d..17595c1 100644
--- a/util.c
+++ b/util.c
@@ -492,7 +492,13 @@ void check_root(uid_t *uid, gid_t *gid)
 	char buf[BUFSIZ];
 	int fd;
 
-	if (getuid() && geteuid())
+	if (!*uid)
+		*uid = geteuid();
+
+	if (!*gid)
+		*gid = getegid();
+
+	if (*uid)
 		return;
 
 	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0)
@@ -524,11 +530,26 @@ void check_root(uid_t *uid, gid_t *gid)
 		*uid = *gid = 65534;
 #endif
 	}
+}
+
+/**
+ * drop_root() - Switch to given UID and GID
+ */
+void drop_root(uid_t uid, gid_t gid)
+{
+	if (setgroups(0, NULL)) {
+		/* If we don't start with CAP_SETGID, this will EPERM */
+		if (errno != EPERM) {
+			err("Can't drop supplementary groups: %s",
+			    strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+	}
 
-	if (!setgroups(0, NULL) && !setgid(*gid) && !setuid(*uid))
+	if (!setgid(gid) && !setuid(uid))
 		return;
 
-	fprintf(stderr, "Can't change user/group, exiting");
+	err("Can't change user/group, exiting");
 	exit(EXIT_FAILURE);
 }
 
diff --git a/util.h b/util.h
index 58312fb..e2f686b 100644
--- a/util.h
+++ b/util.h
@@ -235,6 +235,7 @@ void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
 void check_root(uid_t *uid, gid_t *gid);
+void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
@@ -235,6 +235,7 @@ void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
 void check_root(uid_t *uid, gid_t *gid);
+void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 14/32] Consolidate determination of UID/GID to run as
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (12 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 13/32] Split checking for root from dropping root privilege David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 15/32] Safer handling if we can't open /proc/self/uid_map David Gibson
                   ` (17 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5283 bytes --]

Currently the logic to work out what UID and GID we will run as is spread
across conf().  If --runas is specified it's handled in conf_runas(),
otherwise it's handled by check_root(), which depends on initialization of
the uid and gid variables by either conf() itself or conf_runas().

Make this clearer by putting all the UID and GID logic into a single
conf_ugid() function.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 util.c | 50 ------------------------------------
 util.h |  1 -
 3 files changed, 73 insertions(+), 59 deletions(-)

diff --git a/conf.c b/conf.c
index 545f61d..5c293b5 100644
--- a/conf.c
+++ b/conf.c
@@ -1021,6 +1021,70 @@ static int conf_runas(const char *opt, unsigned int *uid, unsigned int *gid)
 #endif /* !GLIBC_NO_STATIC_NSS */
 }
 
+/**
+ * conf_ugid() - Determine UID and GID to run as
+ * @runas:	--runas option, may be NULL
+ * @uid:	User ID, set on success
+ * @gid:	Group ID, set on success
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int conf_ugid(const char *runas, uid_t *uid, gid_t *gid)
+{
+	const char root_uid_map[] = "         0          0 4294967295";
+	struct passwd *pw;
+	char buf[BUFSIZ];
+	int ret;
+	int fd;
+
+	/* If user has specified --runas, that takes precedence */
+	if (runas) {
+		ret = conf_runas(runas, uid, gid);
+		if (ret)
+			err("Invalid --runas option: %s", runas);
+		return ret;
+	}
+
+	/* Otherwise default to current user and group.. */
+	*uid = geteuid();
+	*gid = getegid();
+
+	/* ..as long as it's not root.. */
+	if (*uid)
+		return 0;
+
+	/* ..or at least not root in the init namespace.. */
+	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0)
+		return 0;
+
+	if (read(fd, buf, BUFSIZ) != sizeof(root_uid_map) ||
+	    strncmp(buf, root_uid_map, sizeof(root_uid_map) - 1)) {
+		close(fd);
+		return 0;
+	}
+
+	close(fd);
+
+	/* ..otherwise use nobody:nobody */
+	warn("Don't run as root. Changing to nobody...");
+#ifndef GLIBC_NO_STATIC_NSS
+	pw = getpwnam("nobody");
+	if (!pw) {
+		perror("getpwnam");
+		exit(EXIT_FAILURE);
+	}
+
+	*uid = pw->pw_uid;
+	*gid = pw->pw_gid;
+#else
+	(void)pw;
+
+	/* Common value for 'nobody', not really specified */
+	*uid = *gid = 65534;
+#endif
+	return 0;
+}
+
 /**
  * conf() - Process command-line arguments and set configuration
  * @c:		Execution context
@@ -1085,9 +1149,10 @@ void conf(struct ctx *c, int argc, char **argv)
 	struct fqdn *dnss = c->dns_search;
 	uint32_t *dns4 = c->ip4.dns;
 	int name, ret, mask, b, i;
+	const char *runas = NULL;
 	unsigned int ifi = 0;
-	uid_t uid = 0;
-	gid_t gid = 0;
+	uid_t uid;
+	gid_t gid;
 
 	if (c->mode == MODE_PASTA)
 		c->no_dhcp_dns = c->no_dhcp_dns_search = 1;
@@ -1210,15 +1275,12 @@ void conf(struct ctx *c, int argc, char **argv)
 			c->trace = c->debug = c->foreground = 1;
 			break;
 		case 12:
-			if (uid || gid) {
+			if (runas) {
 				err("Multiple --runas options given");
 				usage(argv[0]);
 			}
 
-			if (conf_runas(optarg, &uid, &gid)) {
-				err("Invalid --runas option: %s", optarg);
-				usage(argv[0]);
-			}
+			runas = optarg;
 			break;
 		case 'd':
 			if (c->debug) {
@@ -1499,7 +1561,10 @@ void conf(struct ctx *c, int argc, char **argv)
 		}
 	} while (name != -1);
 
-	check_root(&uid, &gid);
+	ret = conf_ugid(runas, &uid, &gid);
+	if (ret)
+		usage(argv[0]);
+
 	drop_root(uid, gid);
 
 	if (c->mode == MODE_PASTA) {
diff --git a/util.c b/util.c
index 17595c1..654410f 100644
--- a/util.c
+++ b/util.c
@@ -482,56 +482,6 @@ void drop_caps(void)
 	}
 }
 
-/**
- * check_root() - Check if root in init ns, exit if we can't drop to user
- */
-void check_root(uid_t *uid, gid_t *gid)
-{
-	const char root_uid_map[] = "         0          0 4294967295";
-	struct passwd *pw;
-	char buf[BUFSIZ];
-	int fd;
-
-	if (!*uid)
-		*uid = geteuid();
-
-	if (!*gid)
-		*gid = getegid();
-
-	if (*uid)
-		return;
-
-	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0)
-		return;
-
-	if (read(fd, buf, BUFSIZ) != sizeof(root_uid_map) ||
-	    strncmp(buf, root_uid_map, sizeof(root_uid_map) - 1)) {
-		close(fd);
-		return;
-	}
-
-	close(fd);
-
-	if (!*uid) {
-		fprintf(stderr, "Don't run as root. Changing to nobody...\n");
-#ifndef GLIBC_NO_STATIC_NSS
-		pw = getpwnam("nobody");
-		if (!pw) {
-			perror("getpwnam");
-			exit(EXIT_FAILURE);
-		}
-
-		*uid = pw->pw_uid;
-		*gid = pw->pw_gid;
-#else
-		(void)pw;
-
-		/* Common value for 'nobody', not really specified */
-		*uid = *gid = 65534;
-#endif
-	}
-}
-
 /**
  * drop_root() - Switch to given UID and GID
  */
diff --git a/util.h b/util.h
index e2f686b..9626cb5 100644
--- a/util.h
+++ b/util.h
@@ -234,7 +234,6 @@ char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
-void check_root(uid_t *uid, gid_t *gid);
 void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
-- 
@@ -234,7 +234,6 @@ char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
 void drop_caps(void);
-void check_root(uid_t *uid, gid_t *gid);
 void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 15/32] Safer handling if we can't open /proc/self/uid_map
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (13 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 14/32] Consolidate determination of UID/GID to run as David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 16/32] Move self-isolation code into a separate file David Gibson
                   ` (16 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 1524 bytes --]

passt is allowed to run as "root" (UID 0) in a user namespace, but notas
real root in the init namespace.  We read /proc/self/uid_map to determine
if we're in the init namespace or not.

If we're unable to open /proc/self/uid_map we assume we're ok and continue
running as UID 0.  This seems unwise: AFAIK the only instance in which
uid_map won't be available is if we're running on a kernel which doesn't
support user namespaces, in which case we won't be able to sandbox
ourselves as we want and fail anyway.  If there are other circumstances
where it can't be opened it seems marginally more likely that we *are*
in the init namespace.

Therefore, fail with an error in this case, instead of carrying on.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/conf.c b/conf.c
index 5c293b5..f1aaa8a 100644
--- a/conf.c
+++ b/conf.c
@@ -1054,8 +1054,12 @@ static int conf_ugid(const char *runas, uid_t *uid, gid_t *gid)
 		return 0;
 
 	/* ..or at least not root in the init namespace.. */
-	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0)
-		return 0;
+	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0) {
+		ret = -errno;
+		err("Can't determine if we're in init namespace: %s",
+		    strerror(-ret));
+		return ret;
+	}
 
 	if (read(fd, buf, BUFSIZ) != sizeof(root_uid_map) ||
 	    strncmp(buf, root_uid_map, sizeof(root_uid_map) - 1)) {
-- 
@@ -1054,8 +1054,12 @@ static int conf_ugid(const char *runas, uid_t *uid, gid_t *gid)
 		return 0;
 
 	/* ..or at least not root in the init namespace.. */
-	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0)
-		return 0;
+	if ((fd = open("/proc/self/uid_map", O_RDONLY | O_CLOEXEC)) < 0) {
+		ret = -errno;
+		err("Can't determine if we're in init namespace: %s",
+		    strerror(-ret));
+		return ret;
+	}
 
 	if (read(fd, buf, BUFSIZ) != sizeof(root_uid_map) ||
 	    strncmp(buf, root_uid_map, sizeof(root_uid_map) - 1)) {
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 16/32] Move self-isolation code into a separate file
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (14 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 15/32] Safer handling if we can't open /proc/self/uid_map David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 17/32] Consolidate validation of pasta namespace options David Gibson
                   ` (15 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 12646 bytes --]

passt/pasta contains a number of routines designed to isolate passt from
the rest of the system for security.  These are spread through util.c and
passt.c.  Move them together into a new isolation.c file.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 Makefile    |   8 +--
 conf.c      |   1 +
 isolation.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 isolation.h |  15 +++++
 passt.c     | 113 +----------------------------------
 pasta.c     |   1 +
 util.c      |  49 ----------------
 util.h      |   2 -
 8 files changed, 187 insertions(+), 167 deletions(-)
 create mode 100644 isolation.c
 create mode 100644 isolation.h

diff --git a/Makefile b/Makefile
index 644a541..af3d1ff 100644
--- a/Makefile
+++ b/Makefile
@@ -32,16 +32,16 @@ CFLAGS += -DRLIMIT_STACK_VAL=$(RLIMIT_STACK_VAL)
 CFLAGS += -DARCH=\"$(TARGET_ARCH)\"
 
 PASST_SRCS = arch.c arp.c checksum.c conf.c dhcp.c dhcpv6.c icmp.c igmp.c \
-	lineread.c mld.c ndp.c netlink.c packet.c passt.c pasta.c pcap.c \
-	siphash.c tap.c tcp.c tcp_splice.c udp.c util.c
+	isolation.c lineread.c mld.c ndp.c netlink.c packet.c passt.c pasta.c \
+	pcap.c siphash.c tap.c tcp.c tcp_splice.c udp.c util.c
 QRAP_SRCS = qrap.c
 SRCS = $(PASST_SRCS) $(QRAP_SRCS)
 
 MANPAGES = passt.1 pasta.1 qrap.1
 
 PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h icmp.h \
-	lineread.h ndp.h netlink.h packet.h passt.h pasta.h pcap.h \
-	siphash.h tap.h tcp.h tcp_splice.h udp.h util.h
+	isolation.h lineread.h ndp.h netlink.h packet.h passt.h pasta.h \
+	pcap.h siphash.h tap.h tcp.h tcp_splice.h udp.h util.h
 HEADERS = $(PASST_HEADERS)
 
 # On gcc 11.2, with -O2 and -flto, tcp_hash() and siphash_20b(), if inlined,
diff --git a/conf.c b/conf.c
index f1aaa8a..08a2106 100644
--- a/conf.c
+++ b/conf.c
@@ -40,6 +40,7 @@
 #include "tcp.h"
 #include "pasta.h"
 #include "lineread.h"
+#include "isolation.h"
 
 /**
  * get_bound_ports() - Get maps of ports with bound sockets
diff --git a/isolation.c b/isolation.c
new file mode 100644
index 0000000..bc8240f
--- /dev/null
+++ b/isolation.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+/* PASST - Plug A Simple Socket Transport
+ *  for qemu/UNIX domain socket mode
+ *
+ * PASTA - Pack A Subtle Tap Abstraction
+ *  for network namespace/tap device mode
+ *
+ * isolation.c - Self isolation helpers
+ *
+ * Copyright Red Hat
+ * Author: Stefano Brivio <sbrivio(a)redhat.com>
+ * Author: David Gibson <david(a)gibson.dropbear.id.au>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <pwd.h>
+#include <sched.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <linux/audit.h>
+#include <linux/capability.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#include "util.h"
+#include "seccomp.h"
+#include "passt.h"
+#include "isolation.h"
+
+/**
+ * drop_caps() - Drop capabilities we might have except for CAP_NET_BIND_SERVICE
+ */
+void drop_caps(void)
+{
+	int i;
+
+	for (i = 0; i < 64; i++) {
+		if (i == CAP_NET_BIND_SERVICE)
+			continue;
+
+		prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+	}
+}
+
+/**
+ * drop_root() - Switch to given UID and GID
+ */
+void drop_root(uid_t uid, gid_t gid)
+{
+	if (setgroups(0, NULL)) {
+		/* If we don't start with CAP_SETGID, this will EPERM */
+		if (errno != EPERM) {
+			err("Can't drop supplementary groups: %s",
+			    strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if (!setgid(gid) && !setuid(uid))
+		return;
+
+	err("Can't change user/group, exiting");
+	exit(EXIT_FAILURE);
+}
+
+/**
+ * sandbox() - Unshare IPC, mount, PID, UTS, and user namespaces, "unmount" root
+ *
+ * Return: negative error code on failure, zero on success
+ */
+int sandbox(struct ctx *c)
+{
+	int flags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS;
+
+	if (!c->netns_only) {
+		if (c->pasta_userns_fd == -1)
+			flags |= CLONE_NEWUSER;
+		else
+			setns(c->pasta_userns_fd, CLONE_NEWUSER);
+	}
+
+	c->pasta_userns_fd = -1;
+
+	/* If we run in foreground, we have no chance to actually move to a new
+	 * PID namespace. For passt, use CLONE_NEWPID anyway, in case somebody
+	 * ever gets around seccomp profiles -- there's no harm in passing it.
+	 */
+	if (!c->foreground || c->mode == MODE_PASST)
+		flags |= CLONE_NEWPID;
+
+	if (unshare(flags)) {
+		perror("unshare");
+		return -errno;
+	}
+
+	if (mount("", "/", "", MS_UNBINDABLE | MS_REC, NULL)) {
+		perror("mount /");
+		return -errno;
+	}
+
+	if (mount("", TMPDIR, "tmpfs",
+		  MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY,
+		  "nr_inodes=2,nr_blocks=0")) {
+		perror("mount tmpfs");
+		return -errno;
+	}
+
+	if (chdir(TMPDIR)) {
+		perror("chdir");
+		return -errno;
+	}
+
+	if (syscall(SYS_pivot_root, ".", ".")) {
+		perror("pivot_root");
+		return -errno;
+	}
+
+	if (umount2(".", MNT_DETACH | UMOUNT_NOFOLLOW)) {
+		perror("umount2");
+		return -errno;
+	}
+
+	drop_caps();	/* Relative to the new user namespace this time. */
+
+	return 0;
+}
+
+/**
+ * seccomp() - Set up seccomp filters depending on mode, won't return on failure
+ * @c:		Execution context
+ */
+void seccomp(const struct ctx *c)
+{
+	struct sock_fprog prog;
+
+	if (c->mode == MODE_PASST) {
+		prog.len = (unsigned short)ARRAY_SIZE(filter_passt);
+		prog.filter = filter_passt;
+	} else {
+		prog.len = (unsigned short)ARRAY_SIZE(filter_pasta);
+		prog.filter = filter_pasta;
+	}
+
+	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
+	    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
+		perror("prctl");
+		exit(EXIT_FAILURE);
+	}
+}
diff --git a/isolation.h b/isolation.h
new file mode 100644
index 0000000..2540a35
--- /dev/null
+++ b/isolation.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: AGPL-3.0-or-later
+ * Copyright Red Hat
+ * Author: Stefano Brivio <sbrivio(a)redhat.com>
+ * Author: David Gibson <david(a)gibson.dropbear.id.au>
+ */
+
+#ifndef ISOLATION_H
+#define ISOLATION_H
+
+void drop_caps(void);
+void drop_root(uid_t uid, gid_t gid);
+int sandbox(struct ctx *c);
+void seccomp(const struct ctx *c);
+
+#endif /* ISOLATION_H */
diff --git a/passt.c b/passt.c
index bbf53d9..2a8314c 100644
--- a/passt.c
+++ b/passt.c
@@ -19,51 +19,25 @@
  * created in a separate network namespace).
  */
 
-#include <sched.h>
-#include <stdio.h>
 #include <sys/epoll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
-#include <sys/uio.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <sys/mount.h>
-#include <netinet/ip.h>
-#include <net/ethernet.h>
-#include <libgen.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <net/if.h>
 #include <netdb.h>
 #include <string.h>
 #include <errno.h>
 #include <time.h>
 #include <syslog.h>
-#include <sys/stat.h>
 #include <sys/prctl.h>
-#include <stddef.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
 #include <netinet/if_ether.h>
 
-#include <linux/seccomp.h>
-#include <linux/audit.h>
-#include <linux/filter.h>
-#include <linux/icmpv6.h>
-
 #include "util.h"
-#include "seccomp.h"
 #include "passt.h"
 #include "dhcp.h"
 #include "dhcpv6.h"
-#include "icmp.h"
-#include "tcp.h"
-#include "udp.h"
+#include "isolation.h"
 #include "pcap.h"
 #include "tap.h"
 #include "conf.h"
@@ -166,91 +140,6 @@ void proto_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s,
 	udp_update_l2_buf(eth_d, eth_s, ip_da);
 }
 
-/**
- * seccomp() - Set up seccomp filters depending on mode, won't return on failure
- * @c:		Execution context
- */
-static void seccomp(const struct ctx *c)
-{
-	struct sock_fprog prog;
-
-	if (c->mode == MODE_PASST) {
-		prog.len = (unsigned short)ARRAY_SIZE(filter_passt);
-		prog.filter = filter_passt;
-	} else {
-		prog.len = (unsigned short)ARRAY_SIZE(filter_pasta);
-		prog.filter = filter_pasta;
-	}
-
-	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
-	    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
-		perror("prctl");
-		exit(EXIT_FAILURE);
-	}
-}
-
-/**
- * sandbox() - Unshare IPC, mount, PID, UTS, and user namespaces, "unmount" root
- *
- * Return: negative error code on failure, zero on success
- */
-static int sandbox(struct ctx *c)
-{
-	int flags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS;
-
-	if (!c->netns_only) {
-		if (c->pasta_userns_fd == -1)
-			flags |= CLONE_NEWUSER;
-		else
-			setns(c->pasta_userns_fd, CLONE_NEWUSER);
-	}
-
-	c->pasta_userns_fd = -1;
-
-	/* If we run in foreground, we have no chance to actually move to a new
-	 * PID namespace. For passt, use CLONE_NEWPID anyway, in case somebody
-	 * ever gets around seccomp profiles -- there's no harm in passing it.
-	 */
-	if (!c->foreground || c->mode == MODE_PASST)
-		flags |= CLONE_NEWPID;
-
-	if (unshare(flags)) {
-		perror("unshare");
-		return -errno;
-	}
-
-	if (mount("", "/", "", MS_UNBINDABLE | MS_REC, NULL)) {
-		perror("mount /");
-		return -errno;
-	}
-
-	if (mount("", TMPDIR, "tmpfs",
-		  MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RDONLY,
-		  "nr_inodes=2,nr_blocks=0")) {
-		perror("mount tmpfs");
-		return -errno;
-	}
-
-	if (chdir(TMPDIR)) {
-		perror("chdir");
-		return -errno;
-	}
-
-	if (syscall(SYS_pivot_root, ".", ".")) {
-		perror("pivot_root");
-		return -errno;
-	}
-
-	if (umount2(".", MNT_DETACH | UMOUNT_NOFOLLOW)) {
-		perror("umount2");
-		return -errno;
-	}
-
-	drop_caps();	/* Relative to the new user namespace this time. */
-
-	return 0;
-}
-
 /**
  * exit_handler() - Signal handler for SIGQUIT and SIGTERM
  * @unused:	Unused, handler deals with SIGQUIT and SIGTERM only
diff --git a/pasta.c b/pasta.c
index a844af2..0bdb655 100644
--- a/pasta.c
+++ b/pasta.c
@@ -40,6 +40,7 @@
 
 #include "util.h"
 #include "passt.h"
+#include "isolation.h"
 #include "netlink.h"
 
 /* PID of child, in case we created a namespace */
diff --git a/util.c b/util.c
index 654410f..f709838 100644
--- a/util.c
+++ b/util.c
@@ -13,30 +13,17 @@
  */
 
 #include <sched.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stddef.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <net/ethernet.h>
-#include <net/if.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
 #include <sys/epoll.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <fcntl.h>
 #include <syslog.h>
 #include <stdarg.h>
 #include <string.h>
 #include <time.h>
 #include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <linux/capability.h>
 
 #include "util.h"
 #include "passt.h"
@@ -467,42 +454,6 @@ void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 	}
 }
 
-/**
- * drop_caps() - Drop capabilities we might have except for CAP_NET_BIND_SERVICE
- */
-void drop_caps(void)
-{
-	int i;
-
-	for (i = 0; i < 64; i++) {
-		if (i == CAP_NET_BIND_SERVICE)
-			continue;
-
-		prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
-	}
-}
-
-/**
- * drop_root() - Switch to given UID and GID
- */
-void drop_root(uid_t uid, gid_t gid)
-{
-	if (setgroups(0, NULL)) {
-		/* If we don't start with CAP_SETGID, this will EPERM */
-		if (errno != EPERM) {
-			err("Can't drop supplementary groups: %s",
-			    strerror(errno));
-			exit(EXIT_FAILURE);
-		}
-	}
-
-	if (!setgid(gid) && !setuid(uid))
-		return;
-
-	err("Can't change user/group, exiting");
-	exit(EXIT_FAILURE);
-}
-
 /**
  * ns_enter() - Enter configured user (unless already joined) and network ns
  * @c:		Execution context
diff --git a/util.h b/util.h
index 9626cb5..1003303 100644
--- a/util.h
+++ b/util.h
@@ -233,8 +233,6 @@ int bitmap_isset(const uint8_t *map, int bit);
 char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
-void drop_caps(void);
-void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
@@ -233,8 +233,6 @@ int bitmap_isset(const uint8_t *map, int bit);
 char *line_read(char *buf, size_t len, int fd);
 void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
 			uint8_t *map, uint8_t *exclude);
-void drop_caps(void);
-void drop_root(uid_t uid, gid_t gid);
 int ns_enter(const struct ctx *c);
 void write_pidfile(int fd, pid_t pid);
 int __daemon(int pidfile_fd, int devnull_fd);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 17/32] Consolidate validation of pasta namespace options
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (15 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 16/32] Move self-isolation code into a separate file David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 18/32] Clean up and rename conf_ns_open() David Gibson
                   ` (14 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5583 bytes --]

There are a number of different ways to specify namespaces for pasta to
use.  Some combinations are valid and some are not.  Currently validation
for these is spread across several places: conf_ns_pid() validates PID
options specifically.  Near its callsite in conf() several other checks
are made. Some additional checks are made in conf_ns_open() and finally
theres a check just before the call to pasta_start_ns().

This is quite hard to follow.  Make it easier by putting all the validation
logic together in a new conf_pasta_ns() function, which subsumes
conf_ns_pid().  This reveals that some of the checks were redundant with
each other, so remove those.

For good measure, rename conf_netns() to conf_netns_opt() to make it
clearer its handling just the --netns option specifically, not overall
configuration of the netns.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c | 83 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 42 insertions(+), 41 deletions(-)

diff --git a/conf.c b/conf.c
index 08a2106..5018794 100644
--- a/conf.c
+++ b/conf.c
@@ -491,13 +491,13 @@ out:
 }
 
 /**
- * conf_netns() - Parse --netns option
+ * conf_netns_opt() - Parse --netns option
  * @netns:	buffer of size PATH_MAX, updated with netns path
  * @arg:	--netns argument
  *
  * Return: 0 on success, negative error code otherwise
  */
-static int conf_netns(char *netns, const char *arg)
+static int conf_netns_opt(char *netns, const char *arg)
 {
 	int ret;
 
@@ -518,40 +518,59 @@ static int conf_netns(char *netns, const char *arg)
 }
 
 /**
- * conf_ns_pid() - Parse non-option argument as a PID
+ * conf_pasta_ns() - Validate all pasta namespace options
+ * @netns_only:	Don't use userns, may be updated
  * @userns:	buffer of size PATH_MAX, initially contains --userns
  *		argument (may be empty), updated with userns path
  * @netns:	buffer of size PATH_MAX, initial contains --netns
  *		argument (may be empty), updated with netns path
- * @arg:	PID of network namespace
+ * @optind:	Index of first non-option argument
+ * @argc:	Number of arguments
+ * @argv:	Command line arguments
  *
  * Return: 0 on success, negative error code otherwise
  */
-static int conf_ns_pid(char *userns, char *netns, const char *arg)
+static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
+			 int optind, int argc, char *argv[])
 {
-	char *endptr;
-	long pidval;
+	if (*netns_only && *userns) {
+		err("Both --userns and --netns-only given");
+		return -EINVAL;
+	}
 
-	if (*netns) {
-		err("Both --netns and PID given");
+	if (*netns && optind != argc) {
+		err("Both --netns and PID or command given");
 		return -EINVAL;
 	}
 
-	pidval = strtol(arg, &endptr, 10);
-	if (!*endptr) {
-		/* Looks like a pid */
-		if (pidval < 0 || pidval > INT_MAX) {
-			err("Invalid PID %s", arg);
-			return -EINVAL;
+	if (optind + 1 == argc) {
+		char *endptr;
+		long pidval;
+
+		pidval = strtol(argv[optind], &endptr, 10);
+		if (!*endptr) {
+			/* Looks like a pid */
+			if (pidval < 0 || pidval > INT_MAX) {
+				err("Invalid PID %s", argv[optind]);
+				return -EINVAL;
+			}
+
+			snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
+			if (!*userns)
+				snprintf(userns, PATH_MAX, "/proc/%ld/ns/user",
+					 pidval);
 		}
+	}
 
-		snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
-		if (!*userns)
-			snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", pidval);
-		return 0;
+	if (*userns && !*netns) {
+		err("--userns requires --netns or PID");
+		return -EINVAL;
 	}
 
-	/* Not a PID, later code will treat as a command */
+	/* Attaching to a netns/PID, with no userns given */
+	if (*netns && !*userns)
+		*netns_only = 1;
+
 	return 0;
 }
 
@@ -585,11 +604,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
 {
 	int ufd = -1, nfd = -1;
 
-	if (c->netns_only && *userns) {
-		err("Both --userns and --netns-only given");
-		return -EINVAL;
-	}
-
 	nfd = open(netns, O_RDONLY | O_CLOEXEC);
 	if (nfd < 0) {
 		err("Couldn't open network namespace %s", netns);
@@ -607,7 +621,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
 
 	c->pasta_netns_fd = nfd;
 	c->pasta_userns_fd = ufd;
-	c->netns_only = !*userns;
 
 	NS_CALL(conf_ns_check, c);
 
@@ -1194,7 +1207,7 @@ void conf(struct ctx *c, int argc, char **argv)
 				usage(argv[0]);
 			}
 
-			ret = conf_netns(netns, optarg);
+			ret = conf_netns_opt(netns, optarg);
 			if (ret < 0)
 				usage(argv[0]);
 			break;
@@ -1573,17 +1586,9 @@ void conf(struct ctx *c, int argc, char **argv)
 	drop_root(uid, gid);
 
 	if (c->mode == MODE_PASTA) {
-		if (*netns && optind != argc) {
-			err("Both --netns and PID or command given");
-			usage(argv[0]);
-		} else if (optind + 1 == argc) {
-			ret = conf_ns_pid(userns, netns, argv[optind]);
-			if (ret < 0)
-				usage(argv[0]);
-		} else if (*userns && !*netns && optind == argc) {
-			err("--userns requires --netns or PID");
+		if (conf_pasta_ns(&c->netns_only, userns, netns,
+				  optind, argc, argv) < 0)
 			usage(argv[0]);
-		}
 	} else if (optind != argc) {
 		usage(argv[0]);
 	}
@@ -1597,10 +1602,6 @@ void conf(struct ctx *c, int argc, char **argv)
 			if (ret < 0)
 				usage(argv[0]);
 		} else {
-			if (*userns) {
-				err("Both --userns and command given");
-				usage(argv[0]);
-			}
 			pasta_start_ns(c, argc - optind, argv + optind);
 		}
 	}
-- 
@@ -491,13 +491,13 @@ out:
 }
 
 /**
- * conf_netns() - Parse --netns option
+ * conf_netns_opt() - Parse --netns option
  * @netns:	buffer of size PATH_MAX, updated with netns path
  * @arg:	--netns argument
  *
  * Return: 0 on success, negative error code otherwise
  */
-static int conf_netns(char *netns, const char *arg)
+static int conf_netns_opt(char *netns, const char *arg)
 {
 	int ret;
 
@@ -518,40 +518,59 @@ static int conf_netns(char *netns, const char *arg)
 }
 
 /**
- * conf_ns_pid() - Parse non-option argument as a PID
+ * conf_pasta_ns() - Validate all pasta namespace options
+ * @netns_only:	Don't use userns, may be updated
  * @userns:	buffer of size PATH_MAX, initially contains --userns
  *		argument (may be empty), updated with userns path
  * @netns:	buffer of size PATH_MAX, initial contains --netns
  *		argument (may be empty), updated with netns path
- * @arg:	PID of network namespace
+ * @optind:	Index of first non-option argument
+ * @argc:	Number of arguments
+ * @argv:	Command line arguments
  *
  * Return: 0 on success, negative error code otherwise
  */
-static int conf_ns_pid(char *userns, char *netns, const char *arg)
+static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
+			 int optind, int argc, char *argv[])
 {
-	char *endptr;
-	long pidval;
+	if (*netns_only && *userns) {
+		err("Both --userns and --netns-only given");
+		return -EINVAL;
+	}
 
-	if (*netns) {
-		err("Both --netns and PID given");
+	if (*netns && optind != argc) {
+		err("Both --netns and PID or command given");
 		return -EINVAL;
 	}
 
-	pidval = strtol(arg, &endptr, 10);
-	if (!*endptr) {
-		/* Looks like a pid */
-		if (pidval < 0 || pidval > INT_MAX) {
-			err("Invalid PID %s", arg);
-			return -EINVAL;
+	if (optind + 1 == argc) {
+		char *endptr;
+		long pidval;
+
+		pidval = strtol(argv[optind], &endptr, 10);
+		if (!*endptr) {
+			/* Looks like a pid */
+			if (pidval < 0 || pidval > INT_MAX) {
+				err("Invalid PID %s", argv[optind]);
+				return -EINVAL;
+			}
+
+			snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
+			if (!*userns)
+				snprintf(userns, PATH_MAX, "/proc/%ld/ns/user",
+					 pidval);
 		}
+	}
 
-		snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
-		if (!*userns)
-			snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", pidval);
-		return 0;
+	if (*userns && !*netns) {
+		err("--userns requires --netns or PID");
+		return -EINVAL;
 	}
 
-	/* Not a PID, later code will treat as a command */
+	/* Attaching to a netns/PID, with no userns given */
+	if (*netns && !*userns)
+		*netns_only = 1;
+
 	return 0;
 }
 
@@ -585,11 +604,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
 {
 	int ufd = -1, nfd = -1;
 
-	if (c->netns_only && *userns) {
-		err("Both --userns and --netns-only given");
-		return -EINVAL;
-	}
-
 	nfd = open(netns, O_RDONLY | O_CLOEXEC);
 	if (nfd < 0) {
 		err("Couldn't open network namespace %s", netns);
@@ -607,7 +621,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
 
 	c->pasta_netns_fd = nfd;
 	c->pasta_userns_fd = ufd;
-	c->netns_only = !*userns;
 
 	NS_CALL(conf_ns_check, c);
 
@@ -1194,7 +1207,7 @@ void conf(struct ctx *c, int argc, char **argv)
 				usage(argv[0]);
 			}
 
-			ret = conf_netns(netns, optarg);
+			ret = conf_netns_opt(netns, optarg);
 			if (ret < 0)
 				usage(argv[0]);
 			break;
@@ -1573,17 +1586,9 @@ void conf(struct ctx *c, int argc, char **argv)
 	drop_root(uid, gid);
 
 	if (c->mode == MODE_PASTA) {
-		if (*netns && optind != argc) {
-			err("Both --netns and PID or command given");
-			usage(argv[0]);
-		} else if (optind + 1 == argc) {
-			ret = conf_ns_pid(userns, netns, argv[optind]);
-			if (ret < 0)
-				usage(argv[0]);
-		} else if (*userns && !*netns && optind == argc) {
-			err("--userns requires --netns or PID");
+		if (conf_pasta_ns(&c->netns_only, userns, netns,
+				  optind, argc, argv) < 0)
 			usage(argv[0]);
-		}
 	} else if (optind != argc) {
 		usage(argv[0]);
 	}
@@ -1597,10 +1602,6 @@ void conf(struct ctx *c, int argc, char **argv)
 			if (ret < 0)
 				usage(argv[0]);
 		} else {
-			if (*userns) {
-				err("Both --userns and command given");
-				usage(argv[0]);
-			}
 			pasta_start_ns(c, argc - optind, argv + optind);
 		}
 	}
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 18/32] Clean up and rename conf_ns_open()
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (16 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 17/32] Consolidate validation of pasta namespace options David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 19/32] Correctly handle --netns-only in pasta_start_ns() David Gibson
                   ` (13 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5662 bytes --]

conf_ns_open() opens file descriptors for the namespaces pasta needs, but
it doesnt really have anything to do with configuration any more.  For
better clarity, move it to pasta.c and rename it pasta_open_ns().  This
makes the symmetry between it and pasta_start_ns() more clear, since these
represent the two basic ways that pasta can operate, either attaching to
an existing namespace/process or spawning a new one.

Since its no longer validating options, the errors it could return
shouldn't cause a usage message.  Just exit directly with an error instead.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c  | 72 +--------------------------------------------------------
 pasta.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 pasta.h |  1 +
 3 files changed, 68 insertions(+), 71 deletions(-)

diff --git a/conf.c b/conf.c
index 5018794..7171748 100644
--- a/conf.c
+++ b/conf.c
@@ -20,7 +20,6 @@
 #include <sched.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <libgen.h>
 #include <limits.h>
 #include <grp.h>
 #include <pwd.h>
@@ -574,73 +573,6 @@ static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
 	return 0;
 }
 
-/**
- * conf_ns_check() - Check if we can enter configured namespaces
- * @arg:	Execution context
- *
- * Return: 0
- */
-static int conf_ns_check(void *arg)
-{
-	struct ctx *c = (struct ctx *)arg;
-
-	if ((!c->netns_only && setns(c->pasta_userns_fd, CLONE_NEWUSER)) ||
-	    setns(c->pasta_netns_fd, CLONE_NEWNET))
-		c->pasta_userns_fd = c->pasta_netns_fd = -1;
-
-	return 0;
-
-}
-
-/**
- * conf_ns_open() - Open network, user namespaces descriptors from configuration
- * @c:		Execution context
- * @userns:	--userns argument, can be an empty string
- * @netns:	network namespace path
- *
- * Return: 0 on success, negative error code otherwise
- */
-static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
-{
-	int ufd = -1, nfd = -1;
-
-	nfd = open(netns, O_RDONLY | O_CLOEXEC);
-	if (nfd < 0) {
-		err("Couldn't open network namespace %s", netns);
-		return -ENOENT;
-	}
-
-	if (!c->netns_only && *userns) {
-		ufd = open(userns, O_RDONLY | O_CLOEXEC);
-		if (ufd < 0) {
-			close(nfd);
-			err("Couldn't open user namespace %s", userns);
-			return -ENOENT;
-		}
-	}
-
-	c->pasta_netns_fd = nfd;
-	c->pasta_userns_fd = ufd;
-
-	NS_CALL(conf_ns_check, c);
-
-	if (c->pasta_netns_fd < 0) {
-		err("Couldn't switch to pasta namespaces");
-		return -ENOENT;
-	}
-
-	if (!c->no_netns_quit) {
-		char buf[PATH_MAX];
-
-		strncpy(buf, netns, PATH_MAX);
-		strncpy(c->netns_base, basename(buf), PATH_MAX - 1);
-		strncpy(buf, netns, PATH_MAX);
-		strncpy(c->netns_dir, dirname(buf), PATH_MAX - 1);
-	}
-
-	return 0;
-}
-
 /**
  * conf_ip4() - Verify or detect IPv4 support, get relevant addresses
  * @ifi:	Host interface to attempt (0 to determine one)
@@ -1598,9 +1530,7 @@ void conf(struct ctx *c, int argc, char **argv)
 
 	if (c->mode == MODE_PASTA) {
 		if (*netns) {
-			ret = conf_ns_open(c, userns, netns);
-			if (ret < 0)
-				usage(argv[0]);
+			pasta_open_ns(c, userns, netns);
 		} else {
 			pasta_start_ns(c, argc - optind, argv + optind);
 		}
diff --git a/pasta.c b/pasta.c
index 0bdb655..0fd45e4 100644
--- a/pasta.c
+++ b/pasta.c
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+#include <libgen.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -101,6 +102,71 @@ netns:
 	return 0;
 }
 
+/**
+ * ns_check() - Check if we can enter configured namespaces
+ * @arg:	Execution context
+ *
+ * Return: 0
+ */
+static int ns_check(void *arg)
+{
+	struct ctx *c = (struct ctx *)arg;
+
+	if ((!c->netns_only && setns(c->pasta_userns_fd, CLONE_NEWUSER)) ||
+	    setns(c->pasta_netns_fd, CLONE_NEWNET))
+		c->pasta_userns_fd = c->pasta_netns_fd = -1;
+
+	return 0;
+
+}
+
+/**
+ * pasta_open_ns() - Open network, user namespaces descriptors
+ * @c:		Execution context
+ * @userns:	--userns argument, can be an empty string
+ * @netns:	network namespace path
+ *
+ * Return: 0 on success, negative error code otherwise
+ */
+void pasta_open_ns(struct ctx *c, const char *userns, const char *netns)
+{
+	int ufd = -1, nfd = -1;
+
+	nfd = open(netns, O_RDONLY | O_CLOEXEC);
+	if (nfd < 0) {
+		err("Couldn't open network namespace %s", netns);
+		exit(EXIT_FAILURE);
+	}
+
+	if (!c->netns_only && *userns) {
+		ufd = open(userns, O_RDONLY | O_CLOEXEC);
+		if (ufd < 0) {
+			close(nfd);
+			err("Couldn't open user namespace %s", userns);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	c->pasta_netns_fd = nfd;
+	c->pasta_userns_fd = ufd;
+
+	NS_CALL(ns_check, c);
+
+	if (c->pasta_netns_fd < 0) {
+		err("Couldn't switch to pasta namespaces");
+		exit(EXIT_FAILURE);
+	}
+
+	if (!c->no_netns_quit) {
+		char buf[PATH_MAX] = { 0 };
+
+		strncpy(buf, netns, PATH_MAX - 1);
+		strncpy(c->netns_base, basename(buf), PATH_MAX - 1);
+		strncpy(buf, netns, PATH_MAX - 1);
+		strncpy(c->netns_dir, dirname(buf), PATH_MAX - 1);
+	}
+}
+
 /**
  * struct pasta_setup_ns_arg - Argument for pasta_setup_ns()
  * @c:		Execution context
diff --git a/pasta.h b/pasta.h
index 19b2e54..a1937b2 100644
--- a/pasta.h
+++ b/pasta.h
@@ -6,6 +6,7 @@
 #ifndef PASTA_H
 #define PASTA_H
 
+void pasta_open_ns(struct ctx *c, const char *userns, const char *netns);
 void pasta_start_ns(struct ctx *c, int argc, char *argv[]);
 void pasta_ns_conf(struct ctx *c);
 void pasta_child_handler(int signal);
-- 
@@ -6,6 +6,7 @@
 #ifndef PASTA_H
 #define PASTA_H
 
+void pasta_open_ns(struct ctx *c, const char *userns, const char *netns);
 void pasta_start_ns(struct ctx *c, int argc, char *argv[]);
 void pasta_ns_conf(struct ctx *c);
 void pasta_child_handler(int signal);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 19/32] Correctly handle --netns-only in pasta_start_ns()
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (17 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 18/32] Clean up and rename conf_ns_open() David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 20/32] Handle userns isolation and dropping root at the same time David Gibson
                   ` (12 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 873 bytes --]

--netns-only is supposed to make pasta use only a network namespace, not
a user namespace.  However, pasta_start_ns() has this backwards, and if
--netns-only is specified it creates a user namespace but *not* a network
namespace.  Correct this.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 pasta.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pasta.c b/pasta.c
index 0fd45e4..7eac8e9 100644
--- a/pasta.c
+++ b/pasta.c
@@ -244,8 +244,8 @@ void pasta_start_ns(struct ctx *c, int argc, char *argv[])
 
 	pasta_child_pid = clone(pasta_setup_ns,
 				ns_fn_stack + sizeof(ns_fn_stack) / 2,
-				(c->netns_only ? 0 : CLONE_NEWNET) |
-				CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWUSER |
+				(c->netns_only ? 0 : CLONE_NEWUSER) |
+				CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET |
 				CLONE_NEWUTS,
 				(void *)&arg);
 
-- 
@@ -244,8 +244,8 @@ void pasta_start_ns(struct ctx *c, int argc, char *argv[])
 
 	pasta_child_pid = clone(pasta_setup_ns,
 				ns_fn_stack + sizeof(ns_fn_stack) / 2,
-				(c->netns_only ? 0 : CLONE_NEWNET) |
-				CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWUSER |
+				(c->netns_only ? 0 : CLONE_NEWUSER) |
+				CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET |
 				CLONE_NEWUTS,
 				(void *)&arg);
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 20/32] Handle userns isolation and dropping root at the same time
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (18 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 19/32] Correctly handle --netns-only in pasta_start_ns() David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 21/32] Allow --userns when pasta spawns a command David Gibson
                   ` (11 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 12918 bytes --]

passt/pasta can interact with user namespaces in a number of ways:
   1) With --netns-only we'll remain in our original user namespace
   2) With --userns or a PID option to pasta we'll join either the given
      user namespace or that of the PID
   3) When pasta spawns a shell or command we'll start a new user namespace
      for the command and then join it
   4) With passt we'll create a new user namespace when we sandbox()
      ourself

However (3) and (4) turn out to have essentially the same effect.  In both
cases we create one new user namespace.  The spawned command starts there,
and passt/pasta itself will live there from sandbox() onwards.

Because of this, we can simplify user namespace handling by moving the
userns handling earlier, to the same point we drop root in the original
namespace.  Extend the drop_user() function to isolate_user() which does
both.

After switching UID and GID in the original userns, isolate_user() will
either join or create the userns we require.  When we spawn a command with
pasta_start_ns()/pasta_setup_ns() we no longer need to create a userns,
because we're already made one.  sandbox() likewise no longer needs to
create (or join) an userns because we're already in the one we need.

We no longer need c->pasta_userns_fd, since the fd is only used locally
in isolate_user().  Likewise we can replace c->netns_only with a local
in conf(), since it's not used outside there.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c      | 11 ++++----
 isolation.c | 75 ++++++++++++++++++++++++++++++++++++++++++-----------
 isolation.h |  2 +-
 passt.c     |  3 ++-
 passt.h     |  4 ---
 pasta.c     | 56 +++++----------------------------------
 pasta.h     |  2 +-
 util.c      |  5 ----
 8 files changed, 77 insertions(+), 81 deletions(-)

diff --git a/conf.c b/conf.c
index 7171748..27d520e 100644
--- a/conf.c
+++ b/conf.c
@@ -1043,6 +1043,7 @@ static int conf_ugid(const char *runas, uid_t *uid, gid_t *gid)
  */
 void conf(struct ctx *c, int argc, char **argv)
 {
+	int netns_only = 0;
 	struct option options[] = {
 		{"debug",	no_argument,		NULL,		'd' },
 		{"quiet",	no_argument,		NULL,		'q' },
@@ -1077,7 +1078,7 @@ void conf(struct ctx *c, int argc, char **argv)
 		{"udp-ns",	required_argument,	NULL,		'U' },
 		{"userns",	required_argument,	NULL,		2 },
 		{"netns",	required_argument,	NULL,		3 },
-		{"netns-only",	no_argument,		&c->netns_only,	1 },
+		{"netns-only",	no_argument,		&netns_only,	1 },
 		{"config-net",	no_argument,		&c->pasta_conf_ns, 1 },
 		{"ns-mac-addr",	required_argument,	NULL,		4 },
 		{"dhcp-dns",	no_argument,		NULL,		5 },
@@ -1515,22 +1516,22 @@ void conf(struct ctx *c, int argc, char **argv)
 	if (ret)
 		usage(argv[0]);
 
-	drop_root(uid, gid);
-
 	if (c->mode == MODE_PASTA) {
-		if (conf_pasta_ns(&c->netns_only, userns, netns,
+		if (conf_pasta_ns(&netns_only, userns, netns,
 				  optind, argc, argv) < 0)
 			usage(argv[0]);
 	} else if (optind != argc) {
 		usage(argv[0]);
 	}
 
+	isolate_user(uid, gid, !netns_only, userns);
+
 	if (c->pasta_conf_ns)
 		c->no_ra = 1;
 
 	if (c->mode == MODE_PASTA) {
 		if (*netns) {
-			pasta_open_ns(c, userns, netns);
+			pasta_open_ns(c, netns);
 		} else {
 			pasta_start_ns(c, argc - optind, argv + optind);
 		}
diff --git a/isolation.c b/isolation.c
index bc8240f..f14b154 100644
--- a/isolation.c
+++ b/isolation.c
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <pwd.h>
 #include <sched.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -59,12 +60,19 @@ void drop_caps(void)
 }
 
 /**
- * drop_root() - Switch to given UID and GID
+ * isolate_user() - Switch to final UID/GID and move into userns
+ * @uid:	UID to run as (in original userns)
+ * @gid:	GID to run as (in original userns)
+ * @use_userns:	Whether to join or create a userns
+ * @userns:	userns path to enter, may be empty
  */
-void drop_root(uid_t uid, gid_t gid)
+void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns)
 {
+	char nsmap[BUFSIZ];
+
+	/* First set our UID & GID in the original namespace */
 	if (setgroups(0, NULL)) {
-		/* If we don't start with CAP_SETGID, this will EPERM */
+		/* If we don't have CAP_SETGID, this will EPERM */
 		if (errno != EPERM) {
 			err("Can't drop supplementary groups: %s",
 			    strerror(errno));
@@ -72,11 +80,57 @@ void drop_root(uid_t uid, gid_t gid)
 		}
 	}
 
-	if (!setgid(gid) && !setuid(uid))
+	if (setgid(gid) != 0) {
+		err("Can't set GID to %u: %s", gid, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	if (setuid(uid) != 0) {
+		err("Can't set UID to %u: %s", uid, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/* If we're told not to use a userns, nothing more to do */
+	if (!use_userns)
+		return;
+
+	/* Otherwise, if given a userns, join it */
+	if (*userns) {
+		int ufd;
+
+		ufd = open(userns, O_RDONLY | O_CLOEXEC);
+		if (ufd < 0) {
+			err("Couldn't open user namespace %s: %s",
+			    userns, strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+
+		if (setns(ufd, CLONE_NEWUSER) != 0) {
+			err("Couldn't enter user namespace %s: %s",
+			    userns, strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+
+		close(ufd);
+
 		return;
+	}
 
-	err("Can't change user/group, exiting");
-	exit(EXIT_FAILURE);
+	/* Otherwise, create our own userns */
+	if (unshare(CLONE_NEWUSER) != 0) {
+		err("Couldn't create user namespace: %s", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/* Configure user and group mappings */
+	snprintf(nsmap, BUFSIZ, "0 %u 1", uid);
+	FWRITE("/proc/self/uid_map", nsmap, "Cannot set uid_map in namespace");
+
+	FWRITE("/proc/self/setgroups", "deny",
+	       "Cannot write to setgroups in namespace");
+
+	snprintf(nsmap, BUFSIZ, "0 %u 1", gid);
+	FWRITE("/proc/self/gid_map", nsmap, "Cannot set gid_map in namespace");
 }
 
 /**
@@ -88,15 +142,6 @@ int sandbox(struct ctx *c)
 {
 	int flags = CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWUTS;
 
-	if (!c->netns_only) {
-		if (c->pasta_userns_fd == -1)
-			flags |= CLONE_NEWUSER;
-		else
-			setns(c->pasta_userns_fd, CLONE_NEWUSER);
-	}
-
-	c->pasta_userns_fd = -1;
-
 	/* If we run in foreground, we have no chance to actually move to a new
 	 * PID namespace. For passt, use CLONE_NEWPID anyway, in case somebody
 	 * ever gets around seccomp profiles -- there's no harm in passing it.
diff --git a/isolation.h b/isolation.h
index 2540a35..2c73df7 100644
--- a/isolation.h
+++ b/isolation.h
@@ -8,7 +8,7 @@
 #define ISOLATION_H
 
 void drop_caps(void);
-void drop_root(uid_t uid, gid_t gid);
+void isolate_user(uid_t uid, gid_t gid, bool use_userns, const char *userns);
 int sandbox(struct ctx *c);
 void seccomp(const struct ctx *c);
 
diff --git a/passt.c b/passt.c
index 2a8314c..f0ed897 100644
--- a/passt.c
+++ b/passt.c
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/resource.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <netdb.h>
@@ -185,7 +186,7 @@ int main(int argc, char **argv)
 
 	drop_caps();
 
-	c.pasta_userns_fd = c.pasta_netns_fd = c.fd_tap = c.fd_tap_listen = -1;
+	c.pasta_netns_fd = c.fd_tap = c.fd_tap_listen = -1;
 
 	sigemptyset(&sa.sa_mask);
 	sa.sa_flags = 0;
diff --git a/passt.h b/passt.h
index 3035430..8c8d710 100644
--- a/passt.h
+++ b/passt.h
@@ -145,8 +145,6 @@ struct ip6_ctx {
  * @pcap:		Path for packet capture file
  * @pid_file:		Path to PID file, empty string if not configured
  * @pasta_netns_fd:	File descriptor for network namespace in pasta mode
- * @pasta_userns_fd:	Descriptor for user namespace to join, -1 once joined
- * @netns_only:		In pasta mode, don't join or create a user namespace
  * @no_netns_quit:	In pasta mode, don't exit if fs-bound namespace is gone
  * @netns_base:		Base name for fs-bound namespace, if any, in pasta mode
  * @netns_dir:		Directory of fs-bound namespace, if any, in pasta mode
@@ -197,8 +195,6 @@ struct ctx {
 	char pid_file[PATH_MAX];
 
 	int pasta_netns_fd;
-	int pasta_userns_fd;
-	int netns_only;
 
 	int no_netns_quit;
 	char netns_base[PATH_MAX];
diff --git a/pasta.c b/pasta.c
index 7eac8e9..e233762 100644
--- a/pasta.c
+++ b/pasta.c
@@ -23,6 +23,7 @@
 #include <libgen.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <syslog.h>
@@ -83,16 +84,6 @@ static int pasta_wait_for_ns(void *arg)
 	int flags = O_RDONLY | O_CLOEXEC;
 	char ns[PATH_MAX];
 
-	if (c->netns_only)
-		goto netns;
-
-	snprintf(ns, PATH_MAX, "/proc/%i/ns/user", pasta_child_pid);
-	do
-		while ((c->pasta_userns_fd = open(ns, flags)) < 0);
-	while (setns(c->pasta_userns_fd, CLONE_NEWUSER) &&
-	       !close(c->pasta_userns_fd));
-
-netns:
 	snprintf(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid);
 	do
 		while ((c->pasta_netns_fd = open(ns, flags)) < 0);
@@ -112,25 +103,23 @@ static int ns_check(void *arg)
 {
 	struct ctx *c = (struct ctx *)arg;
 
-	if ((!c->netns_only && setns(c->pasta_userns_fd, CLONE_NEWUSER)) ||
-	    setns(c->pasta_netns_fd, CLONE_NEWNET))
-		c->pasta_userns_fd = c->pasta_netns_fd = -1;
+	if (setns(c->pasta_netns_fd, CLONE_NEWNET))
+		c->pasta_netns_fd = -1;
 
 	return 0;
 
 }
 
 /**
- * pasta_open_ns() - Open network, user namespaces descriptors
+ * pasta_open_ns() - Open network namespace descriptors
  * @c:		Execution context
- * @userns:	--userns argument, can be an empty string
  * @netns:	network namespace path
  *
  * Return: 0 on success, negative error code otherwise
  */
-void pasta_open_ns(struct ctx *c, const char *userns, const char *netns)
+void pasta_open_ns(struct ctx *c, const char *netns)
 {
-	int ufd = -1, nfd = -1;
+	int nfd = -1;
 
 	nfd = open(netns, O_RDONLY | O_CLOEXEC);
 	if (nfd < 0) {
@@ -138,17 +127,7 @@ void pasta_open_ns(struct ctx *c, const char *userns, const char *netns)
 		exit(EXIT_FAILURE);
 	}
 
-	if (!c->netns_only && *userns) {
-		ufd = open(userns, O_RDONLY | O_CLOEXEC);
-		if (ufd < 0) {
-			close(nfd);
-			err("Couldn't open user namespace %s", userns);
-			exit(EXIT_FAILURE);
-		}
-	}
-
 	c->pasta_netns_fd = nfd;
-	c->pasta_userns_fd = ufd;
 
 	NS_CALL(ns_check, c);
 
@@ -169,12 +148,9 @@ void pasta_open_ns(struct ctx *c, const char *userns, const char *netns)
 
 /**
  * struct pasta_setup_ns_arg - Argument for pasta_setup_ns()
- * @c:		Execution context
- * @euid:	Effective UID of caller
+ * @argv:	Command and arguments to run
  */
 struct pasta_setup_ns_arg {
-	struct ctx *c;
-	int euid;
 	char **argv;
 };
 
@@ -188,21 +164,6 @@ static int pasta_setup_ns(void *arg)
 {
 	struct pasta_setup_ns_arg *a = (struct pasta_setup_ns_arg *)arg;
 
-	if (!a->c->netns_only) {
-		char buf[BUFSIZ];
-
-		snprintf(buf, BUFSIZ, "%i %i %i", 0, a->euid, 1);
-
-		FWRITE("/proc/self/uid_map", buf,
-		       "Cannot set uid_map in namespace");
-
-		FWRITE("/proc/self/setgroups", "deny",
-		       "Cannot write to setgroups in namespace");
-
-		FWRITE("/proc/self/gid_map", buf,
-		       "Cannot set gid_map in namespace");
-	}
-
 	FWRITE("/proc/sys/net/ipv4/ping_group_range", "0 0",
 	       "Cannot set ping_group_range, ICMP requests might fail");
 
@@ -221,8 +182,6 @@ static int pasta_setup_ns(void *arg)
 void pasta_start_ns(struct ctx *c, int argc, char *argv[])
 {
 	struct pasta_setup_ns_arg arg = {
-		.c = c,
-		.euid = geteuid(),
 		.argv = argv,
 	};
 	char *shell = getenv("SHELL") ? getenv("SHELL") : "/bin/sh";
@@ -244,7 +203,6 @@ void pasta_start_ns(struct ctx *c, int argc, char *argv[])
 
 	pasta_child_pid = clone(pasta_setup_ns,
 				ns_fn_stack + sizeof(ns_fn_stack) / 2,
-				(c->netns_only ? 0 : CLONE_NEWUSER) |
 				CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET |
 				CLONE_NEWUTS,
 				(void *)&arg);
diff --git a/pasta.h b/pasta.h
index a1937b2..02df1f6 100644
--- a/pasta.h
+++ b/pasta.h
@@ -6,7 +6,7 @@
 #ifndef PASTA_H
 #define PASTA_H
 
-void pasta_open_ns(struct ctx *c, const char *userns, const char *netns);
+void pasta_open_ns(struct ctx *c, const char *netns);
 void pasta_start_ns(struct ctx *c, int argc, char *argv[]);
 void pasta_ns_conf(struct ctx *c);
 void pasta_child_handler(int signal);
diff --git a/util.c b/util.c
index f709838..8d26561 100644
--- a/util.c
+++ b/util.c
@@ -464,11 +464,6 @@ void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
  */
 int ns_enter(const struct ctx *c)
 {
-	if (!c->netns_only &&
-	    c->pasta_userns_fd != -1 &&
-	    setns(c->pasta_userns_fd, CLONE_NEWUSER))
-		exit(EXIT_FAILURE);
-
 	if (setns(c->pasta_netns_fd, CLONE_NEWNET))
 		exit(EXIT_FAILURE);
 
-- 
@@ -464,11 +464,6 @@ void procfs_scan_listen(struct ctx *c, uint8_t proto, int ip_version, int ns,
  */
 int ns_enter(const struct ctx *c)
 {
-	if (!c->netns_only &&
-	    c->pasta_userns_fd != -1 &&
-	    setns(c->pasta_userns_fd, CLONE_NEWUSER))
-		exit(EXIT_FAILURE);
-
 	if (setns(c->pasta_netns_fd, CLONE_NEWNET))
 		exit(EXIT_FAILURE);
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 21/32] Allow --userns when pasta spawns a command
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (19 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 20/32] Handle userns isolation and dropping root at the same time David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 22/32] test: Group tests by context then protocol, rather than the reverse David Gibson
                   ` (10 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 929 bytes --]

Currently --userns is only allowed when pasta is attaching to an existing
netns or PID, and is prohibited when creating a new netns by spawning a
command or shell.

With the new handling of userns, this check isn't neccessary.  I'm not sure
if there's any use case for --userns with a spawned command, but it's
strictly more flexible and requires zero extra code, so we might as well.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 conf.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/conf.c b/conf.c
index 27d520e..ec191c2 100644
--- a/conf.c
+++ b/conf.c
@@ -561,11 +561,6 @@ static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
 		}
 	}
 
-	if (*userns && !*netns) {
-		err("--userns requires --netns or PID");
-		return -EINVAL;
-	}
-
 	/* Attaching to a netns/PID, with no userns given */
 	if (*netns && !*userns)
 		*netns_only = 1;
-- 
@@ -561,11 +561,6 @@ static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
 		}
 	}
 
-	if (*userns && !*netns) {
-		err("--userns requires --netns or PID");
-		return -EINVAL;
-	}
-
 	/* Attaching to a netns/PID, with no userns given */
 	if (*netns && !*userns)
 		*netns_only = 1;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 22/32] test: Group tests by context then protocol, rather than the reverse
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (20 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 21/32] Allow --userns when pasta spawns a command David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 23/32] test: Remove unused variable FFMPEG_PID_FILE David Gibson
                   ` (9 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 10144 bytes --]

e.g. passt/dhcp rather than dhcp/passt.  This is more consistent with the
two_guests and other test groups, and makes some other cleanups simpler.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/{dhcp/passt => passt/dhcp}               |  2 +-
 test/{ndp/passt => passt/ndp}                 |  2 +-
 test/{shutdown/passt => passt/shutdown}       |  2 +-
 test/{tcp/passt => passt/tcp}                 |  2 +-
 test/{udp/passt => passt/udp}                 |  2 +-
 test/{icmp/passt_in_ns => passt_in_ns/icmp}   |  2 +-
 .../passt_in_ns => passt_in_ns/shutdown}      |  2 +-
 test/{tcp/passt_in_ns => passt_in_ns/tcp}     |  2 +-
 test/{udp/passt_in_ns => passt_in_ns/udp}     |  2 +-
 test/{dhcp/pasta => pasta/dhcp}               |  2 +-
 test/{ndp/pasta => pasta/ndp}                 |  2 +-
 test/{tcp/pasta => pasta/tcp}                 |  2 +-
 test/{udp/pasta => pasta/udp}                 |  2 +-
 test/run                                      | 38 +++++++++----------
 14 files changed, 32 insertions(+), 32 deletions(-)
 rename test/{dhcp/passt => passt/dhcp} (98%)
 rename test/{ndp/passt => passt/ndp} (95%)
 rename test/{shutdown/passt => passt/shutdown} (87%)
 rename test/{tcp/passt => passt/tcp} (98%)
 rename test/{udp/passt => passt/udp} (97%)
 rename test/{icmp/passt_in_ns => passt_in_ns/icmp} (94%)
 rename test/{shutdown/passt_in_ns => passt_in_ns/shutdown} (87%)
 rename test/{tcp/passt_in_ns => passt_in_ns/tcp} (99%)
 rename test/{udp/passt_in_ns => passt_in_ns/udp} (98%)
 rename test/{dhcp/pasta => pasta/dhcp} (96%)
 rename test/{ndp/pasta => pasta/ndp} (95%)
 rename test/{tcp/pasta => pasta/tcp} (98%)
 rename test/{udp/pasta => pasta/udp} (98%)

diff --git a/test/dhcp/passt b/test/passt/dhcp
similarity index 98%
rename from test/dhcp/passt
rename to test/passt/dhcp
index 37bf6b5..eef5183 100644
--- a/test/dhcp/passt
+++ b/test/passt/dhcp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/dhcp/passt - Check DHCP and DHCPv6 functionality in passt mode
+# test/passt/dhcp - Check DHCP and DHCPv6 functionality in passt mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/ndp/passt b/test/passt/ndp
similarity index 95%
rename from test/ndp/passt
rename to test/passt/ndp
index c73fd4d..280b3ae 100644
--- a/test/ndp/passt
+++ b/test/passt/ndp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/ndp/passt - Check NDP functionality in passt mode
+# test/passt/ndp - Check NDP functionality in passt mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/shutdown/passt b/test/passt/shutdown
similarity index 87%
rename from test/shutdown/passt
rename to test/passt/shutdown
index ac8ff08..ce90ea9 100644
--- a/test/shutdown/passt
+++ b/test/passt/shutdown
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/shutdown/passt - Shut down passt (or pasta) and check exit code (will
+# test/passt/shutdown - Shut down passt (or pasta) and check exit code (will
 #                       detect valgrind errors amongst others)
 #
 # Copyright (c) 2022 Red Hat GmbH
diff --git a/test/tcp/passt b/test/passt/tcp
similarity index 98%
rename from test/tcp/passt
rename to test/passt/tcp
index 265f270..d5c8164 100644
--- a/test/tcp/passt
+++ b/test/passt/tcp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/tcp/passt - Check TCP functionality in passt mode
+# test/passt/tcp - Check TCP functionality in passt mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/udp/passt b/test/passt/udp
similarity index 97%
rename from test/udp/passt
rename to test/passt/udp
index a14e6d2..56d01b3 100644
--- a/test/udp/passt
+++ b/test/passt/udp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/udp/passt - Check UDP functionality in passt mode
+# test/passt/udp - Check UDP functionality in passt mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/icmp/passt_in_ns b/test/passt_in_ns/icmp
similarity index 94%
rename from test/icmp/passt_in_ns
rename to test/passt_in_ns/icmp
index e4ac4ff..f326d4b 100644
--- a/test/icmp/passt_in_ns
+++ b/test/passt_in_ns/icmp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/icmp/passt_in_ns - Check ICMP/ICMPv6 functionality for passt in ns
+# test/passt_in_ns/icmp - Check ICMP/ICMPv6 functionality for passt in ns
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/shutdown/passt_in_ns b/test/passt_in_ns/shutdown
similarity index 87%
rename from test/shutdown/passt_in_ns
rename to test/passt_in_ns/shutdown
index 3808adb..abe9d6c 100644
--- a/test/shutdown/passt_in_ns
+++ b/test/passt_in_ns/shutdown
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/shutdown/passt_in_ns - Shut down passt and check exit code (will detect
+# test/passt_in_ns/shutdown - Shut down passt and check exit code (will detect
 #                             valgrind errors amongst others)
 #
 # Copyright (c) 2022 Red Hat GmbH
diff --git a/test/tcp/passt_in_ns b/test/passt_in_ns/tcp
similarity index 99%
rename from test/tcp/passt_in_ns
rename to test/passt_in_ns/tcp
index a248f00..5ec95e8 100644
--- a/test/tcp/passt_in_ns
+++ b/test/passt_in_ns/tcp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/tcp/passt_in_ns - Check TCP functionality for passt in ns with pasta
+# test/passt_in_ns/tcp - Check TCP functionality for passt in ns with pasta
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/udp/passt_in_ns b/test/passt_in_ns/udp
similarity index 98%
rename from test/udp/passt_in_ns
rename to test/passt_in_ns/udp
index d5f08fe..c22a68f 100644
--- a/test/udp/passt_in_ns
+++ b/test/passt_in_ns/udp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/udp/passt_in_ns - Check UDP functionality for passt in ns and pasta
+# test/passt_in_ns/udp - Check UDP functionality for passt in ns and pasta
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/dhcp/pasta b/test/pasta/dhcp
similarity index 96%
rename from test/dhcp/pasta
rename to test/pasta/dhcp
index d1e9611..80eabf5 100644
--- a/test/dhcp/pasta
+++ b/test/pasta/dhcp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/dhcp/pasta - Check DHCP and DHCPv6 functionality in pasta mode
+# test/pasta/dhcp - Check DHCP and DHCPv6 functionality in pasta mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/ndp/pasta b/test/pasta/ndp
similarity index 95%
rename from test/ndp/pasta
rename to test/pasta/ndp
index d776055..d2b2c0b 100644
--- a/test/ndp/pasta
+++ b/test/pasta/ndp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/ndp/pasta - Check DHCP and DHCPv6 functionality in pasta mode
+# test/pasta/ndp - Check DHCP and DHCPv6 functionality in pasta mode
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/tcp/pasta b/test/pasta/tcp
similarity index 98%
rename from test/tcp/pasta
rename to test/pasta/tcp
index a13a2ff..7c7de06 100644
--- a/test/tcp/pasta
+++ b/test/pasta/tcp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/tcp/pasta - Check TCP functionality for pasta
+# test/pasta/tcp - Check TCP functionality for pasta
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/udp/pasta b/test/pasta/udp
similarity index 98%
rename from test/udp/pasta
rename to test/pasta/udp
index 0767e0b..0e58152 100644
--- a/test/udp/pasta
+++ b/test/pasta/udp
@@ -6,7 +6,7 @@
 # PASTA - Pack A Subtle Tap Abstraction
 #  for network namespace/tap device mode
 #
-# test/udp/pasta - Check UDP functionality for pasta
+# test/pasta/udp - Check UDP functionality for pasta
 #
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
diff --git a/test/run b/test/run
index 0ec1334..d8b60bf 100755
--- a/test/run
+++ b/test/run
@@ -74,40 +74,40 @@ run() {
 	teardown distro
 
 	setup pasta
-	test ndp/pasta
-	test dhcp/pasta
-	test tcp/pasta
-	test udp/pasta
-	test shutdown/passt
+	test pasta/ndp
+	test pasta/dhcp
+	test pasta/tcp
+	test pasta/udp
+	test passt/shutdown
 	teardown pasta
 
 	setup passt
-	test ndp/passt
-	test dhcp/passt
-	test tcp/passt
-	test udp/passt
-	test shutdown/passt
+	test passt/ndp
+	test passt/dhcp
+	test passt/tcp
+	test passt/udp
+	test passt/shutdown
 	teardown passt
 
 	VALGRIND=1
 	setup passt_in_ns
-	test ndp/passt
-	test dhcp/passt
-	test icmp/passt_in_ns
-	test tcp/passt_in_ns
-	test udp/passt_in_ns
-	test shutdown/passt_in_ns
+	test passt/ndp
+	test passt/dhcp
+	test passt_in_ns/icmp
+	test passt_in_ns/tcp
+	test passt_in_ns/udp
+	test passt_in_ns/shutdown
 	teardown passt_in_ns
 
 	VALGRIND=0
 	setup passt_in_ns
-	test ndp/passt
-	test dhcp/passt
+	test passt/ndp
+	test passt/dhcp
 	test perf/passt_tcp
 	test perf/passt_udp
 	test perf/pasta_tcp
 	test perf/pasta_udp
-	test shutdown/passt_in_ns
+	test passt_in_ns/shutdown
 	teardown passt_in_ns
 
 	setup two_guests
-- 
@@ -74,40 +74,40 @@ run() {
 	teardown distro
 
 	setup pasta
-	test ndp/pasta
-	test dhcp/pasta
-	test tcp/pasta
-	test udp/pasta
-	test shutdown/passt
+	test pasta/ndp
+	test pasta/dhcp
+	test pasta/tcp
+	test pasta/udp
+	test passt/shutdown
 	teardown pasta
 
 	setup passt
-	test ndp/passt
-	test dhcp/passt
-	test tcp/passt
-	test udp/passt
-	test shutdown/passt
+	test passt/ndp
+	test passt/dhcp
+	test passt/tcp
+	test passt/udp
+	test passt/shutdown
 	teardown passt
 
 	VALGRIND=1
 	setup passt_in_ns
-	test ndp/passt
-	test dhcp/passt
-	test icmp/passt_in_ns
-	test tcp/passt_in_ns
-	test udp/passt_in_ns
-	test shutdown/passt_in_ns
+	test passt/ndp
+	test passt/dhcp
+	test passt_in_ns/icmp
+	test passt_in_ns/tcp
+	test passt_in_ns/udp
+	test passt_in_ns/shutdown
 	teardown passt_in_ns
 
 	VALGRIND=0
 	setup passt_in_ns
-	test ndp/passt
-	test dhcp/passt
+	test passt/ndp
+	test passt/dhcp
 	test perf/passt_tcp
 	test perf/passt_udp
 	test perf/pasta_tcp
 	test perf/pasta_udp
-	test shutdown/passt_in_ns
+	test passt_in_ns/shutdown
 	teardown passt_in_ns
 
 	setup two_guests
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 23/32] test: Remove unused variable FFMPEG_PID_FILE
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (21 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 22/32] test: Group tests by context then protocol, rather than the reverse David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 24/32] test: Actually run cleanup function David Gibson
                   ` (8 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 493 bytes --]

FFPMPEG_PID_FILE is set (creating a temporary file), then never used.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/video | 1 -
 1 file changed, 1 deletion(-)

diff --git a/test/lib/video b/test/lib/video
index 22e73bb..f609abf 100755
--- a/test/lib/video
+++ b/test/lib/video
@@ -13,7 +13,6 @@
 # Copyright (c) 2021-2022 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-FFMPEG_PID_FILE="$(mktemp)"
 VIDEO_START_SECONDS=
 VIDEO_NAME=
 
-- 
@@ -13,7 +13,6 @@
 # Copyright (c) 2021-2022 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-FFMPEG_PID_FILE="$(mktemp)"
 VIDEO_START_SECONDS=
 VIDEO_NAME=
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 24/32] test: Actually run cleanup function
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (22 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 23/32] test: Remove unused variable FFMPEG_PID_FILE David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 25/32] test: Create common state directories for temporary files David Gibson
                   ` (7 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

We install a cleanup() function with 'trap' in order to clean up temporary
files we generate during the tests.  However, we deinstall it after
run_term, which means it won't run in most of the cases where it would be
useful.  Even if "run from_term" exits with an error, that error will be
hidden from the run_term wrapper because it's within a tmux session, so we
will return from run_term normally, uninstall the trap and never clean up.

In fact there's no reason to uninstall the trap at all, it works just as
well on the success exit path as an error exit path.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/run | 1 -
 1 file changed, 1 deletion(-)

diff --git a/test/run b/test/run
index d8b60bf..9b0227b 100755
--- a/test/run
+++ b/test/run
@@ -178,7 +178,6 @@ else
 	:> "${LOGFILE}"
 	trap "cleanup" EXIT
 	run_term
-	trap "" EXIT
 fi
 
 [ ${DEMO} -eq 1 ] && exit 0
-- 
@@ -178,7 +178,6 @@ else
 	:> "${LOGFILE}"
 	trap "cleanup" EXIT
 	run_term
-	trap "" EXIT
 fi
 
 [ ${DEMO} -eq 1 ] && exit 0
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 25/32] test: Create common state directories for temporary files
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (23 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 24/32] test: Actually run cleanup function David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 26/32] test: Move context temporary files to state dir David Gibson
                   ` (6 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 2864 bytes --]

The test scripts create a bunch of temporary files to keep track of
internal state.  Some are made in /tmp with individual mktemp calls, some
go in the passt source directory, and some go in $LOGDIR.  This can
sometimes make it messy to clean up after failed test runs.

Start cleaning this up by creating a single "state" directory ($STATEBASE)
in /tmp for all the state or temporary files used by a single test run.
Clean it up automatically in cleanup() - except when DEBUG==1, because
those files can be useful for debugging test script failures.

We create subdirectories under $STATEBASE for each setup function, exposed
as $STATESETUP.  We also create subdirectories for each test script and
expose those to the scripts as __STATEDIR__.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/setup | 2 ++
 test/lib/term  | 2 +-
 test/lib/test  | 4 ++++
 test/run       | 2 ++
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/test/lib/setup b/test/lib/setup
index 957a9cc..b0420fb 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -394,6 +394,8 @@ teardown_demo_podman() {
 # $*:	Suffix list of setup_*() functions to be called
 setup() {
 	for arg do
+		STATESETUP="${STATEBASE}/${arg}"
+		mkdir -p "${STATESETUP}"
 		eval setup_${arg}
 	done
 }
diff --git a/test/lib/term b/test/lib/term
index ae99010..b2a45e4 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -639,7 +639,7 @@ pause_continue() {
 
 # run_term() - Start tmux session, running entry point, with recording if needed
 run_term() {
-	TMUX="tmux new-session -s passt_test -ePCAP=$PCAP -eDEBUG=$DEBUG"
+	TMUX="tmux new-session -s passt_test -eSTATEBASE=$STATEBASE -ePCAP=$PCAP -eDEBUG=$DEBUG"
 
 	if [ ${CI} -eq 1 ]; then
 		printf '\e[8;50;240t'
diff --git a/test/lib/test b/test/lib/test
index 0d06afd..3dbae0b 100755
--- a/test/lib/test
+++ b/test/lib/test
@@ -351,6 +351,10 @@ test_one() {
 	[ ${CI} -eq 1 ] && video_link "${1}"
 
 	TEST_ONE_subs="$(list_add_pair "" "__BASEPATH__" "${BASEPATH}")"
+	TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__STATESETUP__" "${STATESETUP}")"
+	STATEDIR="${STATEBASE}/${1}"
+	mkdir -p "${STATEDIR}"
+	TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__STATEDIR__" "${STATEDIR}")"
 	TEST_ONE_nok=-1
 	TEST_ONE_perf_nok=0
 	TEST_ONE_skip=0
diff --git a/test/run b/test/run
index 9b0227b..58d9b49 100755
--- a/test/run
+++ b/test/run
@@ -48,6 +48,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
 
 # cleanup() - Remove temporary files
 cleanup() {
+	[ ${DEBUG} -eq 1 ] || rm -rf "${STATEBASE}"
 	rm -f /tmp/.passt_test_log_pipe
 }
 
@@ -176,6 +177,7 @@ else
 	rm -rf "${LOGDIR}"
 	mkdir -p "${LOGDIR}"
 	:> "${LOGFILE}"
+	STATEBASE="$(mktemp -d --tmpdir passt-tests-XXXXXX)"
 	trap "cleanup" EXIT
 	run_term
 fi
-- 
@@ -48,6 +48,7 @@ COMMIT="$(git log --oneline --no-decorate -1)"
 
 # cleanup() - Remove temporary files
 cleanup() {
+	[ ${DEBUG} -eq 1 ] || rm -rf "${STATEBASE}"
 	rm -f /tmp/.passt_test_log_pipe
 }
 
@@ -176,6 +177,7 @@ else
 	rm -rf "${LOGDIR}"
 	mkdir -p "${LOGDIR}"
 	:> "${LOGFILE}"
+	STATEBASE="$(mktemp -d --tmpdir passt-tests-XXXXXX)"
 	trap "cleanup" EXIT
 	run_term
 fi
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 26/32] test: Move context temporary files to state dir
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (24 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 25/32] test: Create common state directories for temporary files David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 27/32] test: Dont regnerate small test file in pasta/tcp David Gibson
                   ` (5 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 5045 bytes --]

Currently the context command dispatch subsystem creates a bunch of
temporary files in $LOGDIR, which is messy.  Store them in $STATEDIR which
is for precisely this purpose.  The logs from each context still go into
$LOGDIR.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/context | 61 +++++++++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 29 deletions(-)

diff --git a/test/lib/context b/test/lib/context
index ccb0004..5448e20 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -17,17 +17,17 @@
 # $1:	Context name
 context_setup_common() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	echo -n "${__name}$ " > "${__prefix}.log"
+	__log="${LOGDIR}/context_${__name}.log"
+	echo -n "${__name}$ " > "${__log}"
 }
 
 # context_setup_host() - Create a new context for running commands on the host
 # $1:	Context name
 context_setup_host() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
 	context_setup_common "${__name}"
-	echo sh -c > "${__prefix}.enter"
+	echo sh -c > "${__enter}"
 }
 
 # context_setup_nsenter() - Create a new context for running commands in a namespace
@@ -36,9 +36,9 @@ context_setup_host() {
 context_setup_nsenter() {
 	__name="$1"
 	shift
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
 	context_setup_common "${__name}"
-	echo "nsenter $@ sh -c" > "${__prefix}.enter"
+	echo "nsenter $@ sh -c" > "${__enter}"
 }
 
 # context_setup_guest() - Create a new context for running commands in a guest
@@ -47,22 +47,23 @@ context_setup_nsenter() {
 context_setup_guest() {
 	__name="$1"
 	__cid="$2"
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
+	__ssh="${STATESETUP}/context_${__name}.ssh"
 	context_setup_common "${__name}"
 
-	cat > "${__prefix}.ssh" <<EOF
+	cat > "${__ssh}" <<EOF
 Host ${__name}
 	User root
-	UserKnownHostsFile ${__prefix}.hosts
+	UserKnownHostsFile ${STATESETUP}/context_{__name}.hosts
 	StrictHostKeyChecking no
 	IdentityFile ${BASEPATH}/guest-key
 	IdentityAgent none
 	ProxyCommand socat - VSOCK-CONNECT:${__cid}:22
 EOF
-	echo "ssh -F ${__prefix}.ssh ${__name}" > "${__prefix}.enter"
+	echo "ssh -F ${__ssh} ${__name}" > "${__enter}"
 
 	# Wait for the guest to be booted and accepting connections
-	while ! ssh -F "${__prefix}.ssh" "${__name}" :; do
+	while ! ssh -F "${__ssh}" "${__name}" :; do
 		sleep 0.1
 	done
 }
@@ -71,7 +72,7 @@ EOF
 # $1:	Context name
 context_teardown() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__prefix="${STATESETUP}/context_${__name}"
 	rm -f "${__prefix}.enter" "${__prefix}.ssh" "${__prefix}.hosts"
 }
 
@@ -79,8 +80,8 @@ context_teardown() {
 # $1:	Context name
 context_exists() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	[ -f "${__prefix}.enter" ]
+	__enter="${STATESETUP}/context_${__name}.enter"
+	[ -f "${__enter}" ]
 }
 
 # context_run() - Run a shell command in a context, and wait for it to finish
@@ -88,18 +89,20 @@ context_exists() {
 # $*:	Command to start
 context_run() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	__enter="$(cat "${__prefix}.enter")"
+	__log="${LOGDIR}/context_${__name}.log"
+	__enter="${STATESETUP}/context_${__name}.enter"
+	__stdout="${STATESETUP}/context_${__name}.stdout"
+	__stderr="${STATESETUP}/context_${__name}.stderr"
 	shift
-	echo "$*" >> "${__prefix}.log"
-	mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
-	tee -a "${__prefix}.log" < "${__prefix}.stdout" &
-	tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
-	${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+	echo "$*" >> "${__log}"
+	mkfifo "${__stdout}" "${__stderr}"
+	tee -a "${__log}" < "${__stdout}" &
+	tee -a "${__log}" < "${__stderr}" >&2 &
+	$(cat ${__enter}) "$*" >> "${__stdout}" 2>> "${__stderr}"
 	rc=$?
-	rm "${__prefix}.stdout" "${__prefix}.stderr"
-	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
-	echo -n "${__name}$ " >> "${__prefix}.log"
+	rm "${__stdout}" "${__stderr}"
+	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__log}"
+	echo -n "${__name}$ " >> "${__log}"
 	return $rc
 }
 
@@ -108,9 +111,9 @@ context_run() {
 # $*:	Command to start
 context_run_bg() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__pidfile="${STATESETUP}/context_${__name}.pid"
 	context_run "$@" &
-	echo $! > "${__prefix}.pid"
+	echo $! > "${__pidfile}"
 }
 
 # context_wait() - Wait for background command in a context to complete
@@ -118,8 +121,8 @@ context_run_bg() {
 # Returns the status of the completed command
 context_wait() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	__pid=$(cat "${__prefix}.pid")
-	rm "${__prefix}.pid"
+	__pidfile="${STATESETUP}/context_${__name}.pid"
+	__pid=$(cat "${__pidfile}")
+	rm "${__pidfile}"
 	wait ${__pid}
 }
-- 
@@ -17,17 +17,17 @@
 # $1:	Context name
 context_setup_common() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	echo -n "${__name}$ " > "${__prefix}.log"
+	__log="${LOGDIR}/context_${__name}.log"
+	echo -n "${__name}$ " > "${__log}"
 }
 
 # context_setup_host() - Create a new context for running commands on the host
 # $1:	Context name
 context_setup_host() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
 	context_setup_common "${__name}"
-	echo sh -c > "${__prefix}.enter"
+	echo sh -c > "${__enter}"
 }
 
 # context_setup_nsenter() - Create a new context for running commands in a namespace
@@ -36,9 +36,9 @@ context_setup_host() {
 context_setup_nsenter() {
 	__name="$1"
 	shift
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
 	context_setup_common "${__name}"
-	echo "nsenter $@ sh -c" > "${__prefix}.enter"
+	echo "nsenter $@ sh -c" > "${__enter}"
 }
 
 # context_setup_guest() - Create a new context for running commands in a guest
@@ -47,22 +47,23 @@ context_setup_nsenter() {
 context_setup_guest() {
 	__name="$1"
 	__cid="$2"
-	__prefix="${LOGDIR}/context_${__name}"
+	__enter="${STATESETUP}/context_${__name}.enter"
+	__ssh="${STATESETUP}/context_${__name}.ssh"
 	context_setup_common "${__name}"
 
-	cat > "${__prefix}.ssh" <<EOF
+	cat > "${__ssh}" <<EOF
 Host ${__name}
 	User root
-	UserKnownHostsFile ${__prefix}.hosts
+	UserKnownHostsFile ${STATESETUP}/context_{__name}.hosts
 	StrictHostKeyChecking no
 	IdentityFile ${BASEPATH}/guest-key
 	IdentityAgent none
 	ProxyCommand socat - VSOCK-CONNECT:${__cid}:22
 EOF
-	echo "ssh -F ${__prefix}.ssh ${__name}" > "${__prefix}.enter"
+	echo "ssh -F ${__ssh} ${__name}" > "${__enter}"
 
 	# Wait for the guest to be booted and accepting connections
-	while ! ssh -F "${__prefix}.ssh" "${__name}" :; do
+	while ! ssh -F "${__ssh}" "${__name}" :; do
 		sleep 0.1
 	done
 }
@@ -71,7 +72,7 @@ EOF
 # $1:	Context name
 context_teardown() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__prefix="${STATESETUP}/context_${__name}"
 	rm -f "${__prefix}.enter" "${__prefix}.ssh" "${__prefix}.hosts"
 }
 
@@ -79,8 +80,8 @@ context_teardown() {
 # $1:	Context name
 context_exists() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	[ -f "${__prefix}.enter" ]
+	__enter="${STATESETUP}/context_${__name}.enter"
+	[ -f "${__enter}" ]
 }
 
 # context_run() - Run a shell command in a context, and wait for it to finish
@@ -88,18 +89,20 @@ context_exists() {
 # $*:	Command to start
 context_run() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	__enter="$(cat "${__prefix}.enter")"
+	__log="${LOGDIR}/context_${__name}.log"
+	__enter="${STATESETUP}/context_${__name}.enter"
+	__stdout="${STATESETUP}/context_${__name}.stdout"
+	__stderr="${STATESETUP}/context_${__name}.stderr"
 	shift
-	echo "$*" >> "${__prefix}.log"
-	mkfifo "${__prefix}.stdout" "${__prefix}.stderr"
-	tee -a "${__prefix}.log" < "${__prefix}.stdout" &
-	tee -a "${__prefix}.log" < "${__prefix}.stderr" >&2 &
-	${__enter} "$*" >> "${__prefix}.stdout" 2>> "${__prefix}.stderr"
+	echo "$*" >> "${__log}"
+	mkfifo "${__stdout}" "${__stderr}"
+	tee -a "${__log}" < "${__stdout}" &
+	tee -a "${__log}" < "${__stderr}" >&2 &
+	$(cat ${__enter}) "$*" >> "${__stdout}" 2>> "${__stderr}"
 	rc=$?
-	rm "${__prefix}.stdout" "${__prefix}.stderr"
-	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__prefix}.log"
-	echo -n "${__name}$ " >> "${__prefix}.log"
+	rm "${__stdout}" "${__stderr}"
+	[ ${DEBUG} -eq 1 ] && echo "[Exit code: $rc]" >> "${__log}"
+	echo -n "${__name}$ " >> "${__log}"
 	return $rc
 }
 
@@ -108,9 +111,9 @@ context_run() {
 # $*:	Command to start
 context_run_bg() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
+	__pidfile="${STATESETUP}/context_${__name}.pid"
 	context_run "$@" &
-	echo $! > "${__prefix}.pid"
+	echo $! > "${__pidfile}"
 }
 
 # context_wait() - Wait for background command in a context to complete
@@ -118,8 +121,8 @@ context_run_bg() {
 # Returns the status of the completed command
 context_wait() {
 	__name="$1"
-	__prefix="${LOGDIR}/context_${__name}"
-	__pid=$(cat "${__prefix}.pid")
-	rm "${__prefix}.pid"
+	__pidfile="${STATESETUP}/context_${__name}.pid"
+	__pid=$(cat "${__pidfile}")
+	rm "${__pidfile}"
 	wait ${__pid}
 }
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 27/32] test: Dont regnerate small test file in pasta/tcp
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (25 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 26/32] test: Move context temporary files to state dir David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 28/32] test: Use paths in __STATEDIR__ instead of 'temp' and 'tempdir' directives David Gibson
                   ` (4 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 785 bytes --]

In what looks like a copy/paste error, pasta/tcp generates its small test
file twice.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/pasta/tcp | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/test/pasta/tcp b/test/pasta/tcp
index 7c7de06..5497f11 100644
--- a/test/pasta/tcp
+++ b/test/pasta/tcp
@@ -91,10 +91,7 @@ hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv6: host to ns: small transfer
-temp	TEMP_SMALL
-temp	TEMP_NS_SMALL
 nsb	socat -u TCP6-LISTEN:10002,bind=[::1] OPEN:__TEMP_NS_SMALL__,create,trunc
-host	dd if=/dev/urandom bs=2k count=1 of=__TEMP_SMALL__
 host	socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10002
 nsw
 hout	MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
-- 
@@ -91,10 +91,7 @@ hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv6: host to ns: small transfer
-temp	TEMP_SMALL
-temp	TEMP_NS_SMALL
 nsb	socat -u TCP6-LISTEN:10002,bind=[::1] OPEN:__TEMP_NS_SMALL__,create,trunc
-host	dd if=/dev/urandom bs=2k count=1 of=__TEMP_SMALL__
 host	socat -u OPEN:__TEMP_SMALL__ TCP6:[::1]:10002
 nsw
 hout	MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 28/32] test: Use paths in __STATEDIR__ instead of 'temp' and 'tempdir' directives
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (26 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 27/32] test: Dont regnerate small test file in pasta/tcp David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 29/32] test: Move pause temporary file to state directory David Gibson
                   ` (3 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 21185 bytes --]

Instead of using the 'temp' and 'tempdir' DSL directives to create
temporary files, use fixed paths relative to __STATEDIR__.  This has two
advantages:
  1) The files are automatically cleaned up if the tests fail (and even if
     that doesn't work they're easier to clean up manuall)
  2) When debugging tests it's easier to figure out which of the temporary
     files are relevant to whatever's going wrong

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/build/all       | 31 +++++++++++++++----------------
 test/demo/passt      |  9 ++++-----
 test/demo/pasta      | 12 +++++-------
 test/demo/podman     | 11 +++++------
 test/distro/debian   |  2 +-
 test/distro/fedora   |  2 +-
 test/distro/opensuse | 16 +++++++++-------
 test/distro/ubuntu   |  8 ++++----
 test/lib/test        | 10 ----------
 test/passt/tcp       |  4 ++--
 test/passt/udp       |  6 +++---
 test/passt_in_ns/tcp |  8 ++++----
 test/passt_in_ns/udp |  6 +++---
 test/pasta/tcp       |  8 ++++----
 test/pasta/udp       | 18 +++++++++---------
 15 files changed, 69 insertions(+), 82 deletions(-)

diff --git a/test/build/all b/test/build/all
index 1a89b77..bacb1d1 100644
--- a/test/build/all
+++ b/test/build/all
@@ -41,22 +41,21 @@ check	[ -f passt ]
 check	[ -h pasta ]
 check	[ -f qrap ]
 
-tempdir	TEMP
-
 test	Install
-host	prefix=__TEMP__ make install
-check	[ -f __TEMP__/bin/passt ]
-check	[ -h __TEMP__/bin/pasta ]
-check	[ -f __TEMP__/bin/qrap ]
-check	man -M __TEMP__/share/man -W passt
-check	man -M __TEMP__/share/man -W pasta
-check	man -M __TEMP__/share/man -W qrap
+host	mkdir __STATEDIR__/prefix
+host	prefix=__STATEDIR__/prefix make install
+check	[ -f __STATEDIR__/prefix/bin/passt ]
+check	[ -h __STATEDIR__/prefix/bin/pasta ]
+check	[ -f __STATEDIR__/prefix/bin/qrap ]
+check	man -M __STATEDIR__/prefix/share/man -W passt
+check	man -M __STATEDIR__/prefix/share/man -W pasta
+check	man -M __STATEDIR__/prefix/share/man -W qrap
 
 test	Uninstall
-host	prefix=__TEMP__ make uninstall
-check	! [ -f __TEMP__/bin/passt ]
-check	! [ -h __TEMP__/bin/pasta ]
-check	! [ -f __TEMP__/bin/qrap ]
-check	! man -M __TEMP__/share/man -W passt 2>/dev/null
-check	! man -M __TEMP__/share/man -W pasta 2>/dev/null
-check	! man -M __TEMP__/share/man -W qrap 2>/dev/null
+host	prefix=__STATEDIR__/prefix make uninstall
+check	! [ -f __STATEDIR__/prefix/bin/passt ]
+check	! [ -h __STATEDIR__/prefix/bin/pasta ]
+check	! [ -f __STATEDIR__/prefix/bin/qrap ]
+check	! man -M __STATEDIR__/prefix/share/man -W passt 2>/dev/null
+check	! man -M __STATEDIR__/prefix/share/man -W pasta 2>/dev/null
+check	! man -M __STATEDIR__/prefix/share/man -W qrap 2>/dev/null
diff --git a/test/demo/passt b/test/demo/passt
index 673afd9..dd6a119 100644
--- a/test/demo/passt
+++ b/test/demo/passt
@@ -20,8 +20,7 @@ sleep	3
 
 say	Let's fetch the source
 sleep	1
-tempdir	TEMPDIR
-host	cd __TEMPDIR__
+host	cd __STATEDIR__
 host	git clone git://passt.top/passt
 sleep	1
 
@@ -52,10 +51,10 @@ host	q
 nl
 nl
 say	Let's create a small initramfs image for the guest.
-guest	cd __TEMPDIR__
+guest	cd __STATEDIR__
 guest	git clone git://mbuto.sh/mbuto
 guest	cd mbuto
-guest	./mbuto -f passt.img -p __TEMPDIR__/passt/test/passt.mbuto -c lz4
+guest	./mbuto -f passt.img -p __STATEDIR__/passt/test/passt.mbuto -c lz4
 sleep	2
 
 nl
@@ -69,7 +68,7 @@ nl
 say	  'pasta' demo above.
 sleep	3
 
-passt	cd __TEMPDIR__/passt
+passt	cd __STATEDIR__/passt
 passtb	./pasta -P /tmp/pasta.pid
 sleep	3
 passt	/sbin/dhclient -4 --no-pid
diff --git a/test/demo/pasta b/test/demo/pasta
index 393149e..22479f8 100644
--- a/test/demo/pasta
+++ b/test/demo/pasta
@@ -20,8 +20,7 @@ sleep	3
 
 say	Let's fetch the source
 sleep	1
-tempdir	TEMPDIR
-host	cd __TEMPDIR__
+host	cd __STATEDIR__
 host	git clone git://passt.top/passt
 sleep	1
 
@@ -47,7 +46,7 @@ sleep	10
 nl
 say	  without PID, it will create a namespace.
 sleep	3
-passt	cd __TEMPDIR__/passt
+passt	cd __STATEDIR__/passt
 passtb	./pasta -P /tmp/pasta.pid
 sleep	3
 
@@ -140,13 +139,12 @@ say	 can also take packet captures.
 sleep	3
 passt	exit
 sleep	2
-temp	TEMP
-passtb	./pasta -p __TEMP__.pcap
+passtb	./pasta -p __STATEDIR__/demo_pasta.pcap
 sleep	2
 passt	
 passt	/sbin/dhclient -4 --no-pid
 sleep	2
-hostb	tshark -r __TEMP__.pcap
+hostb	tshark -r __STATEDIR__/demo_pasta.pcap
 sleep	5
 
 nl
@@ -257,7 +255,7 @@ sleep	2
 killp	PASST
 killp	HOST
 sleep	2
-ns	cd __TEMPDIR__/passt
+ns	cd __STATEDIR__/passt
 nsb	perf report -g --max-stack 3
 sleep	10
 
diff --git a/test/demo/podman b/test/demo/podman
index f3411d8..a83a04f 100644
--- a/test/demo/podman
+++ b/test/demo/podman
@@ -24,14 +24,13 @@ sleep	3
 
 say	Let's fetch Podman
 sleep	1
-tempdir	TEMPDIR
-host	git -C __TEMPDIR__ clone https://github.com/containers/podman.git
+host	git -C __STATEDIR__ clone https://github.com/containers/podman.git
 sleep	1
 
 say	, patch it
 sleep	1
-host	cp ../contrib/podman/0001-libpod-Add-pasta-networking-mode.patch __TEMPDIR__/podman
-host	cd __TEMPDIR__/podman
+host	cp ../contrib/podman/0001-libpod-Add-pasta-networking-mode.patch __STATEDIR__/podman
+host	cd __STATEDIR__/podman
 host	git am -3 0001-libpod-Add-pasta-networking-mode.patch
 sleep	1
 
@@ -54,7 +53,7 @@ nl
 say	Let's start a container with it
 sleep	1
 
-ns1	cd __TEMPDIR__/podman
+ns1	cd __STATEDIR__/podman
 ns1b	./bin/podman run --rm -ti alpine sh
 sleep	2
 
@@ -64,7 +63,7 @@ say	and one with
 em	pasta
 say	 instead.
 
-ns2	cd __TEMPDIR__/podman
+ns2	cd __STATEDIR__/podman
 ns2b	./bin/podman run --net=pasta --rm -ti alpine sh
 sleep	2
 
diff --git a/test/distro/debian b/test/distro/debian
index 83fb32d..4a19f95 100644
--- a/test/distro/debian
+++ b/test/distro/debian
@@ -11,7 +11,7 @@
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-temp	PIDFILE
+set	PIDFILE __STATEDIR__/passt.pid
 htools	cat kill qemu-system-x86_64 qemu-system-aarch64 qemu-system-ppc64
 
 # Quick pasta test: send message from init to ns, and from ns to init
diff --git a/test/distro/fedora b/test/distro/fedora
index daad6a4..a8d3b51 100644
--- a/test/distro/fedora
+++ b/test/distro/fedora
@@ -11,7 +11,7 @@
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-temp	PIDFILE
+set	PIDFILE __STATEDIR__/passt.pid
 htools	cat kill qemu-system-x86_64
 
 # Quick pasta test: send message from init to ns, and from ns to init
diff --git a/test/distro/opensuse b/test/distro/opensuse
index d48deb7..314870f 100644
--- a/test/distro/opensuse
+++ b/test/distro/opensuse
@@ -11,7 +11,7 @@
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-temp	PIDFILE
+set	PIDFILE __STATEDIR__/passt.pid
 htools	qemu-img virt-edit guestfish head sed cat kill qemu-system-x86_64 qemu-system-aarch64 xzcat tr
 
 # Quick pasta test: send message from init to ns, and from ns to init
@@ -44,7 +44,7 @@ hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 qrap.1 Makefile README.md | tr '\n'
 
 test	OpenSUSE Leap 15.1
 
-temp	IMG
+set	IMG __STATEDIR__/opensuse-15.1-x86_64.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/openSUSE-Leap-15.1-JeOS.x86_64-kvm-and-xen.qcow2 __IMG__
 host	guestfish --rw -a __IMG__ -i rm '/usr/lib/systemd/system/systemd-journald.service'
 host	guestfish --rw -a __IMG__ -i rm /etc/systemd/system/default.target.wants/jeos-firstboot.service
@@ -73,6 +73,7 @@ hout	PID cat __PIDFILE__
 
 test	OpenSUSE Leap 15.2
 
+set	IMG __STATEDIR__/opensuse-15.2-x86_64.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/openSUSE-Leap-15.2-JeOS.x86_64-kvm-and-xen.qcow2 __IMG__
 host	guestfish --rw -a __IMG__ -i rm '/usr/lib/systemd/system/systemd-journald.service'
 host	guestfish --rw -a __IMG__ -i rm /etc/systemd/system/default.target.wants/jeos-firstboot.service
@@ -98,6 +99,7 @@ sleep	1
 
 test	OpenSUSE Leap 15.3
 
+set	IMG __STATEDIR__/opensuse-15.3-x86_64.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/openSUSE-Leap-15.3-JeOS.x86_64-kvm-and-xen.qcow2 __IMG__
 host	guestfish --rw -a __IMG__ -i rm '/usr/lib/systemd/system/systemd-journald.service'
 host	guestfish --rw -a __IMG__ -i rm /etc/systemd/system/default.target.wants/jeos-firstboot.service
@@ -125,7 +127,7 @@ sleep	1
 
 test	OpenSUSE Tumbleweed aarch64
 
-temp	IMG
+set	IMG __STATEDIR__/opensuse-tumbleweed-aarch64.img
 host	xzcat __BASEPATH__/openSUSE-Tumbleweed-ARM-JeOS-efi.aarch64.raw.xz > __IMG__
 host	virt-edit -a __IMG__ -m /dev/sda3 /usr/lib/systemd/system/serial-getty(a).service -e 's/ExecStart=.*/ExecStart=\/sbin\/agetty --timeout 5000 --autologin root -i -8 --keep-baud 115200,38400,9600 %I $TERM/g'
 host	guestfish --rw -a __IMG__ -i copy-in __GUEST_FILES__ /root/
@@ -150,9 +152,9 @@ sleep	1
 
 test	OpenSUSE Tumbleweed armv7l
 
-temp	IMG
-temp	ZIMAGE
-temp	INITRD
+set	IMG __STATEDIR__/opensuse-tumbleweed-armv7l.img
+set	ZIMAGE __STATEDIR__/opensuse-tumbleweed-armv7l.zimage
+set	INITRD __STATEDIR__/opensuse-tumbleweed-armv7l.initrd
 host	xzcat __BASEPATH__/openSUSE-Tumbleweed-ARM-JeOS-efi.armv7l.raw.xz > __IMG__
 host	guestfish -a __IMG__ -i download /boot/zImage __ZIMAGE__
 host	guestfish -a __IMG__ -i download /boot/initrd __INITRD__
@@ -178,7 +180,7 @@ sleep	1
 
 test	OpenSUSE Tumbleweed
 
-temp	IMG
+set	IMG __STATEDIR__/opensuse-tumbleweed-x86_64.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/openSUSE-Tumbleweed-JeOS.x86_64-kvm-and-xen.qcow2 __IMG__
 host	guestfish --rw -a __IMG__ -i rm /usr/lib/systemd/system/systemd-journald.service
 host	guestfish --rw -a __IMG__ -i rm /etc/systemd/system/default.target.wants/jeos-firstboot.service
diff --git a/test/distro/ubuntu b/test/distro/ubuntu
index 5e67a46..aa42c99 100644
--- a/test/distro/ubuntu
+++ b/test/distro/ubuntu
@@ -11,7 +11,7 @@
 # Copyright (c) 2021 Red Hat GmbH
 # Author: Stefano Brivio <sbrivio(a)redhat.com>
 
-temp	PIDFILE
+set	PIDFILE __STATEDIR__/passt.pid
 htools	qemu-img virt-edit guestfish cat kill qemu-system-x86_64 qemu-system-ppc64 qemu-system-s390x
 
 # Quick pasta test: send message from init to ns, and from ns to init
@@ -68,7 +68,7 @@ hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 qrap.1 Makefile README.md | tr '\n'
 
 test	Ubuntu 14.04.5 LTS (Trusty Tahr), amd64
 
-temp	IMG
+set	IMG __STATEDIR__/ubuntu-14.04-amd64.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/trusty-server-cloudimg-amd64-disk1.img __IMG__
 host	virt-edit -a __IMG__ /etc/init/ttyS0.conf -e 's/\/getty/\/getty --autologin root/'
 host	guestfish --rw -a __IMG__ -i rm /etc/init/cloud-config.conf
@@ -101,7 +101,7 @@ hout	PID cat __PIDFILE__
 
 test	Ubuntu 14.04.5 LTS (Trusty Tahr), i386
 
-temp	IMG
+set	IMG __STATEDIR__/ubuntu-14.04-i386.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/trusty-server-cloudimg-i386-disk1.img __IMG__
 host	virt-edit -a __IMG__ /etc/init/ttyS0.conf -e 's/\/getty/\/getty --autologin root/'
 host	guestfish --rw -a __IMG__ -i rm /etc/init/cloud-config.conf
@@ -131,7 +131,7 @@ sleep	1
 
 test	Ubuntu 14.04.5 LTS (Trusty Tahr), ppc64le
 
-temp	IMG
+set	IMG __STATEDIR__/ubuntu-14.04-ppc64le.img
 host	qemu-img create -f qcow2 -F qcow2 -b __BASEPATH__/trusty-server-cloudimg-ppc64el-disk1.img __IMG__
 host	virt-edit -a __IMG__ /etc/init/hvc0.conf -e 's/\/getty/\/getty --autologin root/'
 host	guestfish --rw -a __IMG__ -i rm /etc/init/cloud-config.conf
diff --git a/test/lib/test b/test/lib/test
index 3dbae0b..3ad178f 100755
--- a/test/lib/test
+++ b/test/lib/test
@@ -99,16 +99,6 @@ test_one_line() {
 		IFS= eval TEST_ONE_DEF_$TEST_ONE_in_def=
 		IFS="${__ifs}"
 		;;
-	"tempdir")
-		__tmpdir="$(mktemp -d)"
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__arg}__" "${__tmpdir}")"
-		TEST_ONE_dirclean="$(list_add "${TEST_ONE_dirclean}" "${__tmpdir}")"
-		;;
-	"temp")
-		__tmpfile="$(mktemp)"
-		TEST_ONE_subs="$(list_add_pair "${TEST_ONE_subs}" "__${__arg}__" "${__tmpfile}")"
-		TEST_ONE_dirclean="$(list_add "${TEST_ONE_dirclean}" "${__tmpfile}")"
-		;;
 	"test")
 		[ ${TEST_ONE_perf_nok} -eq 0 ] || TEST_ONE_nok=1
 		[ ${TEST_ONE_nok} -eq 1 ] && status_test_fail
diff --git a/test/passt/tcp b/test/passt/tcp
index d5c8164..7af9c54 100644
--- a/test/passt/tcp
+++ b/test/passt/tcp
@@ -15,7 +15,7 @@ gtools	socat ip jq md5sum cut
 htools	dd socat ip jq md5sum cut
 
 test	TCP/IPv4: host to guest: big transfer
-temp	TEMP_BIG
+set	TEMP_BIG __STATEDIR__/big
 guestb	socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_big.bin,create,trunc
 sleep	1
 host	dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
@@ -34,7 +34,7 @@ hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
 
 test	TCP/IPv4: host to guest: small transfer
-temp	TEMP_SMALL
+set	TEMP_SMALL __STATEDIR__/small
 guestb	socat -u TCP4-LISTEN:10001,reuseaddr OPEN:test_small.bin,create,trunc
 sleep	1
 host	dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
diff --git a/test/passt/udp b/test/passt/udp
index 56d01b3..0253a86 100644
--- a/test/passt/udp
+++ b/test/passt/udp
@@ -15,9 +15,9 @@ gtools	socat tee grep cat ip jq md5sum cut
 htools	printf dd socat tee grep cat ip jq md5sum cut
 
 test	UDP/IPv4: host to guest
-temp	TEMP
-temp	SC_PID
-guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > __SC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
+set	TEMP __STATEDIR__/data
+set	SC_PID __STATEDIR__/socat.pid
+guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
 sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10001
diff --git a/test/passt_in_ns/tcp b/test/passt_in_ns/tcp
index 5ec95e8..a2cb667 100644
--- a/test/passt_in_ns/tcp
+++ b/test/passt_in_ns/tcp
@@ -16,7 +16,7 @@ htools	dd socat ip jq md5sum cut
 nstools	socat ip jq md5sum cut
 
 test	TCP/IPv4: host to guest: big transfer
-temp	TEMP_BIG
+set	TEMP_BIG __STATEDIR__/big.img
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_big.bin,create,trunc
 sleep	1
 host	dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__
@@ -27,7 +27,7 @@ gout	GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
 check	[ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv4: host to ns: big transfer
-temp	TEMP_NS_BIG
+set	TEMP_NS_BIG __STATEDIR__/big_ns.img
 nsb	socat -u TCP4-LISTEN:10002 OPEN:__TEMP_NS_BIG__,create,trunc
 host	socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10002
 nsw
@@ -82,7 +82,7 @@ gout	GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
 check	[ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv4: host to guest: small transfer
-temp	TEMP_SMALL
+set	TEMP_SMALL __STATEDIR__/small.img
 guestb	socat -u TCP4-LISTEN:10001 OPEN:test_small.bin,create,trunc
 sleep	1
 host	dd if=/dev/urandom bs=2k count=100 of=__TEMP_SMALL__
@@ -93,7 +93,7 @@ gout	GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
 check	[ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
 
 test	TCP/IPv4: host to ns: small transfer
-temp	TEMP_NS_SMALL
+set	TEMP_NS_SMALL __STATEDIR__/small_ns.img
 nsb	socat -u TCP4-LISTEN:10002 OPEN:__TEMP_NS_SMALL__,create,trunc
 host	socat -u OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10002
 nsw
diff --git a/test/passt_in_ns/udp b/test/passt_in_ns/udp
index c22a68f..3b1e521 100644
--- a/test/passt_in_ns/udp
+++ b/test/passt_in_ns/udp
@@ -16,8 +16,8 @@ nstools	socat tee grep cat ip jq md5sum cut
 htools	printf dd socat tee grep cat ip jq md5sum cut
 
 test	UDP/IPv4: host to guest
-temp	TEMP
-temp	SC_PID
+set	TEMP __STATEDIR__/data
+set	SC_PID __STATEDIR__/socat.pid
 guestb	(socat -u UDP4-LISTEN:10001 STDOUT & echo $! > sc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat sc.pid))
 sleep	1
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
@@ -28,7 +28,7 @@ gout	GUEST_MD5 md5sum test.bin | cut -d' ' -f1
 check	[ "__GUEST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv4: host to ns
-temp	TEMP_NS
+set	TEMP_NS __STATEDIR__/data_ns
 nsb	(socat -u UDP4-LISTEN:10002 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 host	socat -u OPEN:__TEMP__ UDP4:127.0.0.1:10002
 nsw
diff --git a/test/pasta/tcp b/test/pasta/tcp
index 5497f11..d37e21c 100644
--- a/test/pasta/tcp
+++ b/test/pasta/tcp
@@ -15,8 +15,8 @@ htools	dd socat ip jq md5sum cut
 nstools	socat ip jq md5sum cut
 
 test	TCP/IPv4: host to ns: big transfer
-temp	TEMP_BIG
-temp	TEMP_NS_BIG
+set	TEMP_BIG __STATEDIR__/big
+set	TEMP_NS_BIG __STATEDIR__/big_ns
 nsb	socat -u TCP4-LISTEN:10002,bind=127.0.0.1 OPEN:__TEMP_NS_BIG__,create,trunc
 host	dd if=/dev/urandom bs=1M count=10 of=__TEMP_BIG__
 host	socat -u OPEN:__TEMP_BIG__ TCP4:127.0.0.1:10002
@@ -41,8 +41,8 @@ hout	HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
 check	[ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
 
 test	TCP/IPv4: host to ns: small transfer
-temp	TEMP_SMALL
-temp	TEMP_NS_SMALL
+set	TEMP_SMALL __STATEDIR__/small
+set	TEMP_NS_SMALL __STATEDIR__/small_ns
 nsb	socat -u TCP4-LISTEN:10002,bind=127.0.0.1 OPEN:__TEMP_NS_SMALL__,create,trunc
 host	dd if=/dev/urandom bs=2k count=1 of=__TEMP_SMALL__
 host	socat OPEN:__TEMP_SMALL__ TCP4:127.0.0.1:10002
diff --git a/test/pasta/udp b/test/pasta/udp
index 0e58152..74148e3 100644
--- a/test/pasta/udp
+++ b/test/pasta/udp
@@ -15,10 +15,10 @@ nstools	socat tee grep cat ip jq md5sum cut
 htools	printf dd socat tee grep cat ip jq md5sum cut
 
 test	UDP/IPv4: host to ns
-temp	TEMP
-temp	TEMP_NS
-temp	NC_PID
-nsb	(socat -u UDP4-LISTEN:10002,bind=127.0.0.1 STDOUT & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+set	TEMP __STATEDIR__/data
+set	TEMP_NS __STATEDIR__/data_ns
+set	SC_PID __STATEDIR__/socat.pid
+nsb	(socat -u UDP4-LISTEN:10002,bind=127.0.0.1 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 
 host	socat OPEN:__TEMP__ UDP4:127.0.0.1:10002
@@ -28,7 +28,7 @@ nsout	NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
 check	[ "__NS_MD5__" = "__MD5__" ]
 
 test	UDP/IPv4: ns to host (recvmmsg/sendmmsg)
-hostb	(socat -u UDP4-LISTEN:10003,bind=127.0.0.1 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP4-LISTEN:10003,bind=127.0.0.1 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 sleep	1
 ns	socat OPEN:__TEMP_NS__ UDP4:127.0.0.1:10003
 hostw
@@ -36,7 +36,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv4: ns to host (via tap)
-hostb	(socat -u UDP4-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP4-LISTEN:10003 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 nsout	GW ip -j -4 route show|jq -rM '.[] | select(.dst == "default").gateway'
 ns	socat -u OPEN:__TEMP_NS__ UDP4:__GW__:10003
 hostw
@@ -44,7 +44,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: host to ns
-nsb	(socat -u UDP6-LISTEN:10002,bind=[::1] STDOUT & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+nsb	(socat -u UDP6-LISTEN:10002,bind=[::1] STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 host	socat -u OPEN:__TEMP__ UDP6:[::1]:10002
 nsw
 hout	MD5 md5sum __TEMP__ | cut -d' ' -f1
@@ -52,7 +52,7 @@ nsout	NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
 check	[ "__NS_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: ns to host (recvmmsg/sendmmsg)
-hostb	(socat -u UDP6-LISTEN:10003,bind=[::1] STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP6-LISTEN:10003,bind=[::1] STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 sleep	1
 ns	socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
 hostw
@@ -60,7 +60,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: ns to host (via tap)
-hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 nsout	GW6 ip -j -6 route show|jq -rM '.[] | select(.dst == "default").gateway'
 nsout	IFNAME ip -j link show | jq -rM '.[] | select(.link_type == "ether").ifname'
 ns	socat -u OPEN:__TEMP_NS__ UDP6:[__GW6__%__IFNAME__]:10003
-- 
@@ -15,10 +15,10 @@ nstools	socat tee grep cat ip jq md5sum cut
 htools	printf dd socat tee grep cat ip jq md5sum cut
 
 test	UDP/IPv4: host to ns
-temp	TEMP
-temp	TEMP_NS
-temp	NC_PID
-nsb	(socat -u UDP4-LISTEN:10002,bind=127.0.0.1 STDOUT & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+set	TEMP __STATEDIR__/data
+set	TEMP_NS __STATEDIR__/data_ns
+set	SC_PID __STATEDIR__/socat.pid
+nsb	(socat -u UDP4-LISTEN:10002,bind=127.0.0.1 STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 host	dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
 
 host	socat OPEN:__TEMP__ UDP4:127.0.0.1:10002
@@ -28,7 +28,7 @@ nsout	NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
 check	[ "__NS_MD5__" = "__MD5__" ]
 
 test	UDP/IPv4: ns to host (recvmmsg/sendmmsg)
-hostb	(socat -u UDP4-LISTEN:10003,bind=127.0.0.1 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP4-LISTEN:10003,bind=127.0.0.1 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 sleep	1
 ns	socat OPEN:__TEMP_NS__ UDP4:127.0.0.1:10003
 hostw
@@ -36,7 +36,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv4: ns to host (via tap)
-hostb	(socat -u UDP4-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP4-LISTEN:10003 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 nsout	GW ip -j -4 route show|jq -rM '.[] | select(.dst == "default").gateway'
 ns	socat -u OPEN:__TEMP_NS__ UDP4:__GW__:10003
 hostw
@@ -44,7 +44,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: host to ns
-nsb	(socat -u UDP6-LISTEN:10002,bind=[::1] STDOUT & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+nsb	(socat -u UDP6-LISTEN:10002,bind=[::1] STDOUT & echo $! > __SC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 host	socat -u OPEN:__TEMP__ UDP6:[::1]:10002
 nsw
 hout	MD5 md5sum __TEMP__ | cut -d' ' -f1
@@ -52,7 +52,7 @@ nsout	NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
 check	[ "__NS_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: ns to host (recvmmsg/sendmmsg)
-hostb	(socat -u UDP6-LISTEN:10003,bind=[::1] STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP6-LISTEN:10003,bind=[::1] STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 sleep	1
 ns	socat -u OPEN:__TEMP_NS__ UDP6:[::1]:10003
 hostw
@@ -60,7 +60,7 @@ hout	HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
 check	[ "__HOST_MD5__" = "__MD5__" ]
 
 test	UDP/IPv6: ns to host (via tap)
-hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
+hostb	(socat -u UDP6-LISTEN:10003 STDOUT & echo $! > __SC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __SC_PID__))
 nsout	GW6 ip -j -6 route show|jq -rM '.[] | select(.dst == "default").gateway'
 nsout	IFNAME ip -j link show | jq -rM '.[] | select(.link_type == "ether").ifname'
 ns	socat -u OPEN:__TEMP_NS__ UDP6:[__GW6__%__IFNAME__]:10003
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 29/32] test: Move pause temporary file to state directory
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (27 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 28/32] test: Use paths in __STATEDIR__ instead of 'temp' and 'tempdir' directives David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 30/32] test: Store pcap files in $LOGDIR instead of /tmp David Gibson
                   ` (2 subsequent siblings)
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 549 bytes --]

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/term | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/lib/term b/test/lib/term
index b2a45e4..7f77f70 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -599,8 +599,8 @@ pause_continue() {
 	info_nolog "${1}"
 	info_nolog_n "${2}"
 
-	__pause_tmp="$(mktemp)"
-	echo >> "${__pause_tmp}"
+	__pause_tmp="${STATEBASE}/pause.tmp"
+	echo > "${__pause_tmp}"
 	tmux pipe-pane -O -t ${PANE_INFO} "cat >> ${__pause_tmp}"
 	__pane_buf=
 	__wait=0
-- 
@@ -599,8 +599,8 @@ pause_continue() {
 	info_nolog "${1}"
 	info_nolog_n "${2}"
 
-	__pause_tmp="$(mktemp)"
-	echo >> "${__pause_tmp}"
+	__pause_tmp="${STATEBASE}/pause.tmp"
+	echo > "${__pause_tmp}"
 	tmux pipe-pane -O -t ${PANE_INFO} "cat >> ${__pause_tmp}"
 	__pane_buf=
 	__wait=0
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 30/32] test: Store pcap files in $LOGDIR instead of /tmp
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (28 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 29/32] test: Move pause temporary file to state directory David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 31/32] test: Move pidfiles and nsholder sockets into state directory David Gibson
  2022-09-08  6:16 ` [PATCH v2 32/32] test: Move video processing files to $STATEBASE David Gibson
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 3460 bytes --]

The capture files are more or less a different form of log output from the
tests, so place them in $LOGDIR.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/lib/setup | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/test/lib/setup b/test/lib/setup
index b0420fb..87eb05a 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -47,7 +47,7 @@ setup_passt() {
 	#  10003                |      as server
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -94,7 +94,7 @@ setup_pasta() {
 	#  10003   spliced to init  |      as server
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -124,7 +124,7 @@ setup_passt_in_ns() {
 	#  10031    as server  | forwarded to guest |
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_with_passt.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_with_passt.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -142,7 +142,7 @@ setup_passt_in_ns() {
 	context_run ns "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_in_pasta.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_in_pasta.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -194,7 +194,7 @@ setup_two_guests() {
 	#  10005            |           |           |  as server |  to ns #2
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 	context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
@@ -202,7 +202,7 @@ setup_two_guests() {
 	context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 	context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
@@ -220,7 +220,7 @@ setup_two_guests() {
 	context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -228,7 +228,7 @@ setup_two_guests() {
 	sleep 1
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-- 
@@ -47,7 +47,7 @@ setup_passt() {
 	#  10003                |      as server
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -94,7 +94,7 @@ setup_pasta() {
 	#  10003   spliced to init  |      as server
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -124,7 +124,7 @@ setup_passt_in_ns() {
 	#  10031    as server  | forwarded to guest |
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_with_passt.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_with_passt.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -142,7 +142,7 @@ setup_passt_in_ns() {
 	context_run ns "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_in_pasta.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_in_pasta.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -194,7 +194,7 @@ setup_two_guests() {
 	#  10005            |           |           |  as server |  to ns #2
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 	context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
@@ -202,7 +202,7 @@ setup_two_guests() {
 	context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 	context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
@@ -220,7 +220,7 @@ setup_two_guests() {
 	context_run qemu_2 "/sbin/dhclient -6 --no-pid ${__ifname}"
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
@@ -228,7 +228,7 @@ setup_two_guests() {
 	sleep 1
 
 	__opts=
-	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
+	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 31/32] test: Move pidfiles and nsholder sockets into state directory
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (29 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 30/32] test: Store pcap files in $LOGDIR instead of /tmp David Gibson
@ 2022-09-08  6:16 ` David Gibson
  2022-09-08  6:16 ` [PATCH v2 32/32] test: Move video processing files to $STATEBASE David Gibson
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 11033 bytes --]

Currently they go in the passt source tree with a fixed names, which means
their presence can mess with subsequent test runs.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 .gitignore                |  1 -
 test/lib/setup            | 66 +++++++++++++++++++--------------------
 test/passt/shutdown       |  2 +-
 test/passt_in_ns/shutdown |  2 +-
 4 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/.gitignore b/.gitignore
index 80967f3..d3d0e2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,5 @@
 /qrap
 /pasta.1
 /seccomp.h
-/*.pid
 /s*.json
 README.plain.md
diff --git a/test/lib/setup b/test/lib/setup
index 87eb05a..bda53f8 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -53,7 +53,7 @@ setup_passt() {
 
 	context_run passt "make clean"
 	context_run passt "make valgrind"
-	context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P passt.pid"
+	context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt ${__opts} -f -t 10001 -u 10001 -P ${STATESETUP}/passt.pid"
 	sleep 5
 
 	GUEST_CID=94557
@@ -67,7 +67,7 @@ setup_passt() {
 		'virtio-net.napi_tx=1"'					   \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"  \
 		" -netdev socket,fd=5,id=hostnet0"			   \
-		" -pidfile passt_qemu.pid"				   \
+		" -pidfile ${STATESETUP}/qemu.pid"			   \
 		" -device vhost-vsock-pci,guest-cid=$GUEST_CID"
 
 	context_setup_guest guest $GUEST_CID
@@ -81,8 +81,8 @@ setup_pasta() {
 
 	layout_pasta
 
-	context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ns.hold hold"
-	__target_pid=$(${NSHOLDER} ns.hold pid)
+	context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ${STATESETUP}/ns.hold hold"
+	__target_pid=$(${NSHOLDER} ${STATESETUP}/ns.hold pid)
 
 	context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
 
@@ -98,7 +98,7 @@ setup_pasta() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P passt.pid ${__target_pid}"
+	context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P ${STATESETUP}/passt.pid ${__target_pid}"
 	sleep 1
 }
 
@@ -128,9 +128,9 @@ setup_passt_in_ns() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	context_run_bg pasta "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P pasta.pid ${NSHOLDER} ns.hold hold"
+	context_run_bg pasta "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013 -P ${STATESETUP}/pasta.pid ${NSHOLDER} ${STATESETUP}/ns.hold hold"
 	sleep 1
-	__ns_pid=$(${NSHOLDER} ns.hold pid)
+	__ns_pid=$(${NSHOLDER} ${STATESETUP}/ns.hold pid)
 
 	context_setup_nsenter qemu "-t ${__ns_pid} -U -n -p --preserve-credentials"
 	context_setup_nsenter ns "-t ${__ns_pid} -U -n -p --preserve-credentials"
@@ -149,11 +149,11 @@ setup_passt_in_ns() {
 	if [ ${VALGRIND} -eq 1 ]; then
 		context_run passt "make clean"
 		context_run passt "make valgrind"
-		context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+		context_run_bg passt "valgrind --max-stackframe=$((4 * 1024 * 1024)) --trace-children=yes --vgdb=no --error-exitcode=1 --suppressions=test/valgrind.supp ./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P ${STATESETUP}/passt.pid"
 	else
 		context_run passt "make clean"
 		context_run passt "make"
-		context_run_bg passt "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P passt.pid"
+		context_run_bg passt "./passt -f ${__opts} -t 10001,10011,10021,10031 -u 10001,10011,10021,10031 -P ${STATESETUP}/passt.pid"
 	fi
 	sleep 5
 
@@ -169,7 +169,7 @@ setup_passt_in_ns() {
 		'virtio-net.napi_tx=1"'					   \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=524288" \
 		" -netdev socket,fd=5,id=hostnet0"			   \
-		' -pidfile passt_in_ns_qemu.pid'			   \
+		" -pidfile ${STATESETUP}/qemu.pid"			   \
 		" -device vhost-vsock-pci,guest-cid=$GUEST_CID"
 
 	context_setup_guest guest $GUEST_CID
@@ -197,16 +197,16 @@ setup_two_guests() {
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_1.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	context_run_bg pasta_1 "./pasta ${__opts} -P pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ns1.hold hold"
-	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
+	context_run_bg pasta_1 "./pasta ${__opts} -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 ${NSHOLDER} ${STATESETUP}/ns1.hold hold"
+	__ns1_pid=$(${NSHOLDER} ${STATESETUP}/ns1.hold pid)
 	context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
 
 	__opts=
 	[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/pasta_2.pcap"
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
-	context_run_bg pasta_2 "./pasta ${__opts} -P pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ns2.hold hold"
-	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
+	context_run_bg pasta_2 "./pasta ${__opts} -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 ${NSHOLDER} ${STATESETUP}/ns2.hold hold"
+	__ns2_pid=$(${NSHOLDER} ${STATESETUP}/ns2.hold pid)
 	context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
 
 	context_setup_nsenter qemu_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
@@ -224,7 +224,7 @@ setup_two_guests() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	context_run_bg passt_1 "./passt -P passt_1.pid -f ${__opts} -t 10001 -u 10001"
+	context_run_bg passt_1 "./passt -P ${STATESETUP}/passt_1.pid -f ${__opts} -t 10001 -u 10001"
 	sleep 1
 
 	__opts=
@@ -232,7 +232,7 @@ setup_two_guests() {
 	[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
 	[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
 
-	context_run_bg passt_2 "./passt -P passt_2.pid -f ${__opts} -t 10004 -u 10004"
+	context_run_bg passt_2 "./passt -P ${STATESETUP}/passt_2.pid -f ${__opts} -t 10004 -u 10004"
 
 	GUEST_1_CID=94557
 	context_run_bg qemu_1 './qrap 5 qemu-system-$(uname -m)'             \
@@ -245,7 +245,7 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_1.pid'			     \
+		" -pidfile ${STATESETUP}/qemu_1.pid"			     \
 		" -device vhost-vsock-pci,guest-cid=$GUEST_1_CID"
 
 	GUEST_2_CID=94558
@@ -259,7 +259,7 @@ setup_two_guests() {
 		'virtio-net.napi_tx=1"'					     \
 		" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384"    \
 		" -netdev socket,fd=5,id=hostnet0"			     \
-		' -pidfile two_guests_qemu_2.pid'			     \
+		" -pidfile ${STATESETUP}/qemu_2.pid"			     \
 		" -device vhost-vsock-pci,guest-cid=$GUEST_2_CID"
 
 	context_setup_guest guest_1 ${GUEST_1_CID}
@@ -290,9 +290,9 @@ teardown_distro() {
 
 # teardown_passt() - Kill qemu, remove passt PID file
 teardown_passt() {
-	kill $(cat passt_qemu.pid)
+	kill $(cat "${STATESETUP}/qemu.pid")
 
-	rm passt.pid
+	rm "${STATESETUP}/passt.pid"
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_PASST} passt
@@ -301,7 +301,7 @@ teardown_passt() {
 
 # teardown_passt() - Exit namespace, kill pasta process
 teardown_pasta() {
-	${NSHOLDER} ns.hold stop
+	${NSHOLDER} "${STATESETUP}/ns.hold" stop
 	context_wait unshare
 
 	teardown_context_watch ${PANE_HOST} host
@@ -311,13 +311,13 @@ teardown_pasta() {
 
 # teardown_passt_in_ns() - Exit namespace, kill qemu and pasta, remove pid file
 teardown_passt_in_ns() {
-	context_run ns kill $(cat passt_in_ns_qemu.pid)
+	context_run ns kill $(cat "${STATESETUP}/qemu.pid")
 	context_wait qemu
 
-	${NSHOLDER} ns.hold stop
+	${NSHOLDER} "${STATESETUP}/ns.hold" stop
 	context_wait pasta
 
-	rm passt.pid pasta.pid
+	rm "${STATESETUP}/passt.pid" "${STATESETUP}/pasta.pid"
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_PASST} pasta passt
@@ -327,23 +327,23 @@ teardown_passt_in_ns() {
 
 # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
 teardown_two_guests() {
-	__ns1_pid=$(${NSHOLDER} ns1.hold pid)
-	__ns2_pid=$(${NSHOLDER} ns2.hold pid)
-	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat two_guests_qemu_1.pid)
-	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat two_guests_qemu_2.pid)
+	__ns1_pid=$(${NSHOLDER} "${STATESETUP}/ns1.hold" pid)
+	__ns2_pid=$(${NSHOLDER} "${STATESETUP}/ns2.hold" pid)
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat "${STATESETUP}/qemu_1.pid")
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat "${STATESETUP}/qemu_2.pid")
 	context_wait qemu_1
 	context_wait qemu_2
 
-	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat passt_1.pid)
-	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat passt_2.pid)
+	nsenter -U -p --preserve-credentials -t ${__ns1_pid} kill $(cat "${STATESETUP}/passt_1.pid")
+	nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat "${STATESETUP}/passt_2.pid")
 	context_wait passt_1
 	context_wait passt_2
-	${NSHOLDER} ns1.hold stop
-	${NSHOLDER} ns2.hold stop
+	${NSHOLDER} "${STATESETUP}/ns1.hold" stop
+	${NSHOLDER} "${STATESETUP}/ns2.hold" stop
 	context_wait pasta_1
 	context_wait pasta_2
 
-	rm -f passt_[12].pid pasta_[12].pid
+	rm -f "${STATESETUP}/passt__[12].pid" "${STATESETUP}/pasta_[12].pid"
 
 	teardown_context_watch ${PANE_HOST} host
 	teardown_context_watch ${PANE_GUEST_1} qemu_1 guest_1
diff --git a/test/passt/shutdown b/test/passt/shutdown
index ce90ea9..34ddb64 100644
--- a/test/passt/shutdown
+++ b/test/passt/shutdown
@@ -14,7 +14,7 @@
 
 test	shutdown: exit code
 
-hout	PASST_PID cat passt.pid
+hout	PASST_PID cat __STATESETUP__/passt.pid
 host	kill __PASST_PID__
 sleep	1
 passtw
diff --git a/test/passt_in_ns/shutdown b/test/passt_in_ns/shutdown
index abe9d6c..b602ec2 100644
--- a/test/passt_in_ns/shutdown
+++ b/test/passt_in_ns/shutdown
@@ -14,7 +14,7 @@
 
 test	shutdown: exit code
 
-nsout	PASST_PID cat passt.pid
+nsout	PASST_PID cat __STATESETUP__/passt.pid
 ns	kill __PASST_PID__
 sleep	1
 passtw
-- 
@@ -14,7 +14,7 @@
 
 test	shutdown: exit code
 
-nsout	PASST_PID cat passt.pid
+nsout	PASST_PID cat __STATESETUP__/passt.pid
 ns	kill __PASST_PID__
 sleep	1
 passtw
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 32/32] test: Move video processing files to $STATEBASE
  2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
                   ` (30 preceding siblings ...)
  2022-09-08  6:16 ` [PATCH v2 31/32] test: Move pidfiles and nsholder sockets into state directory David Gibson
@ 2022-09-08  6:16 ` David Gibson
  31 siblings, 0 replies; 33+ messages in thread
From: David Gibson @ 2022-09-08  6:16 UTC (permalink / raw)
  To: passt-dev

[-- Attachment #1: Type: text/plain, Size: 3871 bytes --]

The asciinema video handling creates a number of temporary files (.uncat,
.start, .stop) which currently go into the source tree.  Put them in the
temporary state directory to avoid clutter.  Put the final processed video
into the test_logs/ directory, since it's essentially a test output
artefact.

Signed-off-by: David Gibson <david(a)gibson.dropbear.id.au>
---
 test/.gitignore |  3 ---
 test/lib/term   |  8 ++++----
 test/lib/video  | 19 ++++++++++---------
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/test/.gitignore b/test/.gitignore
index 0f91c7d..58c8cf2 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -6,9 +6,6 @@ QEMU_EFI.fd
 *.qcow2
 *.raw
 *.raw.xz
-*.uncut
-*.start
-*.stop
 *.js
 nsholder
 guest-key
diff --git a/test/lib/term b/test/lib/term
index 7f77f70..2945419 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -643,12 +643,12 @@ run_term() {
 
 	if [ ${CI} -eq 1 ]; then
 		printf '\e[8;50;240t'
-		asciinema rec --overwrite ci.uncut -c "$TMUX /bin/sh -c './ci from_term'"
-		video_postprocess ci.uncut
+		asciinema rec --overwrite "${STATEBASE}/ci.uncut" -c "$TMUX /bin/sh -c './ci from_term'"
+		video_postprocess "${STATEBASE}/ci.uncut"
 	elif [ ${DEMO} -eq 1 ]; then
 		printf '\e[8;40;130t'
-		asciinema rec --overwrite demo.uncut -c "$TMUX /bin/sh -c './run_demo from_term'"
-		video_postprocess demo.uncut
+		asciinema rec --overwrite "${STATEBASE}/demo.uncut" -c "$TMUX /bin/sh -c './run_demo from_term'"
+		video_postprocess "${STATEBASE}/demo.uncut"
 	else
 		$TMUX /bin/sh -c './run from_term'
 	fi
diff --git a/test/lib/video b/test/lib/video
index f609abf..915a42f 100755
--- a/test/lib/video
+++ b/test/lib/video
@@ -77,8 +77,8 @@ video_start() {
 	VIDEO_START_SECONDS=$(sed -n 's/\([0-9]*\).[0-9]* [0-9]*.[0-9]*/\1/p' /proc/uptime)
 
 	sync
-	[ ${DEMO} -eq 1 ] && tail -1 "${BASEPATH}/demo.uncut" > "${BASEPATH}/${VIDEO_NAME}.start"
-	[ ${CI} -eq 1 ] && tail -1 "${BASEPATH}/ci.uncut" > "${BASEPATH}/${VIDEO_NAME}.start"
+	[ ${DEMO} -eq 1 ] && tail -1 "${STATEBASE}/demo.uncut" > "${STATEBASE}/${VIDEO_NAME}.start"
+	[ ${CI} -eq 1 ] && tail -1 "${STATEBASE}/ci.uncut" > "${STATEBASE}/${VIDEO_NAME}.start"
 	sync
 
 	tmux refresh-client
@@ -89,8 +89,8 @@ video_stop() {
 	tmux refresh-client
 
 	sync
-	[ ${DEMO} -eq 1 ] && tail -1 "${BASEPATH}/demo.uncut" > "${BASEPATH}/${VIDEO_NAME}.stop"
-	[ ${CI} -eq 1 ] && tail -1 "${BASEPATH}/ci.uncut" > "${BASEPATH}/${VIDEO_NAME}.stop"
+	[ ${DEMO} -eq 1 ] && tail -1 "${STATEBASE}/demo.uncut" > "${STATEBASE}/${VIDEO_NAME}.stop"
+	[ ${CI} -eq 1 ] && tail -1 "${STATEBASE}/ci.uncut" > "${STATEBASE}/${VIDEO_NAME}.stop"
 	sync
 
 	sed -i 's/^.*$/&\\/g' "${BASEPATH}/${VIDEO_NAME}.js"
@@ -108,12 +108,13 @@ video_postprocess() {
 		[ -z "${__header}" ] && __header="${__l}" && continue
 
 		if [ -z "${__cast_name}" ]; then
-			for __cast_cut in *.start; do
+		        for __cast_cut in "${STATEBASE}/"*.start; do
 				[ "${__l}" != "$(cat "${__cast_cut}")" ] && continue
-				__cast_name="${__cast_cut%.start}"
+				__cast_name="$(basename "${__cast_cut}")"
+                                __cast_name="${__cast_name%.start}"
 				__cast_offset=
-				__stop_line="$(cat ${__cast_name}.stop)"
-				echo "${__header}" > "${__cast_name}.cast"
+				__stop_line="$(cat "${STATEBASE}/${__cast_name}.stop")"
+				echo "${__header}" > "${LOGDIR}/${__cast_name}.cast"
 				break
 			done
 			continue
@@ -125,7 +126,7 @@ video_postprocess() {
 		__l_rest="${__l#*.}"
 		[ -z "${__cast_offset}" ] && __cast_offset=${__l_offset}
 		__l_offset=$((__l_offset - __cast_offset))
-		printf '[%s.%s\n' "${__l_offset}" "${__l_rest}" >> "${__cast_name}".cast
+		printf '[%s.%s\n' "${__l_offset}" "${__l_rest}" >> "${LOGDIR}/${__cast_name}".cast
 	done
 	unset IFS
 }
-- 
@@ -77,8 +77,8 @@ video_start() {
 	VIDEO_START_SECONDS=$(sed -n 's/\([0-9]*\).[0-9]* [0-9]*.[0-9]*/\1/p' /proc/uptime)
 
 	sync
-	[ ${DEMO} -eq 1 ] && tail -1 "${BASEPATH}/demo.uncut" > "${BASEPATH}/${VIDEO_NAME}.start"
-	[ ${CI} -eq 1 ] && tail -1 "${BASEPATH}/ci.uncut" > "${BASEPATH}/${VIDEO_NAME}.start"
+	[ ${DEMO} -eq 1 ] && tail -1 "${STATEBASE}/demo.uncut" > "${STATEBASE}/${VIDEO_NAME}.start"
+	[ ${CI} -eq 1 ] && tail -1 "${STATEBASE}/ci.uncut" > "${STATEBASE}/${VIDEO_NAME}.start"
 	sync
 
 	tmux refresh-client
@@ -89,8 +89,8 @@ video_stop() {
 	tmux refresh-client
 
 	sync
-	[ ${DEMO} -eq 1 ] && tail -1 "${BASEPATH}/demo.uncut" > "${BASEPATH}/${VIDEO_NAME}.stop"
-	[ ${CI} -eq 1 ] && tail -1 "${BASEPATH}/ci.uncut" > "${BASEPATH}/${VIDEO_NAME}.stop"
+	[ ${DEMO} -eq 1 ] && tail -1 "${STATEBASE}/demo.uncut" > "${STATEBASE}/${VIDEO_NAME}.stop"
+	[ ${CI} -eq 1 ] && tail -1 "${STATEBASE}/ci.uncut" > "${STATEBASE}/${VIDEO_NAME}.stop"
 	sync
 
 	sed -i 's/^.*$/&\\/g' "${BASEPATH}/${VIDEO_NAME}.js"
@@ -108,12 +108,13 @@ video_postprocess() {
 		[ -z "${__header}" ] && __header="${__l}" && continue
 
 		if [ -z "${__cast_name}" ]; then
-			for __cast_cut in *.start; do
+		        for __cast_cut in "${STATEBASE}/"*.start; do
 				[ "${__l}" != "$(cat "${__cast_cut}")" ] && continue
-				__cast_name="${__cast_cut%.start}"
+				__cast_name="$(basename "${__cast_cut}")"
+                                __cast_name="${__cast_name%.start}"
 				__cast_offset=
-				__stop_line="$(cat ${__cast_name}.stop)"
-				echo "${__header}" > "${__cast_name}.cast"
+				__stop_line="$(cat "${STATEBASE}/${__cast_name}.stop")"
+				echo "${__header}" > "${LOGDIR}/${__cast_name}.cast"
 				break
 			done
 			continue
@@ -125,7 +126,7 @@ video_postprocess() {
 		__l_rest="${__l#*.}"
 		[ -z "${__cast_offset}" ] && __cast_offset=${__l_offset}
 		__l_offset=$((__l_offset - __cast_offset))
-		printf '[%s.%s\n' "${__l_offset}" "${__l_rest}" >> "${__cast_name}".cast
+		printf '[%s.%s\n' "${__l_offset}" "${__l_rest}" >> "${LOGDIR}/${__cast_name}".cast
 	done
 	unset IFS
 }
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2022-09-08  6:16 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-08  6:15 [PATCH v2 00/32] Improve handling of test temporary files David Gibson
2022-09-08  6:15 ` [PATCH v2 01/32] test: Correctly match "background" with "wait" commands David Gibson
2022-09-08  6:15 ` [PATCH v2 02/32] test: Context execution helpers David Gibson
2022-09-08  6:15 ` [PATCH v2 03/32] test: Allow a tmux pane to watch commands executed in contexts David Gibson
2022-09-08  6:15 ` [PATCH v2 04/32] test: Integration of old-style pane execution and new context execution David Gibson
2022-09-08  6:15 ` [PATCH v2 05/32] test: Issue host commands via context for most tests David Gibson
2022-09-08  6:15 ` [PATCH v2 06/32] test: Use new-style contexts for passt pane in the pasta and passt tests David Gibson
2022-09-08  6:15 ` [PATCH v2 07/32] test: Add nsholder utility David Gibson
2022-09-08  6:15 ` [PATCH v2 08/32] test: Extend context system to run commands in namespace for pasta tests David Gibson
2022-09-08  6:15 ` [PATCH v2 09/32] test: Use context system for guest commands David Gibson
2022-09-08  6:15 ` [PATCH v2 10/32] test: Use context system for two_guests tests David Gibson
2022-09-08  6:16 ` [PATCH v2 11/32] test: Use new-style command issue for passt_in_ns tests David Gibson
2022-09-08  6:16 ` [PATCH v2 12/32] Don't store UID & GID persistently in the context structure David Gibson
2022-09-08  6:16 ` [PATCH v2 13/32] Split checking for root from dropping root privilege David Gibson
2022-09-08  6:16 ` [PATCH v2 14/32] Consolidate determination of UID/GID to run as David Gibson
2022-09-08  6:16 ` [PATCH v2 15/32] Safer handling if we can't open /proc/self/uid_map David Gibson
2022-09-08  6:16 ` [PATCH v2 16/32] Move self-isolation code into a separate file David Gibson
2022-09-08  6:16 ` [PATCH v2 17/32] Consolidate validation of pasta namespace options David Gibson
2022-09-08  6:16 ` [PATCH v2 18/32] Clean up and rename conf_ns_open() David Gibson
2022-09-08  6:16 ` [PATCH v2 19/32] Correctly handle --netns-only in pasta_start_ns() David Gibson
2022-09-08  6:16 ` [PATCH v2 20/32] Handle userns isolation and dropping root at the same time David Gibson
2022-09-08  6:16 ` [PATCH v2 21/32] Allow --userns when pasta spawns a command David Gibson
2022-09-08  6:16 ` [PATCH v2 22/32] test: Group tests by context then protocol, rather than the reverse David Gibson
2022-09-08  6:16 ` [PATCH v2 23/32] test: Remove unused variable FFMPEG_PID_FILE David Gibson
2022-09-08  6:16 ` [PATCH v2 24/32] test: Actually run cleanup function David Gibson
2022-09-08  6:16 ` [PATCH v2 25/32] test: Create common state directories for temporary files David Gibson
2022-09-08  6:16 ` [PATCH v2 26/32] test: Move context temporary files to state dir David Gibson
2022-09-08  6:16 ` [PATCH v2 27/32] test: Dont regnerate small test file in pasta/tcp David Gibson
2022-09-08  6:16 ` [PATCH v2 28/32] test: Use paths in __STATEDIR__ instead of 'temp' and 'tempdir' directives David Gibson
2022-09-08  6:16 ` [PATCH v2 29/32] test: Move pause temporary file to state directory David Gibson
2022-09-08  6:16 ` [PATCH v2 30/32] test: Store pcap files in $LOGDIR instead of /tmp David Gibson
2022-09-08  6:16 ` [PATCH v2 31/32] test: Move pidfiles and nsholder sockets into state directory David Gibson
2022-09-08  6:16 ` [PATCH v2 32/32] test: Move video processing files to $STATEBASE David Gibson

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).