Use common subprocSystem for executing commands
This commit is contained in:
parent
a30e2f107c
commit
fe7fe8591f
50
net.c
50
net.c
@ -42,6 +42,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "subproc.h"
|
||||
|
||||
#define IFACE_NAME "vs"
|
||||
|
||||
@ -114,51 +115,15 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
|
||||
return true;
|
||||
}
|
||||
#else // defined(NSJAIL_NL3_WITH_MACVLAN)
|
||||
static bool netSystemSbinIp(struct nsjconf_t *nsjconf, char *const *argv)
|
||||
static bool netSystemSbinIp(struct nsjconf_t *nsjconf, const char *const *argv)
|
||||
{
|
||||
if (nsjconf->clone_newnet == false) {
|
||||
LOG_W
|
||||
("CLONE_NEWNET not enabled. All changes would affect the global networking namespace");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
if (pid == -1) {
|
||||
PLOG_E("fork()");
|
||||
return false;
|
||||
}
|
||||
if (pid == 0) {
|
||||
execve("/sbin/ip", argv, environ);
|
||||
PLOG_E("execve('/sbin/ip'");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int status;
|
||||
while (wait4(pid, &status, __WALL, NULL) != pid) ;
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) == 0) {
|
||||
return true;
|
||||
}
|
||||
LOG_W("'/sbin/ip' returned with exit status: %d", WEXITSTATUS(status));
|
||||
return false;
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
LOG_W("'/sbin/ip' killed with signal: %d", WTERMSIG(status));
|
||||
return false;
|
||||
}
|
||||
if (WIFSTOPPED(status)) {
|
||||
continue;
|
||||
}
|
||||
if (WIFCONTINUED(status)) {
|
||||
continue;
|
||||
}
|
||||
LOG_W("Unknown exit status for '/sbin/ip' (pid=%d): %d", pid, status);
|
||||
kill(pid, SIGKILL);
|
||||
if (subprocSystem(argv, environ) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
|
||||
bool netInitNsFromParent(struct nsjconf_t * nsjconf, int pid)
|
||||
{
|
||||
if (nsjconf->clone_newnet == false) {
|
||||
return true;
|
||||
@ -171,7 +136,8 @@ bool netInitNsFromParent(struct nsjconf_t *nsjconf, int pid)
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
||||
|
||||
char *const argv_add[] =
|
||||
{ "ip", "link", "add", "link", (char *)nsjconf->iface, "name", IFACE_NAME, "netns",
|
||||
{ "/sbin/ip", "link", "add", "link", (char *)nsjconf->iface, "name", IFACE_NAME,
|
||||
"netns",
|
||||
pid_str, "type", "macvlan", "mode", "bridge", NULL
|
||||
};
|
||||
if (netSystemSbinIp(nsjconf, argv_add) == false) {
|
||||
|
65
subproc.c
65
subproc.c
@ -352,3 +352,68 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er
|
||||
netConnToText(fd_in, true /* remote */ , cs_addr, sizeof(cs_addr), NULL);
|
||||
LOG_I("PID: %d about to execute '%s' for %s", pid, nsjconf->argv[0], cs_addr);
|
||||
}
|
||||
|
||||
int subprocSystem(const char **argv, char **env)
|
||||
{
|
||||
bool exec_failed = false;
|
||||
|
||||
int sv[2];
|
||||
if (pipe2(sv, O_CLOEXEC) == -1) {
|
||||
PLOG_W("pipe2(sv, O_CLOEXEC");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
PLOG_W("fork()");
|
||||
close(sv[0]);
|
||||
close(sv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
close(sv[0]);
|
||||
execve(argv[0], (char *const *)argv, (char *const *)env);
|
||||
PLOG_W("execve('%s')", argv[0]);
|
||||
utilWriteToFd(sv[1], "A", 1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(sv[1]);
|
||||
char buf[1];
|
||||
if (utilReadFromFd(sv[0], buf, sizeof(buf)) > 0) {
|
||||
exec_failed = true;
|
||||
LOG_W("Couldn't execute '%s'", argv[0]);
|
||||
}
|
||||
close(sv[0]);
|
||||
|
||||
for (;;) {
|
||||
int status;
|
||||
int ret = wait4(pid, &status, __WALL, NULL);
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
if (ret == -1) {
|
||||
PLOG_W("wait4(pid=%d)", pid);
|
||||
return -1;
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
int exit_code = WEXITSTATUS(status);
|
||||
LOG_D("PID %d exited with exit code: %d", pid, exit_code);
|
||||
if (exec_failed == true) {
|
||||
return -1;
|
||||
} else if (exit_code == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
int exit_signal = WTERMSIG(status);
|
||||
LOG_W("PID %d killed by a signal: %d (%s)", pid, exit_signal,
|
||||
strsignal(exit_signal));
|
||||
return 2;
|
||||
}
|
||||
LOG_W("Unknown exit status: %d", status);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ void subprocRunChild(struct nsjconf_t *nsjconf, int fd_in, int fd_out, int fd_er
|
||||
int subprocCount(struct nsjconf_t *nsjconf);
|
||||
void subprocDisplay(struct nsjconf_t *nsjconf);
|
||||
void subprocKillAll(struct nsjconf_t *nsjconf);
|
||||
int subprocSystem(const char **argv, char **env);
|
||||
|
||||
/* Returns the exit code of the first failing subprocess, or 0 if none fail */
|
||||
int subprocReap(struct nsjconf_t *nsjconf);
|
||||
|
90
user.c
90
user.c
@ -32,6 +32,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "subproc.h"
|
||||
#include "util.h"
|
||||
|
||||
static bool userSetGroups(pid_t pid)
|
||||
@ -87,79 +88,70 @@ static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
return true;
|
||||
}
|
||||
|
||||
// use /usr/bin/newgidmap for writing the uid and gid map
|
||||
/* Use /usr/bin/newgidmap for writing the gid map */
|
||||
static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
{
|
||||
char cmd_buf[1024];
|
||||
char *cmd_ptr = cmd_buf;
|
||||
size_t len = sizeof(cmd_buf);
|
||||
int write_size;
|
||||
char pid_str[16];
|
||||
char ins_gid_str[16];
|
||||
char out_gid_str[16];
|
||||
|
||||
write_size = snprintf(cmd_ptr, len, "/usr/bin/newgidmap %lu %lu %lu 1",
|
||||
(unsigned long)pid,
|
||||
(unsigned long)nsjconf->inside_gid,
|
||||
(unsigned long)nsjconf->outside_gid);
|
||||
if (write_size <= 0 || (size_t) write_size > len) {
|
||||
LOG_E("snprintf writing the new{u,g}idmap command failed");
|
||||
return false;
|
||||
}
|
||||
cmd_ptr += write_size;
|
||||
len -= write_size;
|
||||
snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)pid);
|
||||
snprintf(ins_gid_str, sizeof(ins_gid_str), "%lu", (unsigned long)nsjconf->inside_gid);
|
||||
snprintf(out_gid_str, sizeof(out_gid_str), "%lu", (unsigned long)nsjconf->outside_gid);
|
||||
|
||||
const char *argv[1024] = { "/usr/bin/newgidmap", pid_str, ins_gid_str, out_gid_str, "1" };
|
||||
size_t argv_idx = 5;
|
||||
|
||||
struct mapping_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->gid_mappings, pointers) {
|
||||
write_size = snprintf(cmd_ptr, len, " %s %s %s",
|
||||
p->inside_id, p->outside_id, p->count);
|
||||
if (write_size <= 0 || (size_t) write_size > len) {
|
||||
LOG_E("snprintf writing the new{u,g}idmap command failed");
|
||||
if ((argv_idx + 4) >= ARRAYSIZE(argv)) {
|
||||
LOG_W("Number of arguments to '/usr/bin/newgidmap' too big");
|
||||
return false;
|
||||
}
|
||||
cmd_ptr += write_size;
|
||||
len -= write_size;
|
||||
}
|
||||
|
||||
if (system(cmd_buf) != 0) {
|
||||
LOG_E("system('%s') failed", cmd_buf);
|
||||
while (1) ;
|
||||
argv[argv_idx++] = p->inside_id;
|
||||
argv[argv_idx++] = p->outside_id;
|
||||
argv[argv_idx++] = p->count;
|
||||
}
|
||||
argv[argv_idx++] = NULL;
|
||||
|
||||
if (subprocSystem(argv, environ) != 0) {
|
||||
LOG_E("'/usr/bin/newgidmap' failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// use /usr/bin/newuidmap for writing the uid and gid map
|
||||
/* Use /usr/bin/newuidmap for writing the uid map */
|
||||
static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid)
|
||||
{
|
||||
char cmd_buf[1024];
|
||||
char *cmd_ptr = cmd_buf;
|
||||
size_t len = sizeof(cmd_buf);
|
||||
int write_size;
|
||||
char pid_str[16];
|
||||
char ins_uid_str[16];
|
||||
char out_uid_str[16];
|
||||
|
||||
write_size = snprintf(cmd_ptr, len, "/usr/bin/newuidmap %lu %lu %lu 1",
|
||||
(unsigned long)pid,
|
||||
(unsigned long)nsjconf->inside_uid,
|
||||
(unsigned long)nsjconf->outside_uid);
|
||||
if (write_size <= 0 || (size_t) write_size > len) {
|
||||
LOG_E("snprintf writing the new{u,g}idmap command failed");
|
||||
return false;
|
||||
}
|
||||
cmd_ptr += write_size;
|
||||
len -= write_size;
|
||||
snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)pid);
|
||||
snprintf(ins_uid_str, sizeof(ins_uid_str), "%lu", (unsigned long)nsjconf->inside_uid);
|
||||
snprintf(out_uid_str, sizeof(out_uid_str), "%lu", (unsigned long)nsjconf->outside_uid);
|
||||
|
||||
const char *argv[1024] = { "/usr/bin/newuidmap", pid_str, ins_uid_str, out_uid_str, "1" };
|
||||
size_t argv_idx = 5;
|
||||
|
||||
struct mapping_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->uid_mappings, pointers) {
|
||||
write_size = snprintf(cmd_ptr, len, " %s %s %s",
|
||||
p->inside_id, p->outside_id, p->count);
|
||||
if (write_size <= 0 || (size_t) write_size > len) {
|
||||
LOG_E("snprintf writing the new{u,g}idmap command failed");
|
||||
if ((argv_idx + 4) >= ARRAYSIZE(argv)) {
|
||||
LOG_W("Number of arguments to '/usr/bin/newuidmap' too big");
|
||||
return false;
|
||||
}
|
||||
cmd_ptr += write_size;
|
||||
len -= write_size;
|
||||
}
|
||||
|
||||
if (system(cmd_buf) != 0) {
|
||||
LOG_E("system('%s') failed", cmd_buf);
|
||||
argv[argv_idx++] = p->inside_id;
|
||||
argv[argv_idx++] = p->outside_id;
|
||||
argv[argv_idx++] = p->count;
|
||||
}
|
||||
argv[argv_idx++] = NULL;
|
||||
|
||||
if (subprocSystem(argv, environ) != 0) {
|
||||
LOG_E("'/usr/bin/newuidmap' failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user