From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Gibson To: passt-dev@passt.top Subject: [PATCH 06/10] Consolidate validation of pasta namespace options Date: Wed, 07 Sep 2022 11:45:05 +1000 Message-ID: <20220907014509.3480812-7-david@gibson.dropbear.id.au> In-Reply-To: <20220907014509.3480812-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0378744814424602831==" --===============0378744814424602831== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable There are a number of different ways to specify namespaces for pasta to use. Some combinations are valid and some are not. Currently validation for these is spread across several places: conf_ns_pid() validates PID options specifically. Near its callsite in conf() several other checks are made. Some additional checks are made in conf_ns_open() and finally theres a check just before the call to pasta_start_ns(). This is quite hard to follow. Make it easier by putting all the validation logic together in a new conf_pasta_ns() function, which subsumes conf_ns_pid(). This reveals that some of the checks were redundant with each other, so remove those. For good measure, rename conf_netns() to conf_netns_opt() to make it clearer its handling just the --netns option specifically, not overall configuration of the netns. Signed-off-by: David Gibson --- conf.c | 83 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/conf.c b/conf.c index 08a2106..5018794 100644 --- a/conf.c +++ b/conf.c @@ -491,13 +491,13 @@ out: } =20 /** - * conf_netns() - Parse --netns option + * conf_netns_opt() - Parse --netns option * @netns: buffer of size PATH_MAX, updated with netns path * @arg: --netns argument * * Return: 0 on success, negative error code otherwise */ -static int conf_netns(char *netns, const char *arg) +static int conf_netns_opt(char *netns, const char *arg) { int ret; =20 @@ -518,40 +518,59 @@ static int conf_netns(char *netns, const char *arg) } =20 /** - * conf_ns_pid() - Parse non-option argument as a PID + * conf_pasta_ns() - Validate all pasta namespace options + * @netns_only: Don't use userns, may be updated * @userns: buffer of size PATH_MAX, initially contains --userns * argument (may be empty), updated with userns path * @netns: buffer of size PATH_MAX, initial contains --netns * argument (may be empty), updated with netns path - * @arg: PID of network namespace + * @optind: Index of first non-option argument + * @argc: Number of arguments + * @argv: Command line arguments * * Return: 0 on success, negative error code otherwise */ -static int conf_ns_pid(char *userns, char *netns, const char *arg) +static int conf_pasta_ns(int *netns_only, char *userns, char *netns, + int optind, int argc, char *argv[]) { - char *endptr; - long pidval; + if (*netns_only && *userns) { + err("Both --userns and --netns-only given"); + return -EINVAL; + } =20 - if (*netns) { - err("Both --netns and PID given"); + if (*netns && optind !=3D argc) { + err("Both --netns and PID or command given"); return -EINVAL; } =20 - pidval =3D strtol(arg, &endptr, 10); - if (!*endptr) { - /* Looks like a pid */ - if (pidval < 0 || pidval > INT_MAX) { - err("Invalid PID %s", arg); - return -EINVAL; + if (optind + 1 =3D=3D argc) { + char *endptr; + long pidval; + + pidval =3D strtol(argv[optind], &endptr, 10); + if (!*endptr) { + /* Looks like a pid */ + if (pidval < 0 || pidval > INT_MAX) { + err("Invalid PID %s", argv[optind]); + return -EINVAL; + } + + snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval); + if (!*userns) + snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", + pidval); } + } =20 - snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval); - if (!*userns) - snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", pidval); - return 0; + if (*userns && !*netns) { + err("--userns requires --netns or PID"); + return -EINVAL; } =20 - /* Not a PID, later code will treat as a command */ + /* Attaching to a netns/PID, with no userns given */ + if (*netns && !*userns) + *netns_only =3D 1; + return 0; } =20 @@ -585,11 +604,6 @@ static int conf_ns_open(struct ctx *c, const char *usern= s, const char *netns) { int ufd =3D -1, nfd =3D -1; =20 - if (c->netns_only && *userns) { - err("Both --userns and --netns-only given"); - return -EINVAL; - } - nfd =3D open(netns, O_RDONLY | O_CLOEXEC); if (nfd < 0) { err("Couldn't open network namespace %s", netns); @@ -607,7 +621,6 @@ static int conf_ns_open(struct ctx *c, const char *userns= , const char *netns) =20 c->pasta_netns_fd =3D nfd; c->pasta_userns_fd =3D ufd; - c->netns_only =3D !*userns; =20 NS_CALL(conf_ns_check, c); =20 @@ -1194,7 +1207,7 @@ void conf(struct ctx *c, int argc, char **argv) usage(argv[0]); } =20 - ret =3D conf_netns(netns, optarg); + ret =3D conf_netns_opt(netns, optarg); if (ret < 0) usage(argv[0]); break; @@ -1573,17 +1586,9 @@ void conf(struct ctx *c, int argc, char **argv) drop_root(uid, gid); =20 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 (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"); + if (conf_pasta_ns(&c->netns_only, userns, netns, + optind, argc, argv) < 0) usage(argv[0]); - } } else if (optind !=3D argc) { usage(argv[0]); } @@ -1597,10 +1602,6 @@ void conf(struct ctx *c, int argc, char **argv) if (ret < 0) usage(argv[0]); } else { - if (*userns) { - err("Both --userns and command given"); - usage(argv[0]); - } pasta_start_ns(c, argc - optind, argv + optind); } } --=20 2.37.3 --===============0378744814424602831==--