* [PATCH 01/14] nstool: Rename nsholder to nstool
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-04 1:46 ` [PATCH 02/14] nstool: Reverse parameters " David Gibson
` (13 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
In preparation for extending what it does.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/.gitignore | 2 +-
test/Makefile | 4 ++--
test/lib/setup | 30 +++++++++++++++---------------
test/{nsholder.c => nstool.c} | 20 ++++++++++----------
4 files changed, 28 insertions(+), 28 deletions(-)
rename test/{nsholder.c => nstool.c} (83%)
diff --git a/test/.gitignore b/test/.gitignore
index fbee491..4837402 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -6,6 +6,6 @@ QEMU_EFI.fd
*.raw
*.raw.xz
*.bin
-nsholder
+nstool
guest-key
guest-key.pub
diff --git a/test/Makefile b/test/Makefile
index 1341677..50d283e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -58,7 +58,7 @@ TESTDATA_ASSETS = small.bin big.bin medium.bin
LOCAL_ASSETS = mbuto.img mbuto.mem.img QEMU_EFI.fd \
$(DEBIAN_IMGS:%=prepared-%) $(FEDORA_IMGS:%=prepared-%) \
$(UBUNTU_NEW_IMGS:%=prepared-%) \
- nsholder guest-key guest-key.pub \
+ nstool guest-key guest-key.pub \
$(TESTDATA_ASSETS)
ASSETS = $(DOWNLOAD_ASSETS) $(LOCAL_ASSETS)
@@ -79,7 +79,7 @@ mbuto.img: passt.mbuto mbuto guest-key.pub $(TESTDATA_ASSETS)
mbuto.mem.img: passt.mem.mbuto mbuto ../passt.avx2
./mbuto/mbuto -p ./$< -c lz4 -f $@
-nsholder: nsholder.c
+nstool: nstool.c
$(CC) $(CFLAGS) -o $@ $^
QEMU_EFI.fd:
diff --git a/test/lib/setup b/test/lib/setup
index 5f8ce26..3bd434b 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -17,7 +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"
+NSTOOL="${BASEPATH}/nstool"
# setup_build() - Set up pane layout for build tests
setup_build() {
@@ -77,8 +77,8 @@ setup_pasta() {
layout_pasta
- context_run_bg unshare "unshare -rUnpf ${NSHOLDER} ${STATESETUP}/ns.hold hold"
- __target_pid=$(${NSHOLDER} ${STATESETUP}/ns.hold pid)
+ context_run_bg unshare "unshare -rUnpf ${NSTOOL} ${STATESETUP}/ns.hold hold"
+ __target_pid=$(${NSTOOL} ${STATESETUP}/ns.hold pid)
context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
@@ -126,9 +126,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 ${STATESETUP}/pasta.pid --config-net ${NSHOLDER} ${STATESETUP}/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 --config-net ${NSTOOL} ${STATESETUP}/ns.hold hold"
wait_for [ -f "${STATESETUP}/pasta.pid" ]
- __ns_pid=$(${NSHOLDER} ${STATESETUP}/ns.hold pid)
+ __ns_pid=$(${NSTOOL} ${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"
@@ -189,16 +189,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} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSHOLDER} ${STATESETUP}/ns1.hold hold"
- __ns1_pid=$(${NSHOLDER} ${STATESETUP}/ns1.hold pid)
+ context_run_bg pasta_1 "./pasta ${__opts} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} ${STATESETUP}/ns1.hold hold"
+ __ns1_pid=$(${NSTOOL} ${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} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSHOLDER} ${STATESETUP}/ns2.hold hold"
- __ns2_pid=$(${NSHOLDER} ${STATESETUP}/ns2.hold pid)
+ context_run_bg pasta_2 "./pasta ${__opts} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} ${STATESETUP}/ns2.hold hold"
+ __ns2_pid=$(${NSTOOL} ${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}
@@ -284,7 +284,7 @@ teardown_passt() {
# teardown_pasta() - Exit namespace, kill pasta process
teardown_pasta() {
- ${NSHOLDER} "${STATESETUP}/ns.hold" stop
+ ${NSTOOL} "${STATESETUP}/ns.hold" stop
context_wait unshare
teardown_context_watch ${PANE_HOST} host
@@ -297,7 +297,7 @@ teardown_passt_in_ns() {
context_run ns kill $(cat "${STATESETUP}/qemu.pid")
context_wait qemu
- ${NSHOLDER} "${STATESETUP}/ns.hold" stop
+ ${NSTOOL} "${STATESETUP}/ns.hold" stop
context_wait pasta
rm "${STATESETUP}/passt.pid" "${STATESETUP}/pasta.pid"
@@ -310,8 +310,8 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- __ns1_pid=$(${NSHOLDER} "${STATESETUP}/ns1.hold" pid)
- __ns2_pid=$(${NSHOLDER} "${STATESETUP}/ns2.hold" pid)
+ __ns1_pid=$(${NSTOOL} "${STATESETUP}/ns1.hold" pid)
+ __ns2_pid=$(${NSTOOL} "${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
@@ -321,8 +321,8 @@ teardown_two_guests() {
nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat "${STATESETUP}/passt_2.pid")
context_wait passt_1
context_wait passt_2
- ${NSHOLDER} "${STATESETUP}/ns1.hold" stop
- ${NSHOLDER} "${STATESETUP}/ns2.hold" stop
+ ${NSTOOL} "${STATESETUP}/ns1.hold" stop
+ ${NSTOOL} "${STATESETUP}/ns2.hold" stop
context_wait pasta_1
context_wait pasta_2
diff --git a/test/nsholder.c b/test/nstool.c
similarity index 83%
rename from test/nsholder.c
rename to test/nstool.c
index 010a051..4ae0f85 100644
--- a/test/nsholder.c
+++ b/test/nstool.c
@@ -1,23 +1,23 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
-/* nsholder - maintain a namespace to be entered by other processes
+/* nstool - maintain a namespace to be entered by other processes
*
* Copyright Red Hat
* Author: David Gibson <david@gibson.dropbear.id.au>
*
* Can run in 3 modes:
*
- * nsholder <path> hold
+ * nstool <path> hold
* Designed to be run inside a namespace, opens a Unix domain
* control socket at <path> and waits until instructed to stop
- * with "nsholder <path> stop"
- * nsholder <path> pid
- * Prints the PID of the nsholder hold process with control
+ * with "nstool <path> stop"
+ * nstool <path> pid
+ * Prints the PID of the nstool hold process with control
* socket <path>. This is given in the PID namespace where
- * nsholder pid is executed, not the one where nsholder hold is
+ * nstool pid is executed, not the one where nstool hold is
* running
- * nsholder <path> stop
- * Instruct the nsholder hold with control socket at <path> to exit.
+ * nstool <path> stop
+ * Instruct the nstool hold with control socket at <path> to exit.
*/
#define _GNU_SOURCE
@@ -38,7 +38,7 @@
static void usage(void)
{
- die("Usage: holder <socket path> hold|pid\n");
+ die("Usage: nstool <socket path> hold|pid\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
@@ -53,7 +53,7 @@ static void hold(int fd, const struct sockaddr_un *addr)
if (rc < 0)
die("listen(): %s\n", strerror(errno));
- printf("nsholder: local PID=%d local UID=%u local GID=%u\n",
+ printf("nstool: local PID=%d local UID=%u local GID=%u\n",
getpid(), getuid(), getgid());
do {
int afd = accept(fd, NULL, NULL);
--
@@ -1,23 +1,23 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
-/* nsholder - maintain a namespace to be entered by other processes
+/* nstool - maintain a namespace to be entered by other processes
*
* Copyright Red Hat
* Author: David Gibson <david@gibson.dropbear.id.au>
*
* Can run in 3 modes:
*
- * nsholder <path> hold
+ * nstool <path> hold
* Designed to be run inside a namespace, opens a Unix domain
* control socket at <path> and waits until instructed to stop
- * with "nsholder <path> stop"
- * nsholder <path> pid
- * Prints the PID of the nsholder hold process with control
+ * with "nstool <path> stop"
+ * nstool <path> pid
+ * Prints the PID of the nstool hold process with control
* socket <path>. This is given in the PID namespace where
- * nsholder pid is executed, not the one where nsholder hold is
+ * nstool pid is executed, not the one where nstool hold is
* running
- * nsholder <path> stop
- * Instruct the nsholder hold with control socket at <path> to exit.
+ * nstool <path> stop
+ * Instruct the nstool hold with control socket at <path> to exit.
*/
#define _GNU_SOURCE
@@ -38,7 +38,7 @@
static void usage(void)
{
- die("Usage: holder <socket path> hold|pid\n");
+ die("Usage: nstool <socket path> hold|pid\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
@@ -53,7 +53,7 @@ static void hold(int fd, const struct sockaddr_un *addr)
if (rc < 0)
die("listen(): %s\n", strerror(errno));
- printf("nsholder: local PID=%d local UID=%u local GID=%u\n",
+ printf("nstool: local PID=%d local UID=%u local GID=%u\n",
getpid(), getuid(), getgid());
do {
int afd = accept(fd, NULL, NULL);
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 02/14] nstool: Reverse parameters to nstool
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
2023-04-04 1:46 ` [PATCH 01/14] nstool: Rename nsholder to nstool David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-04 1:46 ` [PATCH 03/14] nstool: Move description of its operation modes from comment to usage David Gibson
` (12 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Having the "subcommand" first is more conventional and will make it more
natural for future extensions I have planned.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/lib/setup | 28 ++++++++++++++--------------
test/nstool.c | 28 ++++++++++++++--------------
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/test/lib/setup b/test/lib/setup
index 3bd434b..e6180b1 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -77,8 +77,8 @@ setup_pasta() {
layout_pasta
- context_run_bg unshare "unshare -rUnpf ${NSTOOL} ${STATESETUP}/ns.hold hold"
- __target_pid=$(${NSTOOL} ${STATESETUP}/ns.hold pid)
+ context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
+ __target_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
@@ -126,9 +126,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 ${STATESETUP}/pasta.pid --config-net ${NSTOOL} ${STATESETUP}/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 --config-net ${NSTOOL} hold ${STATESETUP}/ns.hold"
wait_for [ -f "${STATESETUP}/pasta.pid" ]
- __ns_pid=$(${NSTOOL} ${STATESETUP}/ns.hold pid)
+ __ns_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
context_setup_nsenter qemu "-t ${__ns_pid} -U -n -p --preserve-credentials"
context_setup_nsenter ns "-t ${__ns_pid} -U -n -p --preserve-credentials"
@@ -189,16 +189,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} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} ${STATESETUP}/ns1.hold hold"
- __ns1_pid=$(${NSTOOL} ${STATESETUP}/ns1.hold pid)
+ context_run_bg pasta_1 "./pasta ${__opts} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} hold ${STATESETUP}/ns1.hold"
+ __ns1_pid=$(${NSTOOL} pid ${STATESETUP}/ns1.hold)
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} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} ${STATESETUP}/ns2.hold hold"
- __ns2_pid=$(${NSTOOL} ${STATESETUP}/ns2.hold pid)
+ context_run_bg pasta_2 "./pasta ${__opts} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} hold ${STATESETUP}/ns2.hold"
+ __ns2_pid=$(${NSTOOL} pid ${STATESETUP}/ns2.hold)
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}
@@ -284,7 +284,7 @@ teardown_passt() {
# teardown_pasta() - Exit namespace, kill pasta process
teardown_pasta() {
- ${NSTOOL} "${STATESETUP}/ns.hold" stop
+ ${NSTOOL} stop "${STATESETUP}/ns.hold"
context_wait unshare
teardown_context_watch ${PANE_HOST} host
@@ -297,7 +297,7 @@ teardown_passt_in_ns() {
context_run ns kill $(cat "${STATESETUP}/qemu.pid")
context_wait qemu
- ${NSTOOL} "${STATESETUP}/ns.hold" stop
+ ${NSTOOL} stop "${STATESETUP}/ns.hold"
context_wait pasta
rm "${STATESETUP}/passt.pid" "${STATESETUP}/pasta.pid"
@@ -310,8 +310,8 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- __ns1_pid=$(${NSTOOL} "${STATESETUP}/ns1.hold" pid)
- __ns2_pid=$(${NSTOOL} "${STATESETUP}/ns2.hold" pid)
+ __ns1_pid=$(${NSTOOL} pid "${STATESETUP}/ns1.hold")
+ __ns2_pid=$(${NSTOOL} pid "${STATESETUP}/ns2.hold")
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
@@ -321,8 +321,8 @@ teardown_two_guests() {
nsenter -U -p --preserve-credentials -t ${__ns2_pid} kill $(cat "${STATESETUP}/passt_2.pid")
context_wait passt_1
context_wait passt_2
- ${NSTOOL} "${STATESETUP}/ns1.hold" stop
- ${NSTOOL} "${STATESETUP}/ns2.hold" stop
+ ${NSTOOL} stop "${STATESETUP}/ns1.hold"
+ ${NSTOOL} stop "${STATESETUP}/ns2.hold"
context_wait pasta_1
context_wait pasta_2
diff --git a/test/nstool.c b/test/nstool.c
index 4ae0f85..cc6d617 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -7,17 +7,17 @@
*
* Can run in 3 modes:
*
- * nstool <path> hold
+ * nstool hold <path>
* Designed to be run inside a namespace, opens a Unix domain
* control socket at <path> and waits until instructed to stop
- * with "nstool <path> stop"
- * nstool <path> pid
- * Prints the PID of the nstool hold process with control
- * socket <path>. This is given in the PID namespace where
- * nstool pid is executed, not the one where nstool hold is
- * running
- * nstool <path> stop
- * Instruct the nstool hold with control socket at <path> to exit.
+ * with "nstool stop <path>"
+ * nstool pid <path>
+ * Prints the PID of the nstool hold process with control socket
+ * <path>. This is given in the PID namespace where nstool pid
+ * is executed, not the one where nstool hold is running
+ * nstool stop <path>
+ * Instruct the nstool hold with control socket at <path> to
+ * exit.
*/
#define _GNU_SOURCE
@@ -38,7 +38,7 @@
static void usage(void)
{
- die("Usage: nstool <socket path> hold|pid\n");
+ die("Usage: nstool hold|pid|stop <socket path>\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
@@ -119,18 +119,18 @@ int main(int argc, char *argv[])
if (argc != 3)
usage();
- sockname = argv[1];
+ sockname = argv[2];
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)
+ if (strcmp(argv[1], "hold") == 0)
hold(fd, &sockaddr);
- else if (strcmp(argv[2], "pid") == 0)
+ else if (strcmp(argv[1], "pid") == 0)
pid(fd, &sockaddr);
- else if (strcmp(argv[2], "stop") == 0)
+ else if (strcmp(argv[1], "stop") == 0)
stop(fd, &sockaddr);
else
usage();
--
@@ -7,17 +7,17 @@
*
* Can run in 3 modes:
*
- * nstool <path> hold
+ * nstool hold <path>
* Designed to be run inside a namespace, opens a Unix domain
* control socket at <path> and waits until instructed to stop
- * with "nstool <path> stop"
- * nstool <path> pid
- * Prints the PID of the nstool hold process with control
- * socket <path>. This is given in the PID namespace where
- * nstool pid is executed, not the one where nstool hold is
- * running
- * nstool <path> stop
- * Instruct the nstool hold with control socket at <path> to exit.
+ * with "nstool stop <path>"
+ * nstool pid <path>
+ * Prints the PID of the nstool hold process with control socket
+ * <path>. This is given in the PID namespace where nstool pid
+ * is executed, not the one where nstool hold is running
+ * nstool stop <path>
+ * Instruct the nstool hold with control socket at <path> to
+ * exit.
*/
#define _GNU_SOURCE
@@ -38,7 +38,7 @@
static void usage(void)
{
- die("Usage: nstool <socket path> hold|pid\n");
+ die("Usage: nstool hold|pid|stop <socket path>\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
@@ -119,18 +119,18 @@ int main(int argc, char *argv[])
if (argc != 3)
usage();
- sockname = argv[1];
+ sockname = argv[2];
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)
+ if (strcmp(argv[1], "hold") == 0)
hold(fd, &sockaddr);
- else if (strcmp(argv[2], "pid") == 0)
+ else if (strcmp(argv[1], "pid") == 0)
pid(fd, &sockaddr);
- else if (strcmp(argv[2], "stop") == 0)
+ else if (strcmp(argv[1], "stop") == 0)
stop(fd, &sockaddr);
else
usage();
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 03/14] nstool: Move description of its operation modes from comment to usage
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
2023-04-04 1:46 ` [PATCH 01/14] nstool: Rename nsholder to nstool David Gibson
2023-04-04 1:46 ` [PATCH 02/14] nstool: Reverse parameters " David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:56 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands David Gibson
` (11 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Easier to see it there.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index cc6d617..7e069b6 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -4,20 +4,6 @@
*
* Copyright Red Hat
* Author: David Gibson <david@gibson.dropbear.id.au>
- *
- * Can run in 3 modes:
- *
- * nstool hold <path>
- * Designed to be run inside a namespace, opens a Unix domain
- * control socket at <path> and waits until instructed to stop
- * with "nstool stop <path>"
- * nstool pid <path>
- * Prints the PID of the nstool hold process with control socket
- * <path>. This is given in the PID namespace where nstool pid
- * is executed, not the one where nstool hold is running
- * nstool stop <path>
- * Instruct the nstool hold with control socket at <path> to
- * exit.
*/
#define _GNU_SOURCE
@@ -38,7 +24,17 @@
static void usage(void)
{
- die("Usage: nstool hold|pid|stop <socket path>\n");
+ die("Usage:\n"
+ " nstool hold SOCK\n"
+ " Run within a set of namespaces, open a Unix domain control\n"
+ " socket at SOCK and wait for requests from other nstool\n"
+ " subcommands.\n"
+ " nstool pid SOCK\n"
+ " Print the pid of the nstool hold process with control socket\n"
+ " at SOCK, as seen in the caller's namespace.\n"
+ " nstool stop SOCK\n"
+ " Instruct the nstool hold with control socket at SOCK to\n"
+ " terminate.\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
--
@@ -4,20 +4,6 @@
*
* Copyright Red Hat
* Author: David Gibson <david@gibson.dropbear.id.au>
- *
- * Can run in 3 modes:
- *
- * nstool hold <path>
- * Designed to be run inside a namespace, opens a Unix domain
- * control socket at <path> and waits until instructed to stop
- * with "nstool stop <path>"
- * nstool pid <path>
- * Prints the PID of the nstool hold process with control socket
- * <path>. This is given in the PID namespace where nstool pid
- * is executed, not the one where nstool hold is running
- * nstool stop <path>
- * Instruct the nstool hold with control socket at <path> to
- * exit.
*/
#define _GNU_SOURCE
@@ -38,7 +24,17 @@
static void usage(void)
{
- die("Usage: nstool hold|pid|stop <socket path>\n");
+ die("Usage:\n"
+ " nstool hold SOCK\n"
+ " Run within a set of namespaces, open a Unix domain control\n"
+ " socket at SOCK and wait for requests from other nstool\n"
+ " subcommands.\n"
+ " nstool pid SOCK\n"
+ " Print the pid of the nstool hold process with control socket\n"
+ " at SOCK, as seen in the caller's namespace.\n"
+ " nstool stop SOCK\n"
+ " Instruct the nstool hold with control socket at SOCK to\n"
+ " terminate.\n");
}
static void hold(int fd, const struct sockaddr_un *addr)
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 03/14] nstool: Move description of its operation modes from comment to usage
2023-04-04 1:46 ` [PATCH 03/14] nstool: Move description of its operation modes from comment to usage David Gibson
@ 2023-04-05 11:56 ` Stefano Brivio
2023-04-06 0:10 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:56 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:27 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> Easier to see it there.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 26 +++++++++++---------------
> 1 file changed, 11 insertions(+), 15 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index cc6d617..7e069b6 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -4,20 +4,6 @@
> *
> * Copyright Red Hat
> * Author: David Gibson <david@gibson.dropbear.id.au>
> - *
> - * Can run in 3 modes:
> - *
> - * nstool hold <path>
> - * Designed to be run inside a namespace, opens a Unix domain
> - * control socket at <path> and waits until instructed to stop
> - * with "nstool stop <path>"
> - * nstool pid <path>
> - * Prints the PID of the nstool hold process with control socket
> - * <path>. This is given in the PID namespace where nstool pid
> - * is executed, not the one where nstool hold is running
> - * nstool stop <path>
> - * Instruct the nstool hold with control socket at <path> to
> - * exit.
> */
>
> #define _GNU_SOURCE
> @@ -38,7 +24,17 @@
>
> static void usage(void)
> {
> - die("Usage: nstool hold|pid|stop <socket path>\n");
> + die("Usage:\n"
> + " nstool hold SOCK\n"
> + " Run within a set of namespaces, open a Unix domain control\n"
UNIX domain socket
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 03/14] nstool: Move description of its operation modes from comment to usage
2023-04-05 11:56 ` Stefano Brivio
@ 2023-04-06 0:10 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:10 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 1806 bytes --]
On Wed, Apr 05, 2023 at 01:56:59PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:27 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > Easier to see it there.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 26 +++++++++++---------------
> > 1 file changed, 11 insertions(+), 15 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index cc6d617..7e069b6 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -4,20 +4,6 @@
> > *
> > * Copyright Red Hat
> > * Author: David Gibson <david@gibson.dropbear.id.au>
> > - *
> > - * Can run in 3 modes:
> > - *
> > - * nstool hold <path>
> > - * Designed to be run inside a namespace, opens a Unix domain
> > - * control socket at <path> and waits until instructed to stop
> > - * with "nstool stop <path>"
> > - * nstool pid <path>
> > - * Prints the PID of the nstool hold process with control socket
> > - * <path>. This is given in the PID namespace where nstool pid
> > - * is executed, not the one where nstool hold is running
> > - * nstool stop <path>
> > - * Instruct the nstool hold with control socket at <path> to
> > - * exit.
> > */
> >
> > #define _GNU_SOURCE
> > @@ -38,7 +24,17 @@
> >
> > static void usage(void)
> > {
> > - die("Usage: nstool hold|pid|stop <socket path>\n");
> > + die("Usage:\n"
> > + " nstool hold SOCK\n"
> > + " Run within a set of namespaces, open a Unix domain control\n"
>
> UNIX domain socket
Adjusted.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (2 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 03/14] nstool: Move description of its operation modes from comment to usage David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand David Gibson
` (10 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
This will make it easier to differentiate the options to those commands
further in future.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 102 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 68 insertions(+), 34 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index 7e069b6..9ea7eeb 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
@@ -37,19 +38,55 @@ static void usage(void)
" terminate.\n");
}
-static void hold(int fd, const struct sockaddr_un *addr)
+static int connect_ctl(const char * sockpath, bool wait)
{
+ int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ struct sockaddr_un addr = {
+ .sun_family = AF_UNIX,
+ };
int rc;
- rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
+
+ do {
+ rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+ if (rc < 0 &&
+ (!wait || (errno != ENOENT && errno != ECONNREFUSED)))
+ die("connect() to %s: %s\n", sockpath, strerror(errno));
+ } while (rc < 0);
+
+ return fd;
+}
+
+static void cmd_hold(int argc, char *argv[])
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ struct sockaddr_un addr = {
+ .sun_family = AF_UNIX,
+ };
+ const char *sockpath = argv[1];
+ int rc;
+
+ if (argc != 2)
+ usage();
+
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
+
+ rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (rc < 0)
- die("bind(): %s\n", strerror(errno));
+ die("bind() to %s: %s\n", sockpath, strerror(errno));
rc = listen(fd, 0);
if (rc < 0)
- die("listen(): %s\n", strerror(errno));
+ die("listen() on %s: %s\n", sockpath, strerror(errno));
- printf("nstool: local PID=%d local UID=%u local GID=%u\n",
+ printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
getpid(), getuid(), getgid());
do {
int afd = accept(fd, NULL, NULL);
@@ -63,71 +100,68 @@ static void hold(int fd, const struct sockaddr_un *addr)
die("read(): %s\n", strerror(errno));
} while (rc == 0);
- unlink(addr->sun_path);
+ unlink(sockpath);
}
-static void pid(int fd, const struct sockaddr_un *addr)
+static void cmd_pid(int argc, char *argv[])
{
- int rc;
+ const char *sockpath = argv[1];
struct ucred peercred;
socklen_t optlen = sizeof(peercred);
+ int fd, rc;
- 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);
+ if (argc != 2)
+ usage();
+
+ fd = connect_ctl(sockpath, true);
rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
&peercred, &optlen);
if (rc < 0)
- die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+ die("getsockopet(SO_PEERCRED) %s: %s\n",
+ sockpath, strerror(errno));
close(fd);
printf("%d\n", peercred.pid);
}
-static void stop(int fd, const struct sockaddr_un *addr)
+static void cmd_stop(int argc, char *argv[])
{
- int rc;
+ const char *sockpath = argv[1];
+ int fd, rc;
char buf = 'Q';
- rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
- if (rc < 0)
- die("connect(): %s\n", strerror(errno));
+ if (argc != 2)
+ usage();
+
+ fd = connect_ctl(sockpath, false);
rc = write(fd, &buf, sizeof(buf));
if (rc < 0)
- die("write(): %s\n", strerror(errno));
+ die("write() to %s: %s\n", sockpath, strerror(errno));
close(fd);
}
int main(int argc, char *argv[])
{
+ const char *subcmd = argv[1];
int fd;
- const char *sockname;
- struct sockaddr_un sockaddr = {
- .sun_family = AF_UNIX,
- };
- if (argc != 3)
+ if (argc < 2)
usage();
- sockname = argv[2];
- 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[1], "hold") == 0)
- hold(fd, &sockaddr);
- else if (strcmp(argv[1], "pid") == 0)
- pid(fd, &sockaddr);
- else if (strcmp(argv[1], "stop") == 0)
- stop(fd, &sockaddr);
+ if (strcmp(subcmd, "hold") == 0)
+ cmd_hold(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "pid") == 0)
+ cmd_pid(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "stop") == 0)
+ cmd_stop(argc - 1, argv + 1);
else
usage();
--
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
@@ -37,19 +38,55 @@ static void usage(void)
" terminate.\n");
}
-static void hold(int fd, const struct sockaddr_un *addr)
+static int connect_ctl(const char * sockpath, bool wait)
{
+ int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ struct sockaddr_un addr = {
+ .sun_family = AF_UNIX,
+ };
int rc;
- rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
+
+ do {
+ rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
+ if (rc < 0 &&
+ (!wait || (errno != ENOENT && errno != ECONNREFUSED)))
+ die("connect() to %s: %s\n", sockpath, strerror(errno));
+ } while (rc < 0);
+
+ return fd;
+}
+
+static void cmd_hold(int argc, char *argv[])
+{
+ int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ struct sockaddr_un addr = {
+ .sun_family = AF_UNIX,
+ };
+ const char *sockpath = argv[1];
+ int rc;
+
+ if (argc != 2)
+ usage();
+
+ if (fd < 0)
+ die("socket(): %s\n", strerror(errno));
+
+ strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
+
+ rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
if (rc < 0)
- die("bind(): %s\n", strerror(errno));
+ die("bind() to %s: %s\n", sockpath, strerror(errno));
rc = listen(fd, 0);
if (rc < 0)
- die("listen(): %s\n", strerror(errno));
+ die("listen() on %s: %s\n", sockpath, strerror(errno));
- printf("nstool: local PID=%d local UID=%u local GID=%u\n",
+ printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
getpid(), getuid(), getgid());
do {
int afd = accept(fd, NULL, NULL);
@@ -63,71 +100,68 @@ static void hold(int fd, const struct sockaddr_un *addr)
die("read(): %s\n", strerror(errno));
} while (rc == 0);
- unlink(addr->sun_path);
+ unlink(sockpath);
}
-static void pid(int fd, const struct sockaddr_un *addr)
+static void cmd_pid(int argc, char *argv[])
{
- int rc;
+ const char *sockpath = argv[1];
struct ucred peercred;
socklen_t optlen = sizeof(peercred);
+ int fd, rc;
- 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);
+ if (argc != 2)
+ usage();
+
+ fd = connect_ctl(sockpath, true);
rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
&peercred, &optlen);
if (rc < 0)
- die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
+ die("getsockopet(SO_PEERCRED) %s: %s\n",
+ sockpath, strerror(errno));
close(fd);
printf("%d\n", peercred.pid);
}
-static void stop(int fd, const struct sockaddr_un *addr)
+static void cmd_stop(int argc, char *argv[])
{
- int rc;
+ const char *sockpath = argv[1];
+ int fd, rc;
char buf = 'Q';
- rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
- if (rc < 0)
- die("connect(): %s\n", strerror(errno));
+ if (argc != 2)
+ usage();
+
+ fd = connect_ctl(sockpath, false);
rc = write(fd, &buf, sizeof(buf));
if (rc < 0)
- die("write(): %s\n", strerror(errno));
+ die("write() to %s: %s\n", sockpath, strerror(errno));
close(fd);
}
int main(int argc, char *argv[])
{
+ const char *subcmd = argv[1];
int fd;
- const char *sockname;
- struct sockaddr_un sockaddr = {
- .sun_family = AF_UNIX,
- };
- if (argc != 3)
+ if (argc < 2)
usage();
- sockname = argv[2];
- 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[1], "hold") == 0)
- hold(fd, &sockaddr);
- else if (strcmp(argv[1], "pid") == 0)
- pid(fd, &sockaddr);
- else if (strcmp(argv[1], "stop") == 0)
- stop(fd, &sockaddr);
+ if (strcmp(subcmd, "hold") == 0)
+ cmd_hold(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "pid") == 0)
+ cmd_pid(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "stop") == 0)
+ cmd_stop(argc - 1, argv + 1);
else
usage();
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands
2023-04-04 1:46 ` [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 2:31 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:28 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> This will make it easier to differentiate the options to those commands
> further in future.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 102 +++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 68 insertions(+), 34 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index 7e069b6..9ea7eeb 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -11,6 +11,7 @@
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> +#include <stdbool.h>
> #include <errno.h>
> #include <unistd.h>
> #include <sys/socket.h>
> @@ -37,19 +38,55 @@ static void usage(void)
> " terminate.\n");
> }
>
> -static void hold(int fd, const struct sockaddr_un *addr)
> +static int connect_ctl(const char * sockpath, bool wait)
> {
> + int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> + struct sockaddr_un addr = {
> + .sun_family = AF_UNIX,
> + };
> int rc;
>
> - rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
> + if (fd < 0)
> + die("socket(): %s\n", strerror(errno));
Unrelated: it would be nice if die() added newlines eventually.
> +
> + strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
> +
> + do {
> + rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
> + if (rc < 0 &&
> + (!wait || (errno != ENOENT && errno != ECONNREFUSED)))
> + die("connect() to %s: %s\n", sockpath, strerror(errno));
A (1ms?) delay would be nice to have here -- it's almost a busyloop,
connect() fails fast.
> + } while (rc < 0);
> +
> + return fd;
> +}
> +
> +static void cmd_hold(int argc, char *argv[])
> +{
> + int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> + struct sockaddr_un addr = {
> + .sun_family = AF_UNIX,
> + };
> + const char *sockpath = argv[1];
> + int rc;
> +
> + if (argc != 2)
> + usage();
> +
> + if (fd < 0)
> + die("socket(): %s\n", strerror(errno));
> +
> + strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
> +
> + rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
> if (rc < 0)
> - die("bind(): %s\n", strerror(errno));
> + die("bind() to %s: %s\n", sockpath, strerror(errno));
>
> rc = listen(fd, 0);
> if (rc < 0)
> - die("listen(): %s\n", strerror(errno));
> + die("listen() on %s: %s\n", sockpath, strerror(errno));
>
> - printf("nstool: local PID=%d local UID=%u local GID=%u\n",
> + printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
> getpid(), getuid(), getgid());
> do {
> int afd = accept(fd, NULL, NULL);
> @@ -63,71 +100,68 @@ static void hold(int fd, const struct sockaddr_un *addr)
> die("read(): %s\n", strerror(errno));
> } while (rc == 0);
>
> - unlink(addr->sun_path);
> + unlink(sockpath);
> }
>
> -static void pid(int fd, const struct sockaddr_un *addr)
> +static void cmd_pid(int argc, char *argv[])
> {
> - int rc;
> + const char *sockpath = argv[1];
> struct ucred peercred;
> socklen_t optlen = sizeof(peercred);
> + int fd, rc;
>
> - 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);
> + if (argc != 2)
> + usage();
> +
> + fd = connect_ctl(sockpath, true);
I didn't spot this earlier, but... does it really make sense to wait in
cmd_pid(), also on ENOENT, rather than making 'hold' return only once
the socket is ready? I don't think it would be outrageous to have
'nstool pid' failing if the holding process doesn't exist.
Admittely, I'm biased by the few hundreds of times I needed to
'killall -9 nsholder' in the past months. :)
>
> rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
> &peercred, &optlen);
> if (rc < 0)
> - die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
> + die("getsockopet(SO_PEERCRED) %s: %s\n",
> + sockpath, strerror(errno));
>
> close(fd);
>
> printf("%d\n", peercred.pid);
> }
>
> -static void stop(int fd, const struct sockaddr_un *addr)
> +static void cmd_stop(int argc, char *argv[])
> {
> - int rc;
> + const char *sockpath = argv[1];
> + int fd, rc;
> char buf = 'Q';
>
> - rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
> - if (rc < 0)
> - die("connect(): %s\n", strerror(errno));
> + if (argc != 2)
> + usage();
> +
> + fd = connect_ctl(sockpath, false);
>
> rc = write(fd, &buf, sizeof(buf));
Unrelated: a compound literal would make this more readable.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 2:31 ` David Gibson
2023-04-06 6:47 ` Stefano Brivio
0 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-06 2:31 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 6215 bytes --]
On Wed, Apr 05, 2023 at 01:58:00PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:28 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > This will make it easier to differentiate the options to those commands
> > further in future.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 102 +++++++++++++++++++++++++++++++++-----------------
> > 1 file changed, 68 insertions(+), 34 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index 7e069b6..9ea7eeb 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -11,6 +11,7 @@
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <string.h>
> > +#include <stdbool.h>
> > #include <errno.h>
> > #include <unistd.h>
> > #include <sys/socket.h>
> > @@ -37,19 +38,55 @@ static void usage(void)
> > " terminate.\n");
> > }
> >
> > -static void hold(int fd, const struct sockaddr_un *addr)
> > +static int connect_ctl(const char * sockpath, bool wait)
> > {
> > + int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> > + struct sockaddr_un addr = {
> > + .sun_family = AF_UNIX,
> > + };
> > int rc;
> >
> > - rc = bind(fd, (struct sockaddr *)addr, sizeof(*addr));
> > + if (fd < 0)
> > + die("socket(): %s\n", strerror(errno));
>
> Unrelated: it would be nice if die() added newlines eventually.
Sure, but as you say unrelated.
> > +
> > + strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
> > +
> > + do {
> > + rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
> > + if (rc < 0 &&
> > + (!wait || (errno != ENOENT && errno != ECONNREFUSED)))
> > + die("connect() to %s: %s\n", sockpath, strerror(errno));
>
> A (1ms?) delay would be nice to have here -- it's almost a busyloop,
> connect() fails fast.
Yeah, I guess so. That's not new, it was already like that in
"nsholder pid", so I think something to fix separately.
> > + } while (rc < 0);
> > +
> > + return fd;
> > +}
> > +
> > +static void cmd_hold(int argc, char *argv[])
> > +{
> > + int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> > + struct sockaddr_un addr = {
> > + .sun_family = AF_UNIX,
> > + };
> > + const char *sockpath = argv[1];
> > + int rc;
> > +
> > + if (argc != 2)
> > + usage();
> > +
> > + if (fd < 0)
> > + die("socket(): %s\n", strerror(errno));
> > +
> > + strncpy(addr.sun_path, sockpath, UNIX_PATH_MAX);
> > +
> > + rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
> > if (rc < 0)
> > - die("bind(): %s\n", strerror(errno));
> > + die("bind() to %s: %s\n", sockpath, strerror(errno));
> >
> > rc = listen(fd, 0);
> > if (rc < 0)
> > - die("listen(): %s\n", strerror(errno));
> > + die("listen() on %s: %s\n", sockpath, strerror(errno));
> >
> > - printf("nstool: local PID=%d local UID=%u local GID=%u\n",
> > + printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
> > getpid(), getuid(), getgid());
> > do {
> > int afd = accept(fd, NULL, NULL);
> > @@ -63,71 +100,68 @@ static void hold(int fd, const struct sockaddr_un *addr)
> > die("read(): %s\n", strerror(errno));
> > } while (rc == 0);
> >
> > - unlink(addr->sun_path);
> > + unlink(sockpath);
> > }
> >
> > -static void pid(int fd, const struct sockaddr_un *addr)
> > +static void cmd_pid(int argc, char *argv[])
> > {
> > - int rc;
> > + const char *sockpath = argv[1];
> > struct ucred peercred;
> > socklen_t optlen = sizeof(peercred);
> > + int fd, rc;
> >
> > - 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);
> > + if (argc != 2)
> > + usage();
> > +
> > + fd = connect_ctl(sockpath, true);
>
> I didn't spot this earlier, but... does it really make sense to wait in
> cmd_pid(), also on ENOENT, rather than making 'hold' return only once
> the socket is ready?
So, this is a consequence of the fact that the holder doesn't move
into the background itself - it just sits in the foreground until
terminated. That means that the typical usecase puts it into the
background from the shell with &, which in turn means that when we
reach the next shell command the socket may not be ready - or not even
created.
One of the things I had in mind for a hypothetical "nstool unshare"
would be to avoid this and have it background itself once the socket
is ready.
> I don't think it would be outrageous to have
> 'nstool pid' failing if the holding process doesn't exist.
>
> Admittely, I'm biased by the few hundreds of times I needed to
> 'killall -9 nsholder' in the past months. :)
So... I agree that's irritating, I've done it a similar number of
times. However, I don't think that's really related to the question
above - in my experience it's always been the holder process that's
hung around, not something waiting on a holder.
> > rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
> > &peercred, &optlen);
> > if (rc < 0)
> > - die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
> > + die("getsockopet(SO_PEERCRED) %s: %s\n",
> > + sockpath, strerror(errno));
> >
> > close(fd);
> >
> > printf("%d\n", peercred.pid);
> > }
> >
> > -static void stop(int fd, const struct sockaddr_un *addr)
> > +static void cmd_stop(int argc, char *argv[])
> > {
> > - int rc;
> > + const char *sockpath = argv[1];
> > + int fd, rc;
> > char buf = 'Q';
> >
> > - rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
> > - if (rc < 0)
> > - die("connect(): %s\n", strerror(errno));
> > + if (argc != 2)
> > + usage();
> > +
> > + fd = connect_ctl(sockpath, false);
> >
> > rc = write(fd, &buf, sizeof(buf));
>
> Unrelated: a compound literal would make this more readable.
Uh.. I don't see where a compound literal would even go here.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands
2023-04-06 2:31 ` David Gibson
@ 2023-04-06 6:47 ` Stefano Brivio
2023-04-06 10:35 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-06 6:47 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Thu, 6 Apr 2023 12:31:55 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> On Wed, Apr 05, 2023 at 01:58:00PM +0200, Stefano Brivio wrote:
>
> [...]
>
> > I didn't spot this earlier, but... does it really make sense to wait in
> > cmd_pid(), also on ENOENT, rather than making 'hold' return only once
> > the socket is ready?
>
> So, this is a consequence of the fact that the holder doesn't move
> into the background itself - it just sits in the foreground until
> terminated. That means that the typical usecase puts it into the
> background from the shell with &, which in turn means that when we
> reach the next shell command the socket may not be ready - or not even
> created.
>
> One of the things I had in mind for a hypothetical "nstool unshare"
> would be to avoid this and have it background itself once the socket
> is ready.
Ah, sure, it makes sense now.
> > I don't think it would be outrageous to have
> > 'nstool pid' failing if the holding process doesn't exist.
> >
> > Admittely, I'm biased by the few hundreds of times I needed to
> > 'killall -9 nsholder' in the past months. :)
>
> So... I agree that's irritating, I've done it a similar number of
> times. However, I don't think that's really related to the question
> above - in my experience it's always been the holder process that's
> hung around, not something waiting on a holder.
Yes, same here, but it's something I file under the same category (I
don't remember why nsholder would hang, you probably explained at some
point...).
> > > rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
> > > &peercred, &optlen);
> > > if (rc < 0)
> > > - die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
> > > + die("getsockopet(SO_PEERCRED) %s: %s\n",
> > > + sockpath, strerror(errno));
> > >
> > > close(fd);
> > >
> > > printf("%d\n", peercred.pid);
> > > }
> > >
> > > -static void stop(int fd, const struct sockaddr_un *addr)
> > > +static void cmd_stop(int argc, char *argv[])
> > > {
> > > - int rc;
> > > + const char *sockpath = argv[1];
> > > + int fd, rc;
> > > char buf = 'Q';
> > >
> > > - rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
> > > - if (rc < 0)
> > > - die("connect(): %s\n", strerror(errno));
> > > + if (argc != 2)
> > > + usage();
> > > +
> > > + fd = connect_ctl(sockpath, false);
> > >
> > > rc = write(fd, &buf, sizeof(buf));
> >
> > Unrelated: a compound literal would make this more readable.
>
> Uh.. I don't see where a compound literal would even go here.
I meant:
rc = write(fd, &(char){ 'Q' }, 1);
...so that one doesn't need to look at 'buf'. nstool is C99 anyway.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands
2023-04-06 6:47 ` Stefano Brivio
@ 2023-04-06 10:35 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 10:35 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 3496 bytes --]
On Thu, Apr 06, 2023 at 08:47:48AM +0200, Stefano Brivio wrote:
> On Thu, 6 Apr 2023 12:31:55 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > On Wed, Apr 05, 2023 at 01:58:00PM +0200, Stefano Brivio wrote:
> >
> > [...]
> >
> > > I didn't spot this earlier, but... does it really make sense to wait in
> > > cmd_pid(), also on ENOENT, rather than making 'hold' return only once
> > > the socket is ready?
> >
> > So, this is a consequence of the fact that the holder doesn't move
> > into the background itself - it just sits in the foreground until
> > terminated. That means that the typical usecase puts it into the
> > background from the shell with &, which in turn means that when we
> > reach the next shell command the socket may not be ready - or not even
> > created.
> >
> > One of the things I had in mind for a hypothetical "nstool unshare"
> > would be to avoid this and have it background itself once the socket
> > is ready.
>
> Ah, sure, it makes sense now.
>
> > > I don't think it would be outrageous to have
> > > 'nstool pid' failing if the holding process doesn't exist.
> > >
> > > Admittely, I'm biased by the few hundreds of times I needed to
> > > 'killall -9 nsholder' in the past months. :)
> >
> > So... I agree that's irritating, I've done it a similar number of
> > times. However, I don't think that's really related to the question
> > above - in my experience it's always been the holder process that's
> > hung around, not something waiting on a holder.
>
> Yes, same here, but it's something I file under the same category (I
> don't remember why nsholder would hang, you probably explained at some
> point...).
I believe the main reason is because of the holders which are PID 1
within their pid namespaces. That means that if you interrupt the
tests, the SIGINT or SIGHUP they'll get from tmux etc. shutting down
won't be sufficient to kill them.
>
> > > > rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
> > > > &peercred, &optlen);
> > > > if (rc < 0)
> > > > - die("getsockopet(SO_PEERCRED): %s\n", strerror(errno));
> > > > + die("getsockopet(SO_PEERCRED) %s: %s\n",
> > > > + sockpath, strerror(errno));
> > > >
> > > > close(fd);
> > > >
> > > > printf("%d\n", peercred.pid);
> > > > }
> > > >
> > > > -static void stop(int fd, const struct sockaddr_un *addr)
> > > > +static void cmd_stop(int argc, char *argv[])
> > > > {
> > > > - int rc;
> > > > + const char *sockpath = argv[1];
> > > > + int fd, rc;
> > > > char buf = 'Q';
> > > >
> > > > - rc = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
> > > > - if (rc < 0)
> > > > - die("connect(): %s\n", strerror(errno));
> > > > + if (argc != 2)
> > > > + usage();
> > > > +
> > > > + fd = connect_ctl(sockpath, false);
> > > >
> > > > rc = write(fd, &buf, sizeof(buf));
> > >
> > > Unrelated: a compound literal would make this more readable.
> >
> > Uh.. I don't see where a compound literal would even go here.
>
> I meant:
>
> rc = write(fd, &(char){ 'Q' }, 1);
>
> ...so that one doesn't need to look at 'buf'. nstool is C99 anyway.
Oh, ok. On the other hand it means not using sizeof() to get the
length, which isn't ideal.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (3 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 04/14] nstool: Split some command line parsing and socket setup to subcommands David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 06/14] nstool: Detect what namespaces target is in David Gibson
` (9 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
The new subcommand gives more information about the holder process and its
namespace, and may be further extended in future. Add some options which
give the old behaviour for existing scripts.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/lib/setup | 12 +++++-----
test/nstool.c | 60 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/test/lib/setup b/test/lib/setup
index e6180b1..6d7644a 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -78,7 +78,7 @@ setup_pasta() {
layout_pasta
context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
- __target_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
+ __target_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
@@ -128,7 +128,7 @@ setup_passt_in_ns() {
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 --config-net ${NSTOOL} hold ${STATESETUP}/ns.hold"
wait_for [ -f "${STATESETUP}/pasta.pid" ]
- __ns_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
+ __ns_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
context_setup_nsenter qemu "-t ${__ns_pid} -U -n -p --preserve-credentials"
context_setup_nsenter ns "-t ${__ns_pid} -U -n -p --preserve-credentials"
@@ -190,7 +190,7 @@ setup_two_guests() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
context_run_bg pasta_1 "./pasta ${__opts} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} hold ${STATESETUP}/ns1.hold"
- __ns1_pid=$(${NSTOOL} pid ${STATESETUP}/ns1.hold)
+ __ns1_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns1.hold)
context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
__opts=
@@ -198,7 +198,7 @@ setup_two_guests() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
context_run_bg pasta_2 "./pasta ${__opts} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} hold ${STATESETUP}/ns2.hold"
- __ns2_pid=$(${NSTOOL} pid ${STATESETUP}/ns2.hold)
+ __ns2_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns2.hold)
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}
@@ -310,8 +310,8 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- __ns1_pid=$(${NSTOOL} pid "${STATESETUP}/ns1.hold")
- __ns2_pid=$(${NSTOOL} pid "${STATESETUP}/ns2.hold")
+ __ns1_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns1.hold")
+ __ns2_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns2.hold")
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
diff --git a/test/nstool.c b/test/nstool.c
index 9ea7eeb..2cb4fb3 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -14,6 +14,7 @@
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
+#include <getopt.h>
#include <sys/socket.h>
#include <linux/un.h>
@@ -30,9 +31,11 @@ static void usage(void)
" Run within a set of namespaces, open a Unix domain control\n"
" socket at SOCK and wait for requests from other nstool\n"
" subcommands.\n"
- " nstool pid SOCK\n"
- " Print the pid of the nstool hold process with control socket\n"
- " at SOCK, as seen in the caller's namespace.\n"
+ " nstool info [-pw] pid SOCK\n"
+ " Print information about the nstool hold process with control\n"
+ " socket at SOCK\n"
+ " -p Print just the holder's PID as seen by the caller\n"
+ " -w Retry connecting to SOCK until it is ready\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -103,17 +106,45 @@ static void cmd_hold(int argc, char *argv[])
unlink(sockpath);
}
-static void cmd_pid(int argc, char *argv[])
+static void cmd_info(int argc, char *argv[])
{
- const char *sockpath = argv[1];
+ const struct option options[] = {
+ {"pid", no_argument, NULL, 'p' },
+ {"wait", no_argument, NULL, 'w' },
+ { 0 },
+ };
+ bool pidonly = false, waitforsock = false;
struct ucred peercred;
socklen_t optlen = sizeof(peercred);
- int fd, rc;
+ const char *optstring = "pw";
+ const char *sockpath;
+ int fd, rc, opt;
- if (argc != 2)
+ do {
+ opt = getopt_long(argc, argv, optstring, options, NULL);
+
+ switch (opt) {
+ case 'p':
+ pidonly = true;
+ break;
+ case 'w':
+ waitforsock = true;
+ break;
+ case -1:
+ break;
+ default:
+ usage();
+ }
+ } while (opt != -1);
+
+ if (optind != argc - 1) {
+ fprintf(stderr, "B\n");
usage();
+ }
+
+ sockpath = argv[optind];
- fd = connect_ctl(sockpath, true);
+ fd = connect_ctl(sockpath, waitforsock);
rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
&peercred, &optlen);
@@ -123,7 +154,14 @@ static void cmd_pid(int argc, char *argv[])
close(fd);
- printf("%d\n", peercred.pid);
+ if (pidonly) {
+ printf("%d\n", peercred.pid);
+ } else {
+ printf("As seen from calling context:\n");
+ printf("\tPID:\t%d\n", peercred.pid);
+ printf("\tUID:\t%u\n", peercred.uid);
+ printf("\tGID:\t%u\n", peercred.gid);
+ }
}
static void cmd_stop(int argc, char *argv[])
@@ -158,8 +196,8 @@ int main(int argc, char *argv[])
if (strcmp(subcmd, "hold") == 0)
cmd_hold(argc - 1, argv + 1);
- else if (strcmp(subcmd, "pid") == 0)
- cmd_pid(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "info") == 0)
+ cmd_info(argc - 1, argv + 1);
else if (strcmp(subcmd, "stop") == 0)
cmd_stop(argc - 1, argv + 1);
else
--
@@ -14,6 +14,7 @@
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
+#include <getopt.h>
#include <sys/socket.h>
#include <linux/un.h>
@@ -30,9 +31,11 @@ static void usage(void)
" Run within a set of namespaces, open a Unix domain control\n"
" socket at SOCK and wait for requests from other nstool\n"
" subcommands.\n"
- " nstool pid SOCK\n"
- " Print the pid of the nstool hold process with control socket\n"
- " at SOCK, as seen in the caller's namespace.\n"
+ " nstool info [-pw] pid SOCK\n"
+ " Print information about the nstool hold process with control\n"
+ " socket at SOCK\n"
+ " -p Print just the holder's PID as seen by the caller\n"
+ " -w Retry connecting to SOCK until it is ready\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -103,17 +106,45 @@ static void cmd_hold(int argc, char *argv[])
unlink(sockpath);
}
-static void cmd_pid(int argc, char *argv[])
+static void cmd_info(int argc, char *argv[])
{
- const char *sockpath = argv[1];
+ const struct option options[] = {
+ {"pid", no_argument, NULL, 'p' },
+ {"wait", no_argument, NULL, 'w' },
+ { 0 },
+ };
+ bool pidonly = false, waitforsock = false;
struct ucred peercred;
socklen_t optlen = sizeof(peercred);
- int fd, rc;
+ const char *optstring = "pw";
+ const char *sockpath;
+ int fd, rc, opt;
- if (argc != 2)
+ do {
+ opt = getopt_long(argc, argv, optstring, options, NULL);
+
+ switch (opt) {
+ case 'p':
+ pidonly = true;
+ break;
+ case 'w':
+ waitforsock = true;
+ break;
+ case -1:
+ break;
+ default:
+ usage();
+ }
+ } while (opt != -1);
+
+ if (optind != argc - 1) {
+ fprintf(stderr, "B\n");
usage();
+ }
+
+ sockpath = argv[optind];
- fd = connect_ctl(sockpath, true);
+ fd = connect_ctl(sockpath, waitforsock);
rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
&peercred, &optlen);
@@ -123,7 +154,14 @@ static void cmd_pid(int argc, char *argv[])
close(fd);
- printf("%d\n", peercred.pid);
+ if (pidonly) {
+ printf("%d\n", peercred.pid);
+ } else {
+ printf("As seen from calling context:\n");
+ printf("\tPID:\t%d\n", peercred.pid);
+ printf("\tUID:\t%u\n", peercred.uid);
+ printf("\tGID:\t%u\n", peercred.gid);
+ }
}
static void cmd_stop(int argc, char *argv[])
@@ -158,8 +196,8 @@ int main(int argc, char *argv[])
if (strcmp(subcmd, "hold") == 0)
cmd_hold(argc - 1, argv + 1);
- else if (strcmp(subcmd, "pid") == 0)
- cmd_pid(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "info") == 0)
+ cmd_info(argc - 1, argv + 1);
else if (strcmp(subcmd, "stop") == 0)
cmd_stop(argc - 1, argv + 1);
else
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand
2023-04-04 1:46 ` [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 0:13 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:29 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> The new subcommand gives more information about the holder process and its
> namespace, and may be further extended in future. Add some options which
> give the old behaviour for existing scripts.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/lib/setup | 12 +++++-----
> test/nstool.c | 60 +++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 55 insertions(+), 17 deletions(-)
>
> diff --git a/test/lib/setup b/test/lib/setup
> index e6180b1..6d7644a 100755
> --- a/test/lib/setup
> +++ b/test/lib/setup
> @@ -78,7 +78,7 @@ setup_pasta() {
> layout_pasta
>
> context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
> - __target_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
> + __target_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
Either 'pid' or 'info -pw' needs to be typed a few times, and 'pid' is
simpler. I would have a slight preference toward demultiplexing the
different commands in nstool rather than in scripts (with, say, 'pid'
passing 'pidonly' as true in cmd_info()).
And you always pass '-w', right?
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 0:13 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:13 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 1632 bytes --]
On Wed, Apr 05, 2023 at 01:58:15PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:29 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > The new subcommand gives more information about the holder process and its
> > namespace, and may be further extended in future. Add some options which
> > give the old behaviour for existing scripts.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/lib/setup | 12 +++++-----
> > test/nstool.c | 60 +++++++++++++++++++++++++++++++++++++++++---------
> > 2 files changed, 55 insertions(+), 17 deletions(-)
> >
> > diff --git a/test/lib/setup b/test/lib/setup
> > index e6180b1..6d7644a 100755
> > --- a/test/lib/setup
> > +++ b/test/lib/setup
> > @@ -78,7 +78,7 @@ setup_pasta() {
> > layout_pasta
> >
> > context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
> > - __target_pid=$(${NSTOOL} pid ${STATESETUP}/ns.hold)
> > + __target_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
>
> Either 'pid' or 'info -pw' needs to be typed a few times, and 'pid' is
> simpler. I would have a slight preference toward demultiplexing the
> different commands in nstool rather than in scripts (with, say, 'pid'
> passing 'pidonly' as true in cmd_info()).
>
> And you always pass '-w', right?
As of this patch, that's true, but a lot of that goes away when nstool
exec is introduced.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 06/14] nstool: Detect what namespaces target is in
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (4 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 05/14] nstool: Replace "pid" subcommand with "info" subcommand David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 07/14] nstool: Add magic number to advertized information David Gibson
` (8 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Give nstool the ability to detect what namespaces the target process is in,
relative to where it's called. That is, those namespace types for which
the target is not in the same namespace as the caller. For now, just
print this information with "info", which can be useful for debugging.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 140 insertions(+), 14 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index 2cb4fb3..428c9c4 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -15,8 +15,13 @@
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
+#include <stdarg.h>
#include <sys/socket.h>
#include <linux/un.h>
+#include <linux/limits.h>
+#include <sched.h>
+
+#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
#define die(...) \
do { \
@@ -24,6 +29,28 @@
exit(1); \
} while (0)
+struct ns_type {
+ int flag;
+ const char *name;
+};
+
+const struct ns_type nstypes[] = {
+ { CLONE_NEWCGROUP, "cgroup" },
+ { CLONE_NEWIPC, "ipc" },
+ { CLONE_NEWNET, "net" },
+ { CLONE_NEWNS, "mnt" },
+ { CLONE_NEWPID, "pid" },
+ { CLONE_NEWTIME, "time" },
+ { CLONE_NEWUSER, "user" },
+ { CLONE_NEWUTS, "uts" },
+};
+
+struct holder_info {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+};
+
static void usage(void)
{
die("Usage:\n"
@@ -41,12 +68,16 @@ static void usage(void)
" terminate.\n");
}
-static int connect_ctl(const char * sockpath, bool wait)
+static int connect_ctl(const char *sockpath, bool wait,
+ struct holder_info *info,
+ struct ucred *peercred)
{
int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
+ struct holder_info discard;
+ ssize_t len;
int rc;
if (fd < 0)
@@ -61,6 +92,25 @@ static int connect_ctl(const char * sockpath, bool wait)
die("connect() to %s: %s\n", sockpath, strerror(errno));
} while (rc < 0);
+ if (!info)
+ info = &discard;
+
+ len = read(fd, info, sizeof(*info));
+ if (len < 0)
+ die("read() on control socket %s: %s\n", sockpath, strerror(errno));
+ if ((size_t)len < sizeof(*info))
+ die("short read() on control socket %s\n", sockpath);
+
+ if (peercred) {
+ socklen_t optlen = sizeof(*peercred);
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+ peercred, &optlen);
+ if (rc < 0)
+ die("getsockopet(SO_PEERCRED) %s: %s\n",
+ sockpath, strerror(errno));
+ }
+
return fd;
}
@@ -71,6 +121,7 @@ static void cmd_hold(int argc, char *argv[])
.sun_family = AF_UNIX,
};
const char *sockpath = argv[1];
+ struct holder_info info;
int rc;
if (argc != 2)
@@ -89,8 +140,10 @@ static void cmd_hold(int argc, char *argv[])
if (rc < 0)
die("listen() on %s: %s\n", sockpath, strerror(errno));
- printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
- getpid(), getuid(), getgid());
+ info.pid = getpid();
+ info.uid = getuid();
+ info.gid = getgid();
+
do {
int afd = accept(fd, NULL, NULL);
char buf;
@@ -98,6 +151,12 @@ static void cmd_hold(int argc, char *argv[])
if (afd < 0)
die("accept(): %s\n", strerror(errno));
+ rc = write(afd, &info, sizeof(info));
+ if (rc < 0)
+ die("write(): %s\n", strerror(errno));
+ if ((size_t)rc < sizeof(info))
+ die("short write() on control socket\n");
+
rc = read(afd, &buf, sizeof(buf));
if (rc < 0)
die("read(): %s\n", strerror(errno));
@@ -106,6 +165,68 @@ static void cmd_hold(int argc, char *argv[])
unlink(sockpath);
}
+static ssize_t getlink(char *buf, size_t bufsiz, const char *fmt, ...)
+{
+ char linkpath[PATH_MAX];
+ ssize_t linklen;
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (vsnprintf(linkpath, sizeof(linkpath), fmt, ap) >= PATH_MAX)
+ die("Truncated path \"%s\"\n", linkpath);
+ va_end(ap);
+
+ linklen = readlink(linkpath, buf, bufsiz);
+ if (linklen < 0)
+ die("readlink() on %s: %s\n", linkpath, strerror(errno));
+ if ((size_t)linklen >= bufsiz)
+ die("Target of symbolic link %s is too long\n", linkpath);
+
+ return linklen;
+}
+
+static int detect_namespaces(pid_t pid)
+{
+ int i;
+ int flags = 0;
+
+ for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
+ const struct ns_type *nst = &nstypes[i];
+ char selflink[PATH_MAX], pidlink[PATH_MAX];
+ ssize_t selflen, pidlen;
+
+ selflen = getlink(selflink, sizeof(selflink),
+ "/proc/self/ns/%s", nst->name);
+ pidlen = getlink(pidlink, sizeof(pidlink),
+ "/proc/%d/ns/%s", pid, nst->name);
+
+ if ((selflen != pidlen) || memcmp(selflink, pidlink, selflen))
+ flags |= nst->flag;
+ }
+
+ return flags;
+}
+
+static void print_nstypes(int flags)
+{
+ bool first = true;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
+ const struct ns_type *nst = &nstypes[i];
+
+ if (!(flags & nst->flag))
+ continue;
+
+ printf("%s%s", first ? "" : ", " , nst->name);
+ first = false;
+ flags &= ~nst->flag;
+ }
+
+ if (flags)
+ printf("%s0x%x", first ? "" : ", ", flags);
+}
+
static void cmd_info(int argc, char *argv[])
{
const struct option options[] = {
@@ -114,11 +235,11 @@ static void cmd_info(int argc, char *argv[])
{ 0 },
};
bool pidonly = false, waitforsock = false;
- struct ucred peercred;
- socklen_t optlen = sizeof(peercred);
const char *optstring = "pw";
+ struct holder_info info;
+ struct ucred peercred;
const char *sockpath;
- int fd, rc, opt;
+ int fd, opt;
do {
opt = getopt_long(argc, argv, optstring, options, NULL);
@@ -144,23 +265,28 @@ static void cmd_info(int argc, char *argv[])
sockpath = argv[optind];
- fd = connect_ctl(sockpath, waitforsock);
-
- rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
- &peercred, &optlen);
- if (rc < 0)
- die("getsockopet(SO_PEERCRED) %s: %s\n",
- sockpath, strerror(errno));
+ fd = connect_ctl(sockpath, waitforsock, &info, &peercred);
close(fd);
if (pidonly) {
printf("%d\n", peercred.pid);
} else {
+ int flags = detect_namespaces(peercred.pid);
+
+ printf("Namespaces: ");
+ print_nstypes(flags);
+ printf("\n");
+
printf("As seen from calling context:\n");
printf("\tPID:\t%d\n", peercred.pid);
printf("\tUID:\t%u\n", peercred.uid);
printf("\tGID:\t%u\n", peercred.gid);
+
+ printf("As seen from holding context:\n");
+ printf("\tPID:\t%d\n", info.pid);
+ printf("\tUID:\t%u\n", info.uid);
+ printf("\tGID:\t%u\n", info.gid);
}
}
@@ -173,7 +299,7 @@ static void cmd_stop(int argc, char *argv[])
if (argc != 2)
usage();
- fd = connect_ctl(sockpath, false);
+ fd = connect_ctl(sockpath, false, NULL, NULL);
rc = write(fd, &buf, sizeof(buf));
if (rc < 0)
--
@@ -15,8 +15,13 @@
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
+#include <stdarg.h>
#include <sys/socket.h>
#include <linux/un.h>
+#include <linux/limits.h>
+#include <sched.h>
+
+#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
#define die(...) \
do { \
@@ -24,6 +29,28 @@
exit(1); \
} while (0)
+struct ns_type {
+ int flag;
+ const char *name;
+};
+
+const struct ns_type nstypes[] = {
+ { CLONE_NEWCGROUP, "cgroup" },
+ { CLONE_NEWIPC, "ipc" },
+ { CLONE_NEWNET, "net" },
+ { CLONE_NEWNS, "mnt" },
+ { CLONE_NEWPID, "pid" },
+ { CLONE_NEWTIME, "time" },
+ { CLONE_NEWUSER, "user" },
+ { CLONE_NEWUTS, "uts" },
+};
+
+struct holder_info {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+};
+
static void usage(void)
{
die("Usage:\n"
@@ -41,12 +68,16 @@ static void usage(void)
" terminate.\n");
}
-static int connect_ctl(const char * sockpath, bool wait)
+static int connect_ctl(const char *sockpath, bool wait,
+ struct holder_info *info,
+ struct ucred *peercred)
{
int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
+ struct holder_info discard;
+ ssize_t len;
int rc;
if (fd < 0)
@@ -61,6 +92,25 @@ static int connect_ctl(const char * sockpath, bool wait)
die("connect() to %s: %s\n", sockpath, strerror(errno));
} while (rc < 0);
+ if (!info)
+ info = &discard;
+
+ len = read(fd, info, sizeof(*info));
+ if (len < 0)
+ die("read() on control socket %s: %s\n", sockpath, strerror(errno));
+ if ((size_t)len < sizeof(*info))
+ die("short read() on control socket %s\n", sockpath);
+
+ if (peercred) {
+ socklen_t optlen = sizeof(*peercred);
+
+ rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
+ peercred, &optlen);
+ if (rc < 0)
+ die("getsockopet(SO_PEERCRED) %s: %s\n",
+ sockpath, strerror(errno));
+ }
+
return fd;
}
@@ -71,6 +121,7 @@ static void cmd_hold(int argc, char *argv[])
.sun_family = AF_UNIX,
};
const char *sockpath = argv[1];
+ struct holder_info info;
int rc;
if (argc != 2)
@@ -89,8 +140,10 @@ static void cmd_hold(int argc, char *argv[])
if (rc < 0)
die("listen() on %s: %s\n", sockpath, strerror(errno));
- printf("nstool hold: local PID=%d local UID=%u local GID=%u\n",
- getpid(), getuid(), getgid());
+ info.pid = getpid();
+ info.uid = getuid();
+ info.gid = getgid();
+
do {
int afd = accept(fd, NULL, NULL);
char buf;
@@ -98,6 +151,12 @@ static void cmd_hold(int argc, char *argv[])
if (afd < 0)
die("accept(): %s\n", strerror(errno));
+ rc = write(afd, &info, sizeof(info));
+ if (rc < 0)
+ die("write(): %s\n", strerror(errno));
+ if ((size_t)rc < sizeof(info))
+ die("short write() on control socket\n");
+
rc = read(afd, &buf, sizeof(buf));
if (rc < 0)
die("read(): %s\n", strerror(errno));
@@ -106,6 +165,68 @@ static void cmd_hold(int argc, char *argv[])
unlink(sockpath);
}
+static ssize_t getlink(char *buf, size_t bufsiz, const char *fmt, ...)
+{
+ char linkpath[PATH_MAX];
+ ssize_t linklen;
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (vsnprintf(linkpath, sizeof(linkpath), fmt, ap) >= PATH_MAX)
+ die("Truncated path \"%s\"\n", linkpath);
+ va_end(ap);
+
+ linklen = readlink(linkpath, buf, bufsiz);
+ if (linklen < 0)
+ die("readlink() on %s: %s\n", linkpath, strerror(errno));
+ if ((size_t)linklen >= bufsiz)
+ die("Target of symbolic link %s is too long\n", linkpath);
+
+ return linklen;
+}
+
+static int detect_namespaces(pid_t pid)
+{
+ int i;
+ int flags = 0;
+
+ for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
+ const struct ns_type *nst = &nstypes[i];
+ char selflink[PATH_MAX], pidlink[PATH_MAX];
+ ssize_t selflen, pidlen;
+
+ selflen = getlink(selflink, sizeof(selflink),
+ "/proc/self/ns/%s", nst->name);
+ pidlen = getlink(pidlink, sizeof(pidlink),
+ "/proc/%d/ns/%s", pid, nst->name);
+
+ if ((selflen != pidlen) || memcmp(selflink, pidlink, selflen))
+ flags |= nst->flag;
+ }
+
+ return flags;
+}
+
+static void print_nstypes(int flags)
+{
+ bool first = true;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
+ const struct ns_type *nst = &nstypes[i];
+
+ if (!(flags & nst->flag))
+ continue;
+
+ printf("%s%s", first ? "" : ", " , nst->name);
+ first = false;
+ flags &= ~nst->flag;
+ }
+
+ if (flags)
+ printf("%s0x%x", first ? "" : ", ", flags);
+}
+
static void cmd_info(int argc, char *argv[])
{
const struct option options[] = {
@@ -114,11 +235,11 @@ static void cmd_info(int argc, char *argv[])
{ 0 },
};
bool pidonly = false, waitforsock = false;
- struct ucred peercred;
- socklen_t optlen = sizeof(peercred);
const char *optstring = "pw";
+ struct holder_info info;
+ struct ucred peercred;
const char *sockpath;
- int fd, rc, opt;
+ int fd, opt;
do {
opt = getopt_long(argc, argv, optstring, options, NULL);
@@ -144,23 +265,28 @@ static void cmd_info(int argc, char *argv[])
sockpath = argv[optind];
- fd = connect_ctl(sockpath, waitforsock);
-
- rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED,
- &peercred, &optlen);
- if (rc < 0)
- die("getsockopet(SO_PEERCRED) %s: %s\n",
- sockpath, strerror(errno));
+ fd = connect_ctl(sockpath, waitforsock, &info, &peercred);
close(fd);
if (pidonly) {
printf("%d\n", peercred.pid);
} else {
+ int flags = detect_namespaces(peercred.pid);
+
+ printf("Namespaces: ");
+ print_nstypes(flags);
+ printf("\n");
+
printf("As seen from calling context:\n");
printf("\tPID:\t%d\n", peercred.pid);
printf("\tUID:\t%u\n", peercred.uid);
printf("\tGID:\t%u\n", peercred.gid);
+
+ printf("As seen from holding context:\n");
+ printf("\tPID:\t%d\n", info.pid);
+ printf("\tUID:\t%u\n", info.uid);
+ printf("\tGID:\t%u\n", info.gid);
}
}
@@ -173,7 +299,7 @@ static void cmd_stop(int argc, char *argv[])
if (argc != 2)
usage();
- fd = connect_ctl(sockpath, false);
+ fd = connect_ctl(sockpath, false, NULL, NULL);
rc = write(fd, &buf, sizeof(buf));
if (rc < 0)
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 06/14] nstool: Detect what namespaces target is in
2023-04-04 1:46 ` [PATCH 06/14] nstool: Detect what namespaces target is in David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 0:15 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:30 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> Give nstool the ability to detect what namespaces the target process is in,
> relative to where it's called. That is, those namespace types for which
> the target is not in the same namespace as the caller. For now, just
> print this information with "info", which can be useful for debugging.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 140 insertions(+), 14 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index 2cb4fb3..428c9c4 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -15,8 +15,13 @@
> #include <errno.h>
> #include <unistd.h>
> #include <getopt.h>
> +#include <stdarg.h>
> #include <sys/socket.h>
> #include <linux/un.h>
> +#include <linux/limits.h>
> +#include <sched.h>
> +
> +#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
>
> #define die(...) \
> do { \
> @@ -24,6 +29,28 @@
> exit(1); \
> } while (0)
>
> +struct ns_type {
> + int flag;
> + const char *name;
> +};
> +
> +const struct ns_type nstypes[] = {
> + { CLONE_NEWCGROUP, "cgroup" },
> + { CLONE_NEWIPC, "ipc" },
> + { CLONE_NEWNET, "net" },
> + { CLONE_NEWNS, "mnt" },
> + { CLONE_NEWPID, "pid" },
> + { CLONE_NEWTIME, "time" },
> + { CLONE_NEWUSER, "user" },
> + { CLONE_NEWUTS, "uts" },
> +};
> +
> +struct holder_info {
> + pid_t pid;
> + uid_t uid;
> + gid_t gid;
> +};
> +
> static void usage(void)
> {
> die("Usage:\n"
> @@ -41,12 +68,16 @@ static void usage(void)
> " terminate.\n");
> }
>
> -static int connect_ctl(const char * sockpath, bool wait)
> +static int connect_ctl(const char *sockpath, bool wait,
> + struct holder_info *info,
> + struct ucred *peercred)
> {
> int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> struct sockaddr_un addr = {
> .sun_family = AF_UNIX,
> };
> + struct holder_info discard;
> + ssize_t len;
> int rc;
>
> if (fd < 0)
> @@ -61,6 +92,25 @@ static int connect_ctl(const char * sockpath, bool wait)
> die("connect() to %s: %s\n", sockpath, strerror(errno));
> } while (rc < 0);
>
> + if (!info)
> + info = &discard;
As you close the socket anyway moments later, I wonder if it wouldn't
be doable (and more natural) to just do:
if (info) {
len = read(fd, info, sizeof(*info));
...
}
if (peercred) {
...
}
...but maybe it adds unnecessary complication to 7/14 (or perhaps the
magic is not really part of 'info'?).
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 06/14] nstool: Detect what namespaces target is in
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 0:15 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:15 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 3248 bytes --]
On Wed, Apr 05, 2023 at 01:58:25PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:30 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > Give nstool the ability to detect what namespaces the target process is in,
> > relative to where it's called. That is, those namespace types for which
> > the target is not in the same namespace as the caller. For now, just
> > print this information with "info", which can be useful for debugging.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-----
> > 1 file changed, 140 insertions(+), 14 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index 2cb4fb3..428c9c4 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -15,8 +15,13 @@
> > #include <errno.h>
> > #include <unistd.h>
> > #include <getopt.h>
> > +#include <stdarg.h>
> > #include <sys/socket.h>
> > #include <linux/un.h>
> > +#include <linux/limits.h>
> > +#include <sched.h>
> > +
> > +#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
> >
> > #define die(...) \
> > do { \
> > @@ -24,6 +29,28 @@
> > exit(1); \
> > } while (0)
> >
> > +struct ns_type {
> > + int flag;
> > + const char *name;
> > +};
> > +
> > +const struct ns_type nstypes[] = {
> > + { CLONE_NEWCGROUP, "cgroup" },
> > + { CLONE_NEWIPC, "ipc" },
> > + { CLONE_NEWNET, "net" },
> > + { CLONE_NEWNS, "mnt" },
> > + { CLONE_NEWPID, "pid" },
> > + { CLONE_NEWTIME, "time" },
> > + { CLONE_NEWUSER, "user" },
> > + { CLONE_NEWUTS, "uts" },
> > +};
> > +
> > +struct holder_info {
> > + pid_t pid;
> > + uid_t uid;
> > + gid_t gid;
> > +};
> > +
> > static void usage(void)
> > {
> > die("Usage:\n"
> > @@ -41,12 +68,16 @@ static void usage(void)
> > " terminate.\n");
> > }
> >
> > -static int connect_ctl(const char * sockpath, bool wait)
> > +static int connect_ctl(const char *sockpath, bool wait,
> > + struct holder_info *info,
> > + struct ucred *peercred)
> > {
> > int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> > struct sockaddr_un addr = {
> > .sun_family = AF_UNIX,
> > };
> > + struct holder_info discard;
> > + ssize_t len;
> > int rc;
> >
> > if (fd < 0)
> > @@ -61,6 +92,25 @@ static int connect_ctl(const char * sockpath, bool wait)
> > die("connect() to %s: %s\n", sockpath, strerror(errno));
> > } while (rc < 0);
> >
> > + if (!info)
> > + info = &discard;
>
> As you close the socket anyway moments later, I wonder if it wouldn't
> be doable (and more natural) to just do:
>
> if (info) {
> len = read(fd, info, sizeof(*info));
> ...
> }
I had something like that initially, but that causes the holder to
spit a broken pipe error, which is distracting.
> if (peercred) {
> ...
> }
>
> ...but maybe it adds unnecessary complication to 7/14 (or perhaps the
> magic is not really part of 'info'?).
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 07/14] nstool: Add magic number to advertized information
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (5 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 06/14] nstool: Detect what namespaces target is in David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 08/14] nstool: Helpers to iterate through namespace types David Gibson
` (7 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
So that we'll probably give a better error if you point it at something
that's not an nstool hold control socket.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/test/nstool.c b/test/nstool.c
index 428c9c4..e995f3e 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
@@ -45,7 +46,10 @@ const struct ns_type nstypes[] = {
{ CLONE_NEWUTS, "uts" },
};
+#define NSTOOL_MAGIC 0x75601d75
+
struct holder_info {
+ uint64_t magic;
pid_t pid;
uid_t uid;
gid_t gid;
@@ -101,6 +105,10 @@ static int connect_ctl(const char *sockpath, bool wait,
if ((size_t)len < sizeof(*info))
die("short read() on control socket %s\n", sockpath);
+ if (info->magic != NSTOOL_MAGIC)
+ die("Control socket %s doesn't appear to belong to nstool\n",
+ sockpath);
+
if (peercred) {
socklen_t optlen = sizeof(*peercred);
@@ -140,6 +148,7 @@ static void cmd_hold(int argc, char *argv[])
if (rc < 0)
die("listen() on %s: %s\n", sockpath, strerror(errno));
+ info.magic = NSTOOL_MAGIC;
info.pid = getpid();
info.uid = getuid();
info.gid = getgid();
--
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
@@ -45,7 +46,10 @@ const struct ns_type nstypes[] = {
{ CLONE_NEWUTS, "uts" },
};
+#define NSTOOL_MAGIC 0x75601d75
+
struct holder_info {
+ uint64_t magic;
pid_t pid;
uid_t uid;
gid_t gid;
@@ -101,6 +105,10 @@ static int connect_ctl(const char *sockpath, bool wait,
if ((size_t)len < sizeof(*info))
die("short read() on control socket %s\n", sockpath);
+ if (info->magic != NSTOOL_MAGIC)
+ die("Control socket %s doesn't appear to belong to nstool\n",
+ sockpath);
+
if (peercred) {
socklen_t optlen = sizeof(*peercred);
@@ -140,6 +148,7 @@ static void cmd_hold(int argc, char *argv[])
if (rc < 0)
die("listen() on %s: %s\n", sockpath, strerror(errno));
+ info.magic = NSTOOL_MAGIC;
info.pid = getpid();
info.uid = getuid();
info.gid = getgid();
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 07/14] nstool: Add magic number to advertized information
2023-04-04 1:46 ` [PATCH 07/14] nstool: Add magic number to advertized information David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 0:18 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:31 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> So that we'll probably give a better error if you point it at something
> that's not an nstool hold control socket.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index 428c9c4..e995f3e 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -12,6 +12,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <stdbool.h>
> +#include <stdint.h>
> #include <errno.h>
> #include <unistd.h>
> #include <getopt.h>
> @@ -45,7 +46,10 @@ const struct ns_type nstypes[] = {
> { CLONE_NEWUTS, "uts" },
> };
>
> +#define NSTOOL_MAGIC 0x75601d75
> +
> struct holder_info {
> + uint64_t magic;
Is uint64_t with just 32 bits "set" a trick to detect endianness
problems (perhaps it's a common pattern I'm not aware of)?
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 07/14] nstool: Add magic number to advertized information
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 0:18 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:18 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]
On Wed, Apr 05, 2023 at 01:58:34PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:31 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > So that we'll probably give a better error if you point it at something
> > that's not an nstool hold control socket.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index 428c9c4..e995f3e 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -12,6 +12,7 @@
> > #include <stdlib.h>
> > #include <string.h>
> > #include <stdbool.h>
> > +#include <stdint.h>
> > #include <errno.h>
> > #include <unistd.h>
> > #include <getopt.h>
> > @@ -45,7 +46,10 @@ const struct ns_type nstypes[] = {
> > { CLONE_NEWUTS, "uts" },
> > };
> >
> > +#define NSTOOL_MAGIC 0x75601d75
> > +
> > struct holder_info {
> > + uint64_t magic;
>
> Is uint64_t with just 32 bits "set" a trick to detect endianness
> problems (perhaps it's a common pattern I'm not aware of)?
Heh, no, that's just me having brainfade. I've extended the constant
to 64-bits.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 08/14] nstool: Helpers to iterate through namespace types
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (6 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 07/14] nstool: Add magic number to advertized information David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace David Gibson
` (6 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Will make things a bit less verbose in future.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index e995f3e..5681ce8 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -46,6 +46,14 @@ const struct ns_type nstypes[] = {
{ CLONE_NEWUTS, "uts" },
};
+#define for_each_nst(_nst, _flags) \
+ for ((_nst) = &nstypes[0]; \
+ ((_nst) - nstypes) < ARRAY_SIZE(nstypes); \
+ (_nst)++) \
+ if ((_flags) & (_nst)->flag)
+
+#define for_every_nst(_nst) for_each_nst(_nst, 0x7fffffff)
+
#define NSTOOL_MAGIC 0x75601d75
struct holder_info {
@@ -196,11 +204,10 @@ static ssize_t getlink(char *buf, size_t bufsiz, const char *fmt, ...)
static int detect_namespaces(pid_t pid)
{
- int i;
+ const struct ns_type *nst;
int flags = 0;
- for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
- const struct ns_type *nst = &nstypes[i];
+ for_every_nst(nst) {
char selflink[PATH_MAX], pidlink[PATH_MAX];
ssize_t selflen, pidlen;
@@ -218,15 +225,10 @@ static int detect_namespaces(pid_t pid)
static void print_nstypes(int flags)
{
+ const struct ns_type *nst;
bool first = true;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
- const struct ns_type *nst = &nstypes[i];
-
- if (!(flags & nst->flag))
- continue;
+ for_each_nst(nst, flags) {
printf("%s%s", first ? "" : ", " , nst->name);
first = false;
flags &= ~nst->flag;
--
@@ -46,6 +46,14 @@ const struct ns_type nstypes[] = {
{ CLONE_NEWUTS, "uts" },
};
+#define for_each_nst(_nst, _flags) \
+ for ((_nst) = &nstypes[0]; \
+ ((_nst) - nstypes) < ARRAY_SIZE(nstypes); \
+ (_nst)++) \
+ if ((_flags) & (_nst)->flag)
+
+#define for_every_nst(_nst) for_each_nst(_nst, 0x7fffffff)
+
#define NSTOOL_MAGIC 0x75601d75
struct holder_info {
@@ -196,11 +204,10 @@ static ssize_t getlink(char *buf, size_t bufsiz, const char *fmt, ...)
static int detect_namespaces(pid_t pid)
{
- int i;
+ const struct ns_type *nst;
int flags = 0;
- for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
- const struct ns_type *nst = &nstypes[i];
+ for_every_nst(nst) {
char selflink[PATH_MAX], pidlink[PATH_MAX];
ssize_t selflen, pidlen;
@@ -218,15 +225,10 @@ static int detect_namespaces(pid_t pid)
static void print_nstypes(int flags)
{
+ const struct ns_type *nst;
bool first = true;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(nstypes); i++) {
- const struct ns_type *nst = &nstypes[i];
-
- if (!(flags & nst->flag))
- continue;
+ for_each_nst(nst, flags) {
printf("%s%s", first ? "" : ", " , nst->name);
first = false;
flags &= ~nst->flag;
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 08/14] nstool: Helpers to iterate through namespace types
2023-04-04 1:46 ` [PATCH 08/14] nstool: Helpers to iterate through namespace types David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 0:55 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:32 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> Will make things a bit less verbose in future.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 22 ++++++++++++----------
> 1 file changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index e995f3e..5681ce8 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -46,6 +46,14 @@ const struct ns_type nstypes[] = {
> { CLONE_NEWUTS, "uts" },
> };
>
> +#define for_each_nst(_nst, _flags) \
> + for ((_nst) = &nstypes[0]; \
> + ((_nst) - nstypes) < ARRAY_SIZE(nstypes); \
> + (_nst)++) \
> + if ((_flags) & (_nst)->flag)
> +
> +#define for_every_nst(_nst) for_each_nst(_nst, 0x7fffffff)
Strictly speaking this should be 0x7fffff00 (minus CSIGNAL).
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 08/14] nstool: Helpers to iterate through namespace types
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 0:55 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:55 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 1483 bytes --]
On Wed, Apr 05, 2023 at 01:58:44PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:32 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > Will make things a bit less verbose in future.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 22 ++++++++++++----------
> > 1 file changed, 12 insertions(+), 10 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index e995f3e..5681ce8 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -46,6 +46,14 @@ const struct ns_type nstypes[] = {
> > { CLONE_NEWUTS, "uts" },
> > };
> >
> > +#define for_each_nst(_nst, _flags) \
> > + for ((_nst) = &nstypes[0]; \
> > + ((_nst) - nstypes) < ARRAY_SIZE(nstypes); \
> > + (_nst)++) \
> > + if ((_flags) & (_nst)->flag)
> > +
> > +#define for_every_nst(_nst) for_each_nst(_nst, 0x7fffffff)
>
> Strictly speaking this should be 0x7fffff00 (minus CSIGNAL).
So, I'm here deliberately not trying to embed knowledge of which ns
types actually exist (if I need that, we really need to probe the
kernel to find out). So this is just intended to be every bit in a
positive int. I've now replaced it with INT_MAX, which is probably a
better choice here.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (7 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 08/14] nstool: Helpers to iterate through namespace types David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:58 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 10/14] nstool: Add --keep-caps option to nstool exec David Gibson
` (5 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
This combines nstool info -pw <sock> with nsenter with various options for
a more convenient and less verbose of entering existing nstool managed
namespaces.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 137 insertions(+), 2 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index 5681ce8..25079aa 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -17,7 +17,9 @@
#include <unistd.h>
#include <getopt.h>
#include <stdarg.h>
+#include <fcntl.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#include <linux/un.h>
#include <linux/limits.h>
#include <sched.h>
@@ -75,6 +77,9 @@ static void usage(void)
" socket at SOCK\n"
" -p Print just the holder's PID as seen by the caller\n"
" -w Retry connecting to SOCK until it is ready\n"
+ " nstool exec SOCK [COMMAND [ARGS...]]\n"
+ " Execute command or shell in the namespaces of the nstool hold\n"
+ " with control socket at SOCK\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -84,7 +89,7 @@ static int connect_ctl(const char *sockpath, bool wait,
struct holder_info *info,
struct ucred *peercred)
{
- int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
@@ -132,7 +137,7 @@ static int connect_ctl(const char *sockpath, bool wait,
static void cmd_hold(int argc, char *argv[])
{
- int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
@@ -301,6 +306,134 @@ static void cmd_info(int argc, char *argv[])
}
}
+static int openns(const char *fmt, ...)
+{
+ char nspath[PATH_MAX];
+ va_list ap;
+ int fd;
+
+ va_start(ap, fmt);
+ if (vsnprintf(nspath, sizeof(nspath), fmt, ap) >= PATH_MAX)
+ die("Truncated path \"%s\"\n", nspath);
+ va_end(ap);
+
+ fd = open(nspath, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ die("open() %s: %s\n", nspath, strerror(errno));
+
+ return fd;
+}
+
+static void wait_for_child(pid_t pid)
+{
+ int status;
+
+ /* Match the child's exit status, if possible */
+ for (;;) {
+ pid_t rc;
+
+ rc = waitpid(pid, &status, WUNTRACED);
+ if (rc < 0)
+ die("waitpid() on %d: %s\n", pid, strerror(errno));
+ if (rc != pid)
+ die("waitpid() on %d returned %d", pid, rc);
+ if (WIFSTOPPED(status)) {
+ /* Stop the parent to patch */
+ kill(getpid(), SIGSTOP);
+ /* We must have resumed, resume the child */
+ kill(pid, SIGCONT);
+ continue;
+ }
+
+ break;
+ }
+
+ if (WIFEXITED(status))
+ exit(WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ kill(getpid(), WTERMSIG(status));
+
+ die("Unexpected status for child %d\n", pid);
+}
+
+static void cmd_exec(int argc, char *argv[])
+{
+ const char *shargs[] = { NULL, NULL };
+ const char *sockpath = argv[1];
+ int nfd[ARRAY_SIZE(nstypes)];
+ const struct ns_type *nst;
+ const char *const *xargs;
+ struct ucred peercred;
+ int ctlfd, flags, rc;
+ const char *exe;
+ pid_t xpid;
+
+ if (argc < 2)
+ usage();
+
+ ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
+
+ flags = detect_namespaces(peercred.pid);
+
+ for_each_nst(nst, flags) {
+ int *fd = &nfd[nst - nstypes];
+ *fd = openns("/proc/%d/ns/%s", peercred.pid, nst->name);
+ }
+
+ /* First pass, will get things where we need the privileges of
+ * the initial userns */
+ for_each_nst(nst, flags) {
+ int fd = nfd[nst - nstypes];
+
+ rc = setns(fd, nst->flag);
+ if (rc == 0) {
+ flags &= ~nst->flag;
+ }
+ }
+
+ /* Second pass, will get things where we need the privileges
+ * of the target userns */
+ for_each_nst(nst, flags) {
+ int fd = nfd[nst - nstypes];
+
+ rc = setns(fd, nst->flag);
+ if (rc < 0)
+ die("setns() type %s: %s\n",
+ nst->name, strerror(errno));
+ }
+
+ /* Fork to properly enter PID namespace */
+ xpid = fork();
+ if (xpid < 0)
+ die("fork(): %s\n", strerror(errno));
+
+ if (xpid > 0) {
+ /* Close the control socket so the waiting parent
+ * doesn't block the holder */
+ close(ctlfd);
+ wait_for_child(xpid);
+ }
+
+ /* CHILD */
+ if (argc > 2) {
+ exe = argv[2];
+ xargs = (const char * const*)(argv + 2);
+ } else {
+ exe = getenv("SHELL");
+ if (!exe)
+ exe = "/bin/sh";
+
+ shargs[0] = exe;
+
+ xargs = shargs;
+ }
+
+ rc = execvp(exe, (char *const *)xargs);
+ if (rc < 0)
+ die("execv() %s: %s\n", exe, strerror(errno));
+ die("Returned from exec()\n");
+}
+
static void cmd_stop(int argc, char *argv[])
{
const char *sockpath = argv[1];
@@ -335,6 +468,8 @@ int main(int argc, char *argv[])
cmd_hold(argc - 1, argv + 1);
else if (strcmp(subcmd, "info") == 0)
cmd_info(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "exec") == 0)
+ cmd_exec(argc - 1, argv + 1);
else if (strcmp(subcmd, "stop") == 0)
cmd_stop(argc - 1, argv + 1);
else
--
@@ -17,7 +17,9 @@
#include <unistd.h>
#include <getopt.h>
#include <stdarg.h>
+#include <fcntl.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#include <linux/un.h>
#include <linux/limits.h>
#include <sched.h>
@@ -75,6 +77,9 @@ static void usage(void)
" socket at SOCK\n"
" -p Print just the holder's PID as seen by the caller\n"
" -w Retry connecting to SOCK until it is ready\n"
+ " nstool exec SOCK [COMMAND [ARGS...]]\n"
+ " Execute command or shell in the namespaces of the nstool hold\n"
+ " with control socket at SOCK\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -84,7 +89,7 @@ static int connect_ctl(const char *sockpath, bool wait,
struct holder_info *info,
struct ucred *peercred)
{
- int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
@@ -132,7 +137,7 @@ static int connect_ctl(const char *sockpath, bool wait,
static void cmd_hold(int argc, char *argv[])
{
- int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
+ int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
};
@@ -301,6 +306,134 @@ static void cmd_info(int argc, char *argv[])
}
}
+static int openns(const char *fmt, ...)
+{
+ char nspath[PATH_MAX];
+ va_list ap;
+ int fd;
+
+ va_start(ap, fmt);
+ if (vsnprintf(nspath, sizeof(nspath), fmt, ap) >= PATH_MAX)
+ die("Truncated path \"%s\"\n", nspath);
+ va_end(ap);
+
+ fd = open(nspath, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ die("open() %s: %s\n", nspath, strerror(errno));
+
+ return fd;
+}
+
+static void wait_for_child(pid_t pid)
+{
+ int status;
+
+ /* Match the child's exit status, if possible */
+ for (;;) {
+ pid_t rc;
+
+ rc = waitpid(pid, &status, WUNTRACED);
+ if (rc < 0)
+ die("waitpid() on %d: %s\n", pid, strerror(errno));
+ if (rc != pid)
+ die("waitpid() on %d returned %d", pid, rc);
+ if (WIFSTOPPED(status)) {
+ /* Stop the parent to patch */
+ kill(getpid(), SIGSTOP);
+ /* We must have resumed, resume the child */
+ kill(pid, SIGCONT);
+ continue;
+ }
+
+ break;
+ }
+
+ if (WIFEXITED(status))
+ exit(WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ kill(getpid(), WTERMSIG(status));
+
+ die("Unexpected status for child %d\n", pid);
+}
+
+static void cmd_exec(int argc, char *argv[])
+{
+ const char *shargs[] = { NULL, NULL };
+ const char *sockpath = argv[1];
+ int nfd[ARRAY_SIZE(nstypes)];
+ const struct ns_type *nst;
+ const char *const *xargs;
+ struct ucred peercred;
+ int ctlfd, flags, rc;
+ const char *exe;
+ pid_t xpid;
+
+ if (argc < 2)
+ usage();
+
+ ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
+
+ flags = detect_namespaces(peercred.pid);
+
+ for_each_nst(nst, flags) {
+ int *fd = &nfd[nst - nstypes];
+ *fd = openns("/proc/%d/ns/%s", peercred.pid, nst->name);
+ }
+
+ /* First pass, will get things where we need the privileges of
+ * the initial userns */
+ for_each_nst(nst, flags) {
+ int fd = nfd[nst - nstypes];
+
+ rc = setns(fd, nst->flag);
+ if (rc == 0) {
+ flags &= ~nst->flag;
+ }
+ }
+
+ /* Second pass, will get things where we need the privileges
+ * of the target userns */
+ for_each_nst(nst, flags) {
+ int fd = nfd[nst - nstypes];
+
+ rc = setns(fd, nst->flag);
+ if (rc < 0)
+ die("setns() type %s: %s\n",
+ nst->name, strerror(errno));
+ }
+
+ /* Fork to properly enter PID namespace */
+ xpid = fork();
+ if (xpid < 0)
+ die("fork(): %s\n", strerror(errno));
+
+ if (xpid > 0) {
+ /* Close the control socket so the waiting parent
+ * doesn't block the holder */
+ close(ctlfd);
+ wait_for_child(xpid);
+ }
+
+ /* CHILD */
+ if (argc > 2) {
+ exe = argv[2];
+ xargs = (const char * const*)(argv + 2);
+ } else {
+ exe = getenv("SHELL");
+ if (!exe)
+ exe = "/bin/sh";
+
+ shargs[0] = exe;
+
+ xargs = shargs;
+ }
+
+ rc = execvp(exe, (char *const *)xargs);
+ if (rc < 0)
+ die("execv() %s: %s\n", exe, strerror(errno));
+ die("Returned from exec()\n");
+}
+
static void cmd_stop(int argc, char *argv[])
{
const char *sockpath = argv[1];
@@ -335,6 +468,8 @@ int main(int argc, char *argv[])
cmd_hold(argc - 1, argv + 1);
else if (strcmp(subcmd, "info") == 0)
cmd_info(argc - 1, argv + 1);
+ else if (strcmp(subcmd, "exec") == 0)
+ cmd_exec(argc - 1, argv + 1);
else if (strcmp(subcmd, "stop") == 0)
cmd_stop(argc - 1, argv + 1);
else
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace
2023-04-04 1:46 ` [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace David Gibson
@ 2023-04-05 11:58 ` Stefano Brivio
2023-04-06 0:59 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:58 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:33 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> This combines nstool info -pw <sock> with nsenter with various options for
> a more convenient and less verbose of entering existing nstool managed
> namespaces.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 137 insertions(+), 2 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index 5681ce8..25079aa 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -17,7 +17,9 @@
> #include <unistd.h>
> #include <getopt.h>
> #include <stdarg.h>
> +#include <fcntl.h>
> #include <sys/socket.h>
> +#include <sys/wait.h>
> #include <linux/un.h>
> #include <linux/limits.h>
> #include <sched.h>
> @@ -75,6 +77,9 @@ static void usage(void)
> " socket at SOCK\n"
> " -p Print just the holder's PID as seen by the caller\n"
> " -w Retry connecting to SOCK until it is ready\n"
> + " nstool exec SOCK [COMMAND [ARGS...]]\n"
> + " Execute command or shell in the namespaces of the nstool hold\n"
> + " with control socket at SOCK\n"
> " nstool stop SOCK\n"
> " Instruct the nstool hold with control socket at SOCK to\n"
> " terminate.\n");
> @@ -84,7 +89,7 @@ static int connect_ctl(const char *sockpath, bool wait,
> struct holder_info *info,
> struct ucred *peercred)
> {
> - int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
> struct sockaddr_un addr = {
> .sun_family = AF_UNIX,
> };
> @@ -132,7 +137,7 @@ static int connect_ctl(const char *sockpath, bool wait,
>
> static void cmd_hold(int argc, char *argv[])
> {
> - int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
> struct sockaddr_un addr = {
> .sun_family = AF_UNIX,
> };
> @@ -301,6 +306,134 @@ static void cmd_info(int argc, char *argv[])
> }
> }
>
> +static int openns(const char *fmt, ...)
> +{
> + char nspath[PATH_MAX];
> + va_list ap;
> + int fd;
> +
> + va_start(ap, fmt);
> + if (vsnprintf(nspath, sizeof(nspath), fmt, ap) >= PATH_MAX)
> + die("Truncated path \"%s\"\n", nspath);
> + va_end(ap);
> +
> + fd = open(nspath, O_RDONLY | O_CLOEXEC);
> + if (fd < 0)
> + die("open() %s: %s\n", nspath, strerror(errno));
> +
> + return fd;
> +}
> +
> +static void wait_for_child(pid_t pid)
> +{
> + int status;
> +
> + /* Match the child's exit status, if possible */
> + for (;;) {
> + pid_t rc;
> +
> + rc = waitpid(pid, &status, WUNTRACED);
> + if (rc < 0)
> + die("waitpid() on %d: %s\n", pid, strerror(errno));
> + if (rc != pid)
> + die("waitpid() on %d returned %d", pid, rc);
> + if (WIFSTOPPED(status)) {
> + /* Stop the parent to patch */
> + kill(getpid(), SIGSTOP);
> + /* We must have resumed, resume the child */
> + kill(pid, SIGCONT);
> + continue;
> + }
> +
> + break;
> + }
> +
> + if (WIFEXITED(status))
> + exit(WEXITSTATUS(status));
> + else if (WIFSIGNALED(status))
> + kill(getpid(), WTERMSIG(status));
An alternative could be what pasta_child_handler() does on
WIFSIGNALED(status) -- I don't actually have a preference between the
two.
> +
> + die("Unexpected status for child %d\n", pid);
Weird indentation in this function.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace
2023-04-05 11:58 ` Stefano Brivio
@ 2023-04-06 0:59 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 0:59 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 4407 bytes --]
On Wed, Apr 05, 2023 at 01:58:54PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:33 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > This combines nstool info -pw <sock> with nsenter with various options for
> > a more convenient and less verbose of entering existing nstool managed
> > namespaces.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 137 insertions(+), 2 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index 5681ce8..25079aa 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -17,7 +17,9 @@
> > #include <unistd.h>
> > #include <getopt.h>
> > #include <stdarg.h>
> > +#include <fcntl.h>
> > #include <sys/socket.h>
> > +#include <sys/wait.h>
> > #include <linux/un.h>
> > #include <linux/limits.h>
> > #include <sched.h>
> > @@ -75,6 +77,9 @@ static void usage(void)
> > " socket at SOCK\n"
> > " -p Print just the holder's PID as seen by the caller\n"
> > " -w Retry connecting to SOCK until it is ready\n"
> > + " nstool exec SOCK [COMMAND [ARGS...]]\n"
> > + " Execute command or shell in the namespaces of the nstool hold\n"
> > + " with control socket at SOCK\n"
> > " nstool stop SOCK\n"
> > " Instruct the nstool hold with control socket at SOCK to\n"
> > " terminate.\n");
> > @@ -84,7 +89,7 @@ static int connect_ctl(const char *sockpath, bool wait,
> > struct holder_info *info,
> > struct ucred *peercred)
> > {
> > - int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> > + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
> > struct sockaddr_un addr = {
> > .sun_family = AF_UNIX,
> > };
> > @@ -132,7 +137,7 @@ static int connect_ctl(const char *sockpath, bool wait,
> >
> > static void cmd_hold(int argc, char *argv[])
> > {
> > - int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
> > + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNIX);
> > struct sockaddr_un addr = {
> > .sun_family = AF_UNIX,
> > };
> > @@ -301,6 +306,134 @@ static void cmd_info(int argc, char *argv[])
> > }
> > }
> >
> > +static int openns(const char *fmt, ...)
> > +{
> > + char nspath[PATH_MAX];
> > + va_list ap;
> > + int fd;
> > +
> > + va_start(ap, fmt);
> > + if (vsnprintf(nspath, sizeof(nspath), fmt, ap) >= PATH_MAX)
> > + die("Truncated path \"%s\"\n", nspath);
> > + va_end(ap);
> > +
> > + fd = open(nspath, O_RDONLY | O_CLOEXEC);
> > + if (fd < 0)
> > + die("open() %s: %s\n", nspath, strerror(errno));
> > +
> > + return fd;
> > +}
> > +
> > +static void wait_for_child(pid_t pid)
> > +{
> > + int status;
> > +
> > + /* Match the child's exit status, if possible */
> > + for (;;) {
> > + pid_t rc;
> > +
> > + rc = waitpid(pid, &status, WUNTRACED);
> > + if (rc < 0)
> > + die("waitpid() on %d: %s\n", pid, strerror(errno));
> > + if (rc != pid)
> > + die("waitpid() on %d returned %d", pid, rc);
> > + if (WIFSTOPPED(status)) {
> > + /* Stop the parent to patch */
> > + kill(getpid(), SIGSTOP);
> > + /* We must have resumed, resume the child */
> > + kill(pid, SIGCONT);
> > + continue;
> > + }
> > +
> > + break;
> > + }
> > +
> > + if (WIFEXITED(status))
> > + exit(WEXITSTATUS(status));
> > + else if (WIFSIGNALED(status))
> > + kill(getpid(), WTERMSIG(status));
>
> An alternative could be what pasta_child_handler() does on
> WIFSIGNALED(status) -- I don't actually have a preference between the
> two.
Right. The idiom above I copied from unshare and nsenter in
util-linux. Seems marginally more thorough than the 128+ trick.
> > +
> > + die("Unexpected status for child %d\n", pid);
>
> Weird indentation in this function.
Ugh, yes. I think I did a copy paste at some point that introduced a
bunch of spaces where there should be tabs. Fixing.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 10/14] nstool: Add --keep-caps option to nstool exec
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (8 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 09/14] nstool: Add nstool exec command to execute commands in an nstool namespace David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:59 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 11/14] test: Initialise ${TRACE} properly David Gibson
` (4 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
This allows you to run commands within a user namespace with the
privilege that comes from owning that userns.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 89 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 79 insertions(+), 10 deletions(-)
diff --git a/test/nstool.c b/test/nstool.c
index 25079aa..3ecc456 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -18,11 +18,15 @@
#include <getopt.h>
#include <stdarg.h>
#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
#include <linux/un.h>
-#include <linux/limits.h>
#include <sched.h>
+#include <linux/capability.h>
#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
@@ -75,11 +79,13 @@ static void usage(void)
" nstool info [-pw] pid SOCK\n"
" Print information about the nstool hold process with control\n"
" socket at SOCK\n"
- " -p Print just the holder's PID as seen by the caller\n"
- " -w Retry connecting to SOCK until it is ready\n"
- " nstool exec SOCK [COMMAND [ARGS...]]\n"
+ " -p Print just the holder's PID as seen by the caller\n"
+ " -w Retry connecting to SOCK until it is ready\n"
+ " nstool exec [--keep-caps] SOCK [COMMAND [ARGS...]]\n"
" Execute command or shell in the namespaces of the nstool hold\n"
" with control socket at SOCK\n"
+ " --keep-caps Give all possible capabilities to COMMAND via\n"
+ " the ambient capability mask\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -275,7 +281,6 @@ static void cmd_info(int argc, char *argv[])
} while (opt != -1);
if (optind != argc - 1) {
- fprintf(stderr, "B\n");
usage();
}
@@ -356,21 +361,82 @@ static void wait_for_child(pid_t pid)
die("Unexpected status for child %d\n", pid);
}
+static void caps_to_ambient(void)
+{
+ /* Use raw system calls to avoid the overly complex caps
+ * libraries. */
+ struct __user_cap_header_struct header = {
+ .version = _LINUX_CAPABILITY_VERSION_3,
+ .pid = 0,
+ };
+ struct __user_cap_data_struct payload[_LINUX_CAPABILITY_U32S_3] =
+ {{ 0 }};
+ uint64_t effective, cap;
+
+ if (syscall(SYS_capget, &header, payload) < 0)
+ die("capget(): %s\n", strerror(errno));
+
+ /* First make caps inheritable */
+ payload[0].inheritable = payload[0].permitted;
+ payload[1].inheritable = payload[1].permitted;
+
+ if (syscall(SYS_capset, &header, payload) < 0)
+ die("capset(): %s\n", strerror(errno));
+
+ effective = ((uint64_t)payload[1].effective << 32) | (uint64_t)payload[0].effective;
+
+ for (cap = 0; cap < (sizeof(effective) * 8); cap++) {
+ /* Skip non-existent caps */
+ if (prctl(PR_CAPBSET_READ, cap, 0, 0, 0) < 0)
+ continue;
+
+ if ((effective & (1 << cap))
+ && prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) < 0)
+ die("prctl(PR_CAP_AMBIENT): %s\n", strerror(errno));
+ }
+
+}
+
static void cmd_exec(int argc, char *argv[])
{
+ enum {
+ OPT_EXEC_KEEPCAPS = CHAR_MAX + 1,
+ };
+ const struct option options[] = {
+ {"keep-caps", no_argument, NULL, OPT_EXEC_KEEPCAPS },
+ { 0 },
+ };
const char *shargs[] = { NULL, NULL };
const char *sockpath = argv[1];
int nfd[ARRAY_SIZE(nstypes)];
+ const char *optstring = "";
const struct ns_type *nst;
+ int ctlfd, flags, opt, rc;
const char *const *xargs;
+ bool keepcaps = false;
struct ucred peercred;
- int ctlfd, flags, rc;
const char *exe;
pid_t xpid;
- if (argc < 2)
+ do {
+ opt = getopt_long(argc, argv, optstring, options, NULL);
+
+ switch (opt) {
+ case OPT_EXEC_KEEPCAPS:
+ keepcaps = true;
+ break;
+ case -1:
+ break;
+ default:
+ usage();
+ }
+ } while (opt != -1);
+
+ if (argc < optind + 1)
usage();
+ sockpath = argv[optind];
+
ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
flags = detect_namespaces(peercred.pid);
@@ -415,9 +481,9 @@ static void cmd_exec(int argc, char *argv[])
}
/* CHILD */
- if (argc > 2) {
- exe = argv[2];
- xargs = (const char * const*)(argv + 2);
+ if (argc > optind + 1) {
+ exe = argv[optind + 1];
+ xargs = (const char * const*)(argv + optind + 1);
} else {
exe = getenv("SHELL");
if (!exe)
@@ -428,6 +494,9 @@ static void cmd_exec(int argc, char *argv[])
xargs = shargs;
}
+ if (keepcaps)
+ caps_to_ambient();
+
rc = execvp(exe, (char *const *)xargs);
if (rc < 0)
die("execv() %s: %s\n", exe, strerror(errno));
--
@@ -18,11 +18,15 @@
#include <getopt.h>
#include <stdarg.h>
#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
#include <linux/un.h>
-#include <linux/limits.h>
#include <sched.h>
+#include <linux/capability.h>
#define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
@@ -75,11 +79,13 @@ static void usage(void)
" nstool info [-pw] pid SOCK\n"
" Print information about the nstool hold process with control\n"
" socket at SOCK\n"
- " -p Print just the holder's PID as seen by the caller\n"
- " -w Retry connecting to SOCK until it is ready\n"
- " nstool exec SOCK [COMMAND [ARGS...]]\n"
+ " -p Print just the holder's PID as seen by the caller\n"
+ " -w Retry connecting to SOCK until it is ready\n"
+ " nstool exec [--keep-caps] SOCK [COMMAND [ARGS...]]\n"
" Execute command or shell in the namespaces of the nstool hold\n"
" with control socket at SOCK\n"
+ " --keep-caps Give all possible capabilities to COMMAND via\n"
+ " the ambient capability mask\n"
" nstool stop SOCK\n"
" Instruct the nstool hold with control socket at SOCK to\n"
" terminate.\n");
@@ -275,7 +281,6 @@ static void cmd_info(int argc, char *argv[])
} while (opt != -1);
if (optind != argc - 1) {
- fprintf(stderr, "B\n");
usage();
}
@@ -356,21 +361,82 @@ static void wait_for_child(pid_t pid)
die("Unexpected status for child %d\n", pid);
}
+static void caps_to_ambient(void)
+{
+ /* Use raw system calls to avoid the overly complex caps
+ * libraries. */
+ struct __user_cap_header_struct header = {
+ .version = _LINUX_CAPABILITY_VERSION_3,
+ .pid = 0,
+ };
+ struct __user_cap_data_struct payload[_LINUX_CAPABILITY_U32S_3] =
+ {{ 0 }};
+ uint64_t effective, cap;
+
+ if (syscall(SYS_capget, &header, payload) < 0)
+ die("capget(): %s\n", strerror(errno));
+
+ /* First make caps inheritable */
+ payload[0].inheritable = payload[0].permitted;
+ payload[1].inheritable = payload[1].permitted;
+
+ if (syscall(SYS_capset, &header, payload) < 0)
+ die("capset(): %s\n", strerror(errno));
+
+ effective = ((uint64_t)payload[1].effective << 32) | (uint64_t)payload[0].effective;
+
+ for (cap = 0; cap < (sizeof(effective) * 8); cap++) {
+ /* Skip non-existent caps */
+ if (prctl(PR_CAPBSET_READ, cap, 0, 0, 0) < 0)
+ continue;
+
+ if ((effective & (1 << cap))
+ && prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) < 0)
+ die("prctl(PR_CAP_AMBIENT): %s\n", strerror(errno));
+ }
+
+}
+
static void cmd_exec(int argc, char *argv[])
{
+ enum {
+ OPT_EXEC_KEEPCAPS = CHAR_MAX + 1,
+ };
+ const struct option options[] = {
+ {"keep-caps", no_argument, NULL, OPT_EXEC_KEEPCAPS },
+ { 0 },
+ };
const char *shargs[] = { NULL, NULL };
const char *sockpath = argv[1];
int nfd[ARRAY_SIZE(nstypes)];
+ const char *optstring = "";
const struct ns_type *nst;
+ int ctlfd, flags, opt, rc;
const char *const *xargs;
+ bool keepcaps = false;
struct ucred peercred;
- int ctlfd, flags, rc;
const char *exe;
pid_t xpid;
- if (argc < 2)
+ do {
+ opt = getopt_long(argc, argv, optstring, options, NULL);
+
+ switch (opt) {
+ case OPT_EXEC_KEEPCAPS:
+ keepcaps = true;
+ break;
+ case -1:
+ break;
+ default:
+ usage();
+ }
+ } while (opt != -1);
+
+ if (argc < optind + 1)
usage();
+ sockpath = argv[optind];
+
ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
flags = detect_namespaces(peercred.pid);
@@ -415,9 +481,9 @@ static void cmd_exec(int argc, char *argv[])
}
/* CHILD */
- if (argc > 2) {
- exe = argv[2];
- xargs = (const char * const*)(argv + 2);
+ if (argc > optind + 1) {
+ exe = argv[optind + 1];
+ xargs = (const char * const*)(argv + optind + 1);
} else {
exe = getenv("SHELL");
if (!exe)
@@ -428,6 +494,9 @@ static void cmd_exec(int argc, char *argv[])
xargs = shargs;
}
+ if (keepcaps)
+ caps_to_ambient();
+
rc = execvp(exe, (char *const *)xargs);
if (rc < 0)
die("execv() %s: %s\n", exe, strerror(errno));
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 10/14] nstool: Add --keep-caps option to nstool exec
2023-04-04 1:46 ` [PATCH 10/14] nstool: Add --keep-caps option to nstool exec David Gibson
@ 2023-04-05 11:59 ` Stefano Brivio
2023-04-06 1:11 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:59 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:34 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> This allows you to run commands within a user namespace with the
> privilege that comes from owning that userns.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/nstool.c | 89 +++++++++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 79 insertions(+), 10 deletions(-)
>
> diff --git a/test/nstool.c b/test/nstool.c
> index 25079aa..3ecc456 100644
> --- a/test/nstool.c
> +++ b/test/nstool.c
> @@ -18,11 +18,15 @@
> #include <getopt.h>
> #include <stdarg.h>
> #include <fcntl.h>
> +#include <limits.h>
> +#include <unistd.h>
> #include <sys/socket.h>
> #include <sys/wait.h>
> +#include <sys/syscall.h>
> +#include <sys/prctl.h>
> #include <linux/un.h>
> -#include <linux/limits.h>
> #include <sched.h>
> +#include <linux/capability.h>
>
> #define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
>
> @@ -75,11 +79,13 @@ static void usage(void)
> " nstool info [-pw] pid SOCK\n"
> " Print information about the nstool hold process with control\n"
> " socket at SOCK\n"
> - " -p Print just the holder's PID as seen by the caller\n"
> - " -w Retry connecting to SOCK until it is ready\n"
> - " nstool exec SOCK [COMMAND [ARGS...]]\n"
> + " -p Print just the holder's PID as seen by the caller\n"
> + " -w Retry connecting to SOCK until it is ready\n"
> + " nstool exec [--keep-caps] SOCK [COMMAND [ARGS...]]\n"
> " Execute command or shell in the namespaces of the nstool hold\n"
> " with control socket at SOCK\n"
> + " --keep-caps Give all possible capabilities to COMMAND via\n"
> + " the ambient capability mask\n"
> " nstool stop SOCK\n"
> " Instruct the nstool hold with control socket at SOCK to\n"
> " terminate.\n");
> @@ -275,7 +281,6 @@ static void cmd_info(int argc, char *argv[])
> } while (opt != -1);
>
> if (optind != argc - 1) {
> - fprintf(stderr, "B\n");
> usage();
> }
>
> @@ -356,21 +361,82 @@ static void wait_for_child(pid_t pid)
> die("Unexpected status for child %d\n", pid);
> }
>
> +static void caps_to_ambient(void)
> +{
> + /* Use raw system calls to avoid the overly complex caps
> + * libraries. */
Bad indentation here.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 10/14] nstool: Add --keep-caps option to nstool exec
2023-04-05 11:59 ` Stefano Brivio
@ 2023-04-06 1:11 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 1:11 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 2882 bytes --]
On Wed, Apr 05, 2023 at 01:59:02PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:34 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > This allows you to run commands within a user namespace with the
> > privilege that comes from owning that userns.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/nstool.c | 89 +++++++++++++++++++++++++++++++++++++++++++++------
> > 1 file changed, 79 insertions(+), 10 deletions(-)
> >
> > diff --git a/test/nstool.c b/test/nstool.c
> > index 25079aa..3ecc456 100644
> > --- a/test/nstool.c
> > +++ b/test/nstool.c
> > @@ -18,11 +18,15 @@
> > #include <getopt.h>
> > #include <stdarg.h>
> > #include <fcntl.h>
> > +#include <limits.h>
> > +#include <unistd.h>
> > #include <sys/socket.h>
> > #include <sys/wait.h>
> > +#include <sys/syscall.h>
> > +#include <sys/prctl.h>
> > #include <linux/un.h>
> > -#include <linux/limits.h>
> > #include <sched.h>
> > +#include <linux/capability.h>
> >
> > #define ARRAY_SIZE(a) ((int)(sizeof(a) / sizeof((a)[0])))
> >
> > @@ -75,11 +79,13 @@ static void usage(void)
> > " nstool info [-pw] pid SOCK\n"
> > " Print information about the nstool hold process with control\n"
> > " socket at SOCK\n"
> > - " -p Print just the holder's PID as seen by the caller\n"
> > - " -w Retry connecting to SOCK until it is ready\n"
> > - " nstool exec SOCK [COMMAND [ARGS...]]\n"
> > + " -p Print just the holder's PID as seen by the caller\n"
> > + " -w Retry connecting to SOCK until it is ready\n"
> > + " nstool exec [--keep-caps] SOCK [COMMAND [ARGS...]]\n"
> > " Execute command or shell in the namespaces of the nstool hold\n"
> > " with control socket at SOCK\n"
> > + " --keep-caps Give all possible capabilities to COMMAND via\n"
> > + " the ambient capability mask\n"
> > " nstool stop SOCK\n"
> > " Instruct the nstool hold with control socket at SOCK to\n"
> > " terminate.\n");
> > @@ -275,7 +281,6 @@ static void cmd_info(int argc, char *argv[])
> > } while (opt != -1);
> >
> > if (optind != argc - 1) {
> > - fprintf(stderr, "B\n");
> > usage();
> > }
> >
> > @@ -356,21 +361,82 @@ static void wait_for_child(pid_t pid)
> > die("Unexpected status for child %d\n", pid);
> > }
> >
> > +static void caps_to_ambient(void)
> > +{
> > + /* Use raw system calls to avoid the overly complex caps
> > + * libraries. */
>
> Bad indentation here.
More pasted spaces. Fixing.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 11/14] test: Initialise ${TRACE} properly
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (9 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 10/14] nstool: Add --keep-caps option to nstool exec David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-04 1:46 ` [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests David Gibson
` (3 subsequent siblings)
14 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Unlike ${DEBUG} we don't initialize ${TRACE} to 0 if not set, which cases
failures when testing it later. That failure acts as though it is false,
however it emits spurious errors in script.log, which can make it harder to
spot real errors.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/run | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test/run b/test/run
index e07513f..1945c7b 100755
--- a/test/run
+++ b/test/run
@@ -32,6 +32,9 @@ FAST=${FAST:-1}
# If set, run passt and pasta with debug options
DEBUG=${DEBUG:-0}
+# If set, run passt and pasta with trace options
+TRACE=${TRACE:-0}
+
# If set, tell passt and pasta to take packet captures
PCAP=${PCAP:-0}
--
@@ -32,6 +32,9 @@ FAST=${FAST:-1}
# If set, run passt and pasta with debug options
DEBUG=${DEBUG:-0}
+# If set, run passt and pasta with trace options
+TRACE=${TRACE:-0}
+
# If set, tell passt and pasta to take packet captures
PCAP=${PCAP:-0}
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (10 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 11/14] test: Initialise ${TRACE} properly David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 11:59 ` Stefano Brivio
2023-04-04 1:46 ` [PATCH 13/14] nstool: Advertise the holder's cwd (in its mountns) across the socket David Gibson
` (2 subsequent siblings)
14 siblings, 1 reply; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Using this, rather than using "nstool info" to get the pid then manually
connecting with nsenter makes things a little simpler.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/lib/context | 14 +++++++++-----
test/lib/setup | 33 +++++++++++++--------------------
test/run | 2 +-
3 files changed, 23 insertions(+), 26 deletions(-)
diff --git a/test/lib/context b/test/lib/context
index ee6b683..d9d8260 100644
--- a/test/lib/context
+++ b/test/lib/context
@@ -13,6 +13,8 @@
# Copyright Red Hat
# Author: David Gibson <david@gibson.dropbear.id.au>
+NSTOOL="${BASEPATH}/nstool"
+
# context_setup_common() - Create outline of a new context
# $1: Context name
context_setup_common() {
@@ -30,15 +32,17 @@ context_setup_host() {
echo sh -c > "${__enter}"
}
-# context_setup_nsenter() - Create a new context for running commands in a namespace
+# context_setup_nstool() - Create a new context for running commands with nstool exec
# $1: Context name
-# $2: Namespace PID
-context_setup_nsenter() {
+# $2: nstool control socket
+context_setup_nstool() {
__name="$1"
- shift
+ __sock="$2"
__enter="${STATESETUP}/context_${__name}.enter"
+ # Wait for the ns to be ready
+ ${NSTOOL} info -w "${__sock}" > /dev/null
context_setup_common "${__name}"
- echo "nsenter $@ sh -c" > "${__enter}"
+ echo "${NSTOOL} exec ${__sock} -- sh -c" > "${__enter}"
}
# context_setup_guest() - Create a new context for running commands in a guest
diff --git a/test/lib/setup b/test/lib/setup
index 6d7644a..7b17336 100755
--- a/test/lib/setup
+++ b/test/lib/setup
@@ -17,7 +17,6 @@ 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))"
-NSTOOL="${BASEPATH}/nstool"
# setup_build() - Set up pane layout for build tests
setup_build() {
@@ -78,9 +77,8 @@ setup_pasta() {
layout_pasta
context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
- __target_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
- context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
+ context_setup_nstool ns ${STATESETUP}/ns.hold
# Ports:
#
@@ -94,7 +92,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 ${STATESETUP}/passt.pid ${__target_pid}"
+ context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P ${STATESETUP}/passt.pid $(${NSTOOL} info -pw ${STATESETUP}/ns.hold)"
# pidfile isn't created until pasta is ready
wait_for [ -f "${STATESETUP}/passt.pid" ]
@@ -128,11 +126,10 @@ setup_passt_in_ns() {
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 --config-net ${NSTOOL} hold ${STATESETUP}/ns.hold"
wait_for [ -f "${STATESETUP}/pasta.pid" ]
- __ns_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
- 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"
+ context_setup_nstool qemu ${STATESETUP}/ns.hold
+ context_setup_nstool ns ${STATESETUP}/ns.hold
+ context_setup_nstool passt ${STATESETUP}/ns.hold
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_in_pasta.pcap"
@@ -190,19 +187,17 @@ setup_two_guests() {
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
[ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
context_run_bg pasta_1 "./pasta ${__opts} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} hold ${STATESETUP}/ns1.hold"
- __ns1_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns1.hold)
- context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
+ context_setup_nstool passt_1 ${STATESETUP}/ns1.hold
__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} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} hold ${STATESETUP}/ns2.hold"
- __ns2_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns2.hold)
- context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
+ context_setup_nstool passt_2 ${STATESETUP}/ns2.hold
- 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}
+ context_setup_nstool qemu_1 ${STATESETUP}/ns1.hold
+ context_setup_nstool qemu_2 ${STATESETUP}/ns2.hold
__ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
@@ -310,15 +305,13 @@ teardown_passt_in_ns() {
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
- __ns1_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns1.hold")
- __ns2_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns2.hold")
- 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")
+ ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/qemu_1.pid")
+ ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/qemu_2.pid")
context_wait qemu_1
context_wait qemu_2
- 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")
+ ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/passt_1.pid")
+ ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/passt_2.pid")
context_wait passt_1
context_wait passt_2
${NSTOOL} stop "${STATESETUP}/ns1.hold"
diff --git a/test/run b/test/run
index 1945c7b..447d831 100755
--- a/test/run
+++ b/test/run
@@ -41,9 +41,9 @@ PCAP=${PCAP:-0}
COMMIT="$(git log --oneline --no-decorate -1)"
. lib/util
+. lib/context
. lib/setup
. lib/setup_ugly
-. lib/context
. lib/term
. lib/perf_report
. lib/layout
--
@@ -41,9 +41,9 @@ PCAP=${PCAP:-0}
COMMIT="$(git log --oneline --no-decorate -1)"
. lib/util
+. lib/context
. lib/setup
. lib/setup_ugly
-. lib/context
. lib/term
. lib/perf_report
. lib/layout
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests
2023-04-04 1:46 ` [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests David Gibson
@ 2023-04-05 11:59 ` Stefano Brivio
2023-04-06 1:14 ` David Gibson
0 siblings, 1 reply; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 11:59 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:36 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> Using this, rather than using "nstool info" to get the pid then manually
> connecting with nsenter makes things a little simpler.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> test/lib/context | 14 +++++++++-----
> test/lib/setup | 33 +++++++++++++--------------------
> test/run | 2 +-
> 3 files changed, 23 insertions(+), 26 deletions(-)
>
> diff --git a/test/lib/context b/test/lib/context
> index ee6b683..d9d8260 100644
> --- a/test/lib/context
> +++ b/test/lib/context
> @@ -13,6 +13,8 @@
> # Copyright Red Hat
> # Author: David Gibson <david@gibson.dropbear.id.au>
>
> +NSTOOL="${BASEPATH}/nstool"
> +
> # context_setup_common() - Create outline of a new context
> # $1: Context name
> context_setup_common() {
> @@ -30,15 +32,17 @@ context_setup_host() {
> echo sh -c > "${__enter}"
> }
>
> -# context_setup_nsenter() - Create a new context for running commands in a namespace
> +# context_setup_nstool() - Create a new context for running commands with nstool exec
> # $1: Context name
> -# $2: Namespace PID
> -context_setup_nsenter() {
> +# $2: nstool control socket
> +context_setup_nstool() {
> __name="$1"
> - shift
> + __sock="$2"
> __enter="${STATESETUP}/context_${__name}.enter"
> + # Wait for the ns to be ready
> + ${NSTOOL} info -w "${__sock}" > /dev/null
Bad indentation here.
> context_setup_common "${__name}"
> - echo "nsenter $@ sh -c" > "${__enter}"
> + echo "${NSTOOL} exec ${__sock} -- sh -c" > "${__enter}"
> }
>
> # context_setup_guest() - Create a new context for running commands in a guest
> diff --git a/test/lib/setup b/test/lib/setup
> index 6d7644a..7b17336 100755
> --- a/test/lib/setup
> +++ b/test/lib/setup
> @@ -17,7 +17,6 @@ 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))"
> -NSTOOL="${BASEPATH}/nstool"
>
> # setup_build() - Set up pane layout for build tests
> setup_build() {
> @@ -78,9 +77,8 @@ setup_pasta() {
> layout_pasta
>
> context_run_bg unshare "unshare -rUnpf ${NSTOOL} hold ${STATESETUP}/ns.hold"
> - __target_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
>
> - context_setup_nsenter ns -U -n -p --preserve-credentials -t ${__target_pid}
> + context_setup_nstool ns ${STATESETUP}/ns.hold
>
> # Ports:
> #
> @@ -94,7 +92,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 ${STATESETUP}/passt.pid ${__target_pid}"
> + context_run_bg passt "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 -P ${STATESETUP}/passt.pid $(${NSTOOL} info -pw ${STATESETUP}/ns.hold)"
>
> # pidfile isn't created until pasta is ready
> wait_for [ -f "${STATESETUP}/passt.pid" ]
> @@ -128,11 +126,10 @@ setup_passt_in_ns() {
>
> 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 --config-net ${NSTOOL} hold ${STATESETUP}/ns.hold"
> wait_for [ -f "${STATESETUP}/pasta.pid" ]
> - __ns_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns.hold)
>
> - 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"
> + context_setup_nstool qemu ${STATESETUP}/ns.hold
> + context_setup_nstool ns ${STATESETUP}/ns.hold
> + context_setup_nstool passt ${STATESETUP}/ns.hold
>
> __opts=
> [ ${PCAP} -eq 1 ] && __opts="${__opts} -p ${LOGDIR}/passt_in_pasta.pcap"
> @@ -190,19 +187,17 @@ setup_two_guests() {
> [ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
> [ ${TRACE} -eq 1 ] && __opts="${__opts} --trace"
> context_run_bg pasta_1 "./pasta ${__opts} --trace -l /tmp/pasta1.log -P ${STATESETUP}/pasta_1.pid -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004 --config-net ${NSTOOL} hold ${STATESETUP}/ns1.hold"
> - __ns1_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns1.hold)
> - context_setup_nsenter passt_1 -U -n -p --preserve-credentials -t ${__ns1_pid}
> + context_setup_nstool passt_1 ${STATESETUP}/ns1.hold
>
> __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} --trace -l /tmp/pasta2.log -P ${STATESETUP}/pasta_2.pid -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001 --config-net ${NSTOOL} hold ${STATESETUP}/ns2.hold"
> - __ns2_pid=$(${NSTOOL} info -pw ${STATESETUP}/ns2.hold)
> - context_setup_nsenter passt_2 -U -n -p --preserve-credentials -t ${__ns2_pid}
> + context_setup_nstool passt_2 ${STATESETUP}/ns2.hold
>
> - 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}
> + context_setup_nstool qemu_1 ${STATESETUP}/ns1.hold
> + context_setup_nstool qemu_2 ${STATESETUP}/ns2.hold
>
> __ifname="$(context_run qemu_1 "ip -j link show | jq -rM '.[] | select(.link_type == \"ether\").ifname'")"
>
> @@ -310,15 +305,13 @@ teardown_passt_in_ns() {
>
> # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
> teardown_two_guests() {
> - __ns1_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns1.hold")
> - __ns2_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns2.hold")
> - 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")
> + ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/qemu_1.pid")
> + ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/qemu_2.pid")
> context_wait qemu_1
> context_wait qemu_2
>
> - 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")
> + ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/passt_1.pid")
> + ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/passt_2.pid")
...and here.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests
2023-04-05 11:59 ` Stefano Brivio
@ 2023-04-06 1:14 ` David Gibson
0 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-06 1:14 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev
[-- Attachment #1: Type: text/plain, Size: 3062 bytes --]
On Wed, Apr 05, 2023 at 01:59:12PM +0200, Stefano Brivio wrote:
> On Tue, 4 Apr 2023 11:46:36 +1000
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > Using this, rather than using "nstool info" to get the pid then manually
> > connecting with nsenter makes things a little simpler.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > test/lib/context | 14 +++++++++-----
> > test/lib/setup | 33 +++++++++++++--------------------
> > test/run | 2 +-
> > 3 files changed, 23 insertions(+), 26 deletions(-)
> >
> > diff --git a/test/lib/context b/test/lib/context
> > index ee6b683..d9d8260 100644
> > --- a/test/lib/context
> > +++ b/test/lib/context
> > @@ -13,6 +13,8 @@
> > # Copyright Red Hat
> > # Author: David Gibson <david@gibson.dropbear.id.au>
> >
> > +NSTOOL="${BASEPATH}/nstool"
> > +
> > # context_setup_common() - Create outline of a new context
> > # $1: Context name
> > context_setup_common() {
> > @@ -30,15 +32,17 @@ context_setup_host() {
> > echo sh -c > "${__enter}"
> > }
> >
> > -# context_setup_nsenter() - Create a new context for running commands in a namespace
> > +# context_setup_nstool() - Create a new context for running commands with nstool exec
> > # $1: Context name
> > -# $2: Namespace PID
> > -context_setup_nsenter() {
> > +# $2: nstool control socket
> > +context_setup_nstool() {
> > __name="$1"
> > - shift
> > + __sock="$2"
> > __enter="${STATESETUP}/context_${__name}.enter"
> > + # Wait for the ns to be ready
> > + ${NSTOOL} info -w "${__sock}" > /dev/null
>
> Bad indentation here.
Fixed. Drat, emacs isn't doing what I expected here.
[snip]
> >
> > # teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
> > teardown_two_guests() {
> > - __ns1_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns1.hold")
> > - __ns2_pid=$(${NSTOOL} info -pw "${STATESETUP}/ns2.hold")
> > - 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")
> > + ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/qemu_1.pid")
> > + ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/qemu_2.pid")
> > context_wait qemu_1
> > context_wait qemu_2
> >
> > - 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")
> > + ${NSTOOL} exec ${STATESETUP}/ns1.hold -- kill $(cat "${STATESETUP}/passt_1.pid")
> > + ${NSTOOL} exec ${STATESETUP}/ns2.hold -- kill $(cat "${STATESETUP}/passt_2.pid")
>
> ...and here.
Fixed here as well.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH 13/14] nstool: Advertise the holder's cwd (in its mountns) across the socket
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (11 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 12/14] test: Use "nstool exec" to slightly simplify tests David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-04 1:46 ` [PATCH 14/14] nstool: Enter holder's cwd when changing mount ns with nstool exec David Gibson
2023-04-05 12:01 ` [PATCH 00/14] Improved tool for testing across multiple namespaces Stefano Brivio
14 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
This is possible useful in nstool info and has further uses for nstool
exec.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/nstool.c b/test/nstool.c
index 3ecc456..c07eabb 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -67,6 +67,7 @@ struct holder_info {
pid_t pid;
uid_t uid;
gid_t gid;
+ char cwd[PATH_MAX];
};
static void usage(void)
@@ -171,6 +172,8 @@ static void cmd_hold(int argc, char *argv[])
info.pid = getpid();
info.uid = getuid();
info.gid = getgid();
+ if (!getcwd(info.cwd, sizeof(info.cwd)))
+ die("getcwd(): %s\n", strerror(errno));
do {
int afd = accept(fd, NULL, NULL);
@@ -308,6 +311,7 @@ static void cmd_info(int argc, char *argv[])
printf("\tPID:\t%d\n", info.pid);
printf("\tUID:\t%u\n", info.uid);
printf("\tGID:\t%u\n", info.gid);
+ printf("\tCWD:\t%s\n", info.cwd);
}
}
--
@@ -67,6 +67,7 @@ struct holder_info {
pid_t pid;
uid_t uid;
gid_t gid;
+ char cwd[PATH_MAX];
};
static void usage(void)
@@ -171,6 +172,8 @@ static void cmd_hold(int argc, char *argv[])
info.pid = getpid();
info.uid = getuid();
info.gid = getgid();
+ if (!getcwd(info.cwd, sizeof(info.cwd)))
+ die("getcwd(): %s\n", strerror(errno));
do {
int afd = accept(fd, NULL, NULL);
@@ -308,6 +311,7 @@ static void cmd_info(int argc, char *argv[])
printf("\tPID:\t%d\n", info.pid);
printf("\tUID:\t%u\n", info.uid);
printf("\tGID:\t%u\n", info.gid);
+ printf("\tCWD:\t%s\n", info.cwd);
}
}
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* [PATCH 14/14] nstool: Enter holder's cwd when changing mount ns with nstool exec
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (12 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 13/14] nstool: Advertise the holder's cwd (in its mountns) across the socket David Gibson
@ 2023-04-04 1:46 ` David Gibson
2023-04-05 12:01 ` [PATCH 00/14] Improved tool for testing across multiple namespaces Stefano Brivio
14 siblings, 0 replies; 36+ messages in thread
From: David Gibson @ 2023-04-04 1:46 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
If we enter a mount namespace with nstool exec our working directory will
be changed to / in the new mount ns. This is surprising if we haven't
actually altered any mounts yet in the new ns. Instead, change the working
directory to match that of the holder process in this situation.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
test/nstool.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/test/nstool.c b/test/nstool.c
index c07eabb..a1c31be 100644
--- a/test/nstool.c
+++ b/test/nstool.c
@@ -417,6 +417,7 @@ static void cmd_exec(int argc, char *argv[])
const struct ns_type *nst;
int ctlfd, flags, opt, rc;
const char *const *xargs;
+ struct holder_info info;
bool keepcaps = false;
struct ucred peercred;
const char *exe;
@@ -441,7 +442,7 @@ static void cmd_exec(int argc, char *argv[])
sockpath = argv[optind];
- ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
+ ctlfd = connect_ctl(sockpath, false, &info, &peercred);
flags = detect_namespaces(peercred.pid);
@@ -472,6 +473,15 @@ static void cmd_exec(int argc, char *argv[])
nst->name, strerror(errno));
}
+ /* If we've entered a mount ns, our cwd has changed to /.
+ * Switch to the cwd of the holder, which is probably less
+ * surprising. */
+ if (flags & CLONE_NEWNS) {
+ rc = chdir(info.cwd);
+ if (rc < 0)
+ die("chdir(\"%s\"): %s\n", info.cwd, strerror(errno));
+ }
+
/* Fork to properly enter PID namespace */
xpid = fork();
if (xpid < 0)
--
@@ -417,6 +417,7 @@ static void cmd_exec(int argc, char *argv[])
const struct ns_type *nst;
int ctlfd, flags, opt, rc;
const char *const *xargs;
+ struct holder_info info;
bool keepcaps = false;
struct ucred peercred;
const char *exe;
@@ -441,7 +442,7 @@ static void cmd_exec(int argc, char *argv[])
sockpath = argv[optind];
- ctlfd = connect_ctl(sockpath, false, NULL, &peercred);
+ ctlfd = connect_ctl(sockpath, false, &info, &peercred);
flags = detect_namespaces(peercred.pid);
@@ -472,6 +473,15 @@ static void cmd_exec(int argc, char *argv[])
nst->name, strerror(errno));
}
+ /* If we've entered a mount ns, our cwd has changed to /.
+ * Switch to the cwd of the holder, which is probably less
+ * surprising. */
+ if (flags & CLONE_NEWNS) {
+ rc = chdir(info.cwd);
+ if (rc < 0)
+ die("chdir(\"%s\"): %s\n", info.cwd, strerror(errno));
+ }
+
/* Fork to properly enter PID namespace */
xpid = fork();
if (xpid < 0)
--
2.39.2
^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [PATCH 00/14] Improved tool for testing across multiple namespaces
2023-04-04 1:46 [PATCH 00/14] Improved tool for testing across multiple namespaces David Gibson
` (13 preceding siblings ...)
2023-04-04 1:46 ` [PATCH 14/14] nstool: Enter holder's cwd when changing mount ns with nstool exec David Gibson
@ 2023-04-05 12:01 ` Stefano Brivio
14 siblings, 0 replies; 36+ messages in thread
From: Stefano Brivio @ 2023-04-05 12:01 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Tue, 4 Apr 2023 11:46:24 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> This series extends the "nsholder" tool we use in the tests to
> "nstool" with some more features. In particular it allows entering an
> established namespace with capabilities intact, and it allows entering
> them with less verbose options than nsenter.
>
> For now this only gives a modest simplification of the tests, but it
> should enable more in future.
>
> I haven't managed to get all the way through the testsuite with this:
> it's wedging in the IPv4 UDP throughput tests, but that's happening
> for me with the main branch too. I'll debug that, but I don't want to
> delay this series on that for now.
>
> David Gibson (14):
> nstool: Rename nsholder to nstool
> nstool: Reverse parameters to nstool
> nstool: Move description of its operation modes from comment to usage
> nstool: Split some command line parsing and socket setup to
> subcommands
> nstool: Replace "pid" subcommand with "info" subcommand
> nstool: Detect what namespaces target is in
> nstool: Add magic number to advertized information
> nstool: Helpers to iterate through namespace types
> nstool: Add nstool exec command to execute commands in an nstool
> namespace
> nstool: Add --keep-caps option to nstool exec
> test: Initialise ${TRACE} properly
> test: Use "nstool exec" to slightly simplify tests
> nstool: Advertise the holder's cwd (in its mountns) across the socket
> nstool: Enter holder's cwd when changing mount ns with nstool exec
In general this series looks good to me. None of the comments I have
should actually impact functionality, so I can also apply as it is for
the moment, I don't want to stand in the way of progress (and focus) --
as you prefer.
--
Stefano
^ permalink raw reply [flat|nested] 36+ messages in thread