From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Gibson To: passt-dev@passt.top Subject: [PATCH 8/8] Allow pasta to take a command to execute Date: Fri, 26 Aug 2022 14:58:39 +1000 Message-ID: <20220826045839.1112152-9-david@gibson.dropbear.id.au> In-Reply-To: <20220826045839.1112152-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============5208396021144715323==" --===============5208396021144715323== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When not given an existing PID or network namspace to attach to, pasta spawns a shell. Most commands which can spawn a shell in an altered environment can also run other commands in that same environment, which can be useful in automation. Allow pasta to do the same thing; it can be given an arbitrary command to run in the network and user namespace which pasta creates. If neither a command nor an existing PID or netns to attach to is given, continue to spawn a default shell, as before. Signed-off-by: David Gibson --- conf.c | 27 ++++++++++++++++++--------- passt.1 | 14 +++++++++----- pasta.c | 33 +++++++++++++++++++++++---------- pasta.h | 2 +- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/conf.c b/conf.c index 2a18124..162c2dd 100644 --- a/conf.c +++ b/conf.c @@ -550,7 +550,8 @@ static int conf_ns_pid(char *userns, char *netns, const c= har *arg) return 0; } =20 - return -EINVAL; + /* Not a PID, later code will treat as a command */ + return 0; } =20 /** @@ -1480,14 +1481,18 @@ void conf(struct ctx *c, int argc, char **argv) =20 check_root(c); =20 - if (c->mode =3D=3D MODE_PASTA && optind + 1 =3D=3D argc) { - ret =3D conf_ns_pid(userns, netns, argv[optind]); - if (ret < 0) + if (c->mode =3D=3D MODE_PASTA) { + if (*netns && optind !=3D argc) { + err("Both --netns and PID or command given"); usage(argv[0]); - } else if (c->mode =3D=3D MODE_PASTA && *userns - && !*netns && optind =3D=3D argc) { - err("--userns requires --netns or PID"); - usage(argv[0]); + } else if (optind + 1 =3D=3D argc) { + ret =3D conf_ns_pid(userns, netns, argv[optind]); + if (ret < 0) + usage(argv[0]); + } else if (*userns && !*netns && optind =3D=3D argc) { + err("--userns requires --netns or PID"); + usage(argv[0]); + } } else if (optind !=3D argc) { usage(argv[0]); } @@ -1501,7 +1506,11 @@ void conf(struct ctx *c, int argc, char **argv) if (ret < 0) usage(argv[0]); } else { - pasta_start_ns(c); + if (*userns) { + err("Both --userns and command given"); + usage(argv[0]); + } + pasta_start_ns(c, argc - optind, argv + optind); } } =20 diff --git a/passt.1 b/passt.1 index 4a09ced..3cc5a9d 100644 --- a/passt.1 +++ b/passt.1 @@ -15,7 +15,10 @@ [\fIOPTION\fR]... .br .B pasta -[\fIOPTION\fR]... [\fIPID\fR] +[\fIOPTION\fR]... [\fICOMMAND\fR [\fIARG\fR]...] +.br +.B pasta +[\fIOPTION\fR]... \fIPID\fR .br .B pasta [\fIOPTION\fR]... \fB--netns\fR [\fIPATH\fR|\fINAME\fR] @@ -62,10 +65,11 @@ or with the \fBqrap\fR(1) wrapper. equivalent functionality to network namespaces, as the one offered by \fBpasst\fR for virtual machines. =20 -If PID or --netns are given, \fBpasta\fR associates to an existing user and -network namespace. Otherwise, \fBpasta\fR creates a new user and network -namespace, and spawns an interactive shell within this context. A \fItap\fR -device within the network namespace is created to provide network connectivi= ty. +If PID or --netns are given, \fBpasta\fR associates to an existing +user and network namespace. Otherwise, \fBpasta\fR creates a new user +and network namespace, and spawns the given command or a default shell +within this context. A \fItap\fR device within the network namespace +is created to provide network connectivity. =20 For local TCP and UDP traffic only, \fBpasta\fR also implements a bypass path directly mapping Layer-4 sockets between \fIinit\fR and target namespaces, diff --git a/pasta.c b/pasta.c index 830748f..a844af2 100644 --- a/pasta.c +++ b/pasta.c @@ -108,6 +108,7 @@ netns: struct pasta_setup_ns_arg { struct ctx *c; int euid; + char **argv; }; =20 /** @@ -119,7 +120,6 @@ struct pasta_setup_ns_arg { static int pasta_setup_ns(void *arg) { struct pasta_setup_ns_arg *a =3D (struct pasta_setup_ns_arg *)arg; - char *shell; =20 if (!a->c->netns_only) { char buf[BUFSIZ]; @@ -139,29 +139,42 @@ static int pasta_setup_ns(void *arg) FWRITE("/proc/sys/net/ipv4/ping_group_range", "0 0", "Cannot set ping_group_range, ICMP requests might fail"); =20 - shell =3D getenv("SHELL") ? getenv("SHELL") : "/bin/sh"; - if (strstr(shell, "/bash")) - execve(shell, ((char *[]) { shell, "-l", NULL }), environ); - else - execve(shell, ((char *[]) { shell, NULL }), environ); + execvp(a->argv[0], a->argv); =20 - perror("execve"); + perror("execvp"); exit(EXIT_FAILURE); } =20 /** - * pasta_start_ns() - Fork shell in new namespace if target ns is not given + * pasta_start_ns() - Fork command in new namespace if target ns is not given * @c: Execution context + * @argc: Number of arguments for spawned command + * @argv: Command to spawn and arguments */ -void pasta_start_ns(struct ctx *c) +void pasta_start_ns(struct ctx *c, int argc, char *argv[]) { - struct pasta_setup_ns_arg arg =3D { .c =3D c, .euid =3D geteuid() }; + struct pasta_setup_ns_arg arg =3D { + .c =3D c, + .euid =3D geteuid(), + .argv =3D argv, + }; + char *shell =3D getenv("SHELL") ? getenv("SHELL") : "/bin/sh"; + char *sh_argv[] =3D { shell, NULL }; + char *bash_argv[] =3D { shell, "-l", NULL }; char ns_fn_stack[NS_FN_STACK_SIZE]; =20 c->foreground =3D 1; if (!c->debug) c->quiet =3D 1; =20 + if (argc =3D=3D 0) { + if (strstr(shell, "/bash")) { + arg.argv =3D bash_argv; + } else { + arg.argv =3D sh_argv; + } + } + pasta_child_pid =3D clone(pasta_setup_ns, ns_fn_stack + sizeof(ns_fn_stack) / 2, (c->netns_only ? 0 : CLONE_NEWNET) | diff --git a/pasta.h b/pasta.h index 8c80006..19b2e54 100644 --- a/pasta.h +++ b/pasta.h @@ -6,7 +6,7 @@ #ifndef PASTA_H #define PASTA_H =20 -void pasta_start_ns(struct ctx *c); +void pasta_start_ns(struct ctx *c, int argc, char *argv[]); void pasta_ns_conf(struct ctx *c); void pasta_child_handler(int signal); int pasta_netns_quit_init(struct ctx *c); --=20 2.37.2 --===============5208396021144715323==--