Consolidate validation of pasta namespace options
There are a number of different ways to specify namespaces for pasta to use. Some combinations are valid and some are not. Currently validation for these is spread across several places: conf_ns_pid() validates PID options specifically. Near its callsite in conf() several other checks are made. Some additional checks are made in conf_ns_open() and finally theres a check just before the call to pasta_start_ns(). This is quite hard to follow. Make it easier by putting all the validation logic together in a new conf_pasta_ns() function, which subsumes conf_ns_pid(). This reveals that some of the checks were redundant with each other, so remove those. For good measure, rename conf_netns() to conf_netns_opt() to make it clearer its handling just the --netns option specifically, not overall configuration of the netns. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
d72a1e7bb9
commit
e8b19a4bd2
1 changed files with 45 additions and 44 deletions
89
conf.c
89
conf.c
|
@ -491,13 +491,13 @@ out:
|
|||
}
|
||||
|
||||
/**
|
||||
* conf_netns() - Parse --netns option
|
||||
* conf_netns_opt() - Parse --netns option
|
||||
* @netns: buffer of size PATH_MAX, updated with netns path
|
||||
* @arg: --netns argument
|
||||
*
|
||||
* Return: 0 on success, negative error code otherwise
|
||||
*/
|
||||
static int conf_netns(char *netns, const char *arg)
|
||||
static int conf_netns_opt(char *netns, const char *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -518,40 +518,59 @@ static int conf_netns(char *netns, const char *arg)
|
|||
}
|
||||
|
||||
/**
|
||||
* conf_ns_pid() - Parse non-option argument as a PID
|
||||
* conf_pasta_ns() - Validate all pasta namespace options
|
||||
* @netns_only: Don't use userns, may be updated
|
||||
* @userns: buffer of size PATH_MAX, initially contains --userns
|
||||
* argument (may be empty), updated with userns path
|
||||
* @netns: buffer of size PATH_MAX, initial contains --netns
|
||||
* argument (may be empty), updated with netns path
|
||||
* @arg: PID of network namespace
|
||||
* @optind: Index of first non-option argument
|
||||
* @argc: Number of arguments
|
||||
* @argv: Command line arguments
|
||||
*
|
||||
* Return: 0 on success, negative error code otherwise
|
||||
*/
|
||||
static int conf_ns_pid(char *userns, char *netns, const char *arg)
|
||||
static int conf_pasta_ns(int *netns_only, char *userns, char *netns,
|
||||
int optind, int argc, char *argv[])
|
||||
{
|
||||
char *endptr;
|
||||
long pidval;
|
||||
|
||||
if (*netns) {
|
||||
err("Both --netns and PID given");
|
||||
if (*netns_only && *userns) {
|
||||
err("Both --userns and --netns-only given");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pidval = strtol(arg, &endptr, 10);
|
||||
if (!*endptr) {
|
||||
/* Looks like a pid */
|
||||
if (pidval < 0 || pidval > INT_MAX) {
|
||||
err("Invalid PID %s", arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
|
||||
if (!*userns)
|
||||
snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", pidval);
|
||||
return 0;
|
||||
if (*netns && optind != argc) {
|
||||
err("Both --netns and PID or command given");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Not a PID, later code will treat as a command */
|
||||
if (optind + 1 == argc) {
|
||||
char *endptr;
|
||||
long pidval;
|
||||
|
||||
pidval = strtol(argv[optind], &endptr, 10);
|
||||
if (!*endptr) {
|
||||
/* Looks like a pid */
|
||||
if (pidval < 0 || pidval > INT_MAX) {
|
||||
err("Invalid PID %s", argv[optind]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
|
||||
if (!*userns)
|
||||
snprintf(userns, PATH_MAX, "/proc/%ld/ns/user",
|
||||
pidval);
|
||||
}
|
||||
}
|
||||
|
||||
if (*userns && !*netns) {
|
||||
err("--userns requires --netns or PID");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Attaching to a netns/PID, with no userns given */
|
||||
if (*netns && !*userns)
|
||||
*netns_only = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -585,11 +604,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
|
|||
{
|
||||
int ufd = -1, nfd = -1;
|
||||
|
||||
if (c->netns_only && *userns) {
|
||||
err("Both --userns and --netns-only given");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nfd = open(netns, O_RDONLY | O_CLOEXEC);
|
||||
if (nfd < 0) {
|
||||
err("Couldn't open network namespace %s", netns);
|
||||
|
@ -607,7 +621,6 @@ static int conf_ns_open(struct ctx *c, const char *userns, const char *netns)
|
|||
|
||||
c->pasta_netns_fd = nfd;
|
||||
c->pasta_userns_fd = ufd;
|
||||
c->netns_only = !*userns;
|
||||
|
||||
NS_CALL(conf_ns_check, c);
|
||||
|
||||
|
@ -1194,7 +1207,7 @@ void conf(struct ctx *c, int argc, char **argv)
|
|||
usage(argv[0]);
|
||||
}
|
||||
|
||||
ret = conf_netns(netns, optarg);
|
||||
ret = conf_netns_opt(netns, optarg);
|
||||
if (ret < 0)
|
||||
usage(argv[0]);
|
||||
break;
|
||||
|
@ -1573,17 +1586,9 @@ void conf(struct ctx *c, int argc, char **argv)
|
|||
drop_root(uid, gid);
|
||||
|
||||
if (c->mode == MODE_PASTA) {
|
||||
if (*netns && optind != argc) {
|
||||
err("Both --netns and PID or command given");
|
||||
if (conf_pasta_ns(&c->netns_only, userns, netns,
|
||||
optind, argc, argv) < 0)
|
||||
usage(argv[0]);
|
||||
} else if (optind + 1 == argc) {
|
||||
ret = conf_ns_pid(userns, netns, argv[optind]);
|
||||
if (ret < 0)
|
||||
usage(argv[0]);
|
||||
} else if (*userns && !*netns && optind == argc) {
|
||||
err("--userns requires --netns or PID");
|
||||
usage(argv[0]);
|
||||
}
|
||||
} else if (optind != argc) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
@ -1597,10 +1602,6 @@ void conf(struct ctx *c, int argc, char **argv)
|
|||
if (ret < 0)
|
||||
usage(argv[0]);
|
||||
} else {
|
||||
if (*userns) {
|
||||
err("Both --userns and command given");
|
||||
usage(argv[0]);
|
||||
}
|
||||
pasta_start_ns(c, argc - optind, argv + optind);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue