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
73
conf.c
73
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
|
* @netns: buffer of size PATH_MAX, updated with netns path
|
||||||
* @arg: --netns argument
|
* @arg: --netns argument
|
||||||
*
|
*
|
||||||
* Return: 0 on success, negative error code otherwise
|
* 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;
|
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
|
* @userns: buffer of size PATH_MAX, initially contains --userns
|
||||||
* argument (may be empty), updated with userns path
|
* argument (may be empty), updated with userns path
|
||||||
* @netns: buffer of size PATH_MAX, initial contains --netns
|
* @netns: buffer of size PATH_MAX, initial contains --netns
|
||||||
* argument (may be empty), updated with netns path
|
* 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
|
* 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;
|
if (*netns_only && *userns) {
|
||||||
long pidval;
|
err("Both --userns and --netns-only given");
|
||||||
|
|
||||||
if (*netns) {
|
|
||||||
err("Both --netns and PID given");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pidval = strtol(arg, &endptr, 10);
|
if (*netns && optind != argc) {
|
||||||
|
err("Both --netns and PID or command given");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind + 1 == argc) {
|
||||||
|
char *endptr;
|
||||||
|
long pidval;
|
||||||
|
|
||||||
|
pidval = strtol(argv[optind], &endptr, 10);
|
||||||
if (!*endptr) {
|
if (!*endptr) {
|
||||||
/* Looks like a pid */
|
/* Looks like a pid */
|
||||||
if (pidval < 0 || pidval > INT_MAX) {
|
if (pidval < 0 || pidval > INT_MAX) {
|
||||||
err("Invalid PID %s", arg);
|
err("Invalid PID %s", argv[optind]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
|
snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
|
||||||
if (!*userns)
|
if (!*userns)
|
||||||
snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", pidval);
|
snprintf(userns, PATH_MAX, "/proc/%ld/ns/user",
|
||||||
return 0;
|
pidval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not a PID, later code will treat as a command */
|
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;
|
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;
|
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);
|
nfd = open(netns, O_RDONLY | O_CLOEXEC);
|
||||||
if (nfd < 0) {
|
if (nfd < 0) {
|
||||||
err("Couldn't open network namespace %s", netns);
|
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_netns_fd = nfd;
|
||||||
c->pasta_userns_fd = ufd;
|
c->pasta_userns_fd = ufd;
|
||||||
c->netns_only = !*userns;
|
|
||||||
|
|
||||||
NS_CALL(conf_ns_check, c);
|
NS_CALL(conf_ns_check, c);
|
||||||
|
|
||||||
|
@ -1194,7 +1207,7 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = conf_netns(netns, optarg);
|
ret = conf_netns_opt(netns, optarg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
break;
|
break;
|
||||||
|
@ -1573,17 +1586,9 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
drop_root(uid, gid);
|
drop_root(uid, gid);
|
||||||
|
|
||||||
if (c->mode == MODE_PASTA) {
|
if (c->mode == MODE_PASTA) {
|
||||||
if (*netns && optind != argc) {
|
if (conf_pasta_ns(&c->netns_only, userns, netns,
|
||||||
err("Both --netns and PID or command given");
|
optind, argc, argv) < 0)
|
||||||
usage(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) {
|
} else if (optind != argc) {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
}
|
}
|
||||||
|
@ -1597,10 +1602,6 @@ void conf(struct ctx *c, int argc, char **argv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
} else {
|
} else {
|
||||||
if (*userns) {
|
|
||||||
err("Both --userns and command given");
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
pasta_start_ns(c, argc - optind, argv + optind);
|
pasta_start_ns(c, argc - optind, argv + optind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue