Skip to content

Commit

Permalink
create-sandbox: join the target userns if euid!=0
Browse files Browse the repository at this point in the history
when not running in a user namespace, attempt to join the target user
namespace to gain enough privileges to create the sandbox.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Jul 26, 2019
1 parent 6f46a05 commit 45072b0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
39 changes: 30 additions & 9 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@
// + 100 .
#define NETWORK_PREFIX_MAX (25)

static int nsenter(pid_t target_pid, char *netns, char *userns)
static int nsenter(pid_t target_pid, char *netns, char *userns,
bool only_userns)
{
int usernsfd = -1, netnsfd;
if (!netns) {
int usernsfd = -1, netnsfd = -1;
if (!only_userns && !netns) {
if (asprintf(&netns, "/proc/%d/ns/net", target_pid) < 0) {
perror("cannot get netns path");
return -1;
Expand All @@ -48,7 +49,7 @@ static int nsenter(pid_t target_pid, char *netns, char *userns)
return -1;
}
}
if ((netnsfd = open(netns, O_RDONLY)) < 0) {
if (!only_userns && (netnsfd = open(netns, O_RDONLY)) < 0) {
perror(netns);
return netnsfd;
}
Expand All @@ -58,10 +59,14 @@ static int nsenter(pid_t target_pid, char *netns, char *userns)
}

if (usernsfd != -1) {
setns(usernsfd, CLONE_NEWUSER);
int r = setns(usernsfd, CLONE_NEWUSER);
if (only_userns && r < 0) {
perror("setns(CLONE_NEWUSER)");
return -1;
}
close(usernsfd);
}
if (setns(netnsfd, CLONE_NEWNET) < 0) {
if (netnsfd != -1 && setns(netnsfd, CLONE_NEWNET) < 0) {
perror("setns(CLONE_NEWNET)");
return -1;
}
Expand Down Expand Up @@ -194,7 +199,7 @@ static int child(int sock, pid_t target_pid, bool do_config_network,
struct slirp4netns_config *cfg)
{
int rc, tapfd;
if ((rc = nsenter(target_pid, netns_path, userns_path)) < 0) {
if ((rc = nsenter(target_pid, netns_path, userns_path, false)) < 0) {
return rc;
}
if ((tapfd = open_tap(tapname)) < 0) {
Expand Down Expand Up @@ -247,7 +252,7 @@ static int recvfd(int sock)
}

static int parent(int sock, int ready_fd, int exit_fd, const char *api_socket,
struct slirp4netns_config *cfg)
struct slirp4netns_config *cfg, pid_t target_pid)
{
int rc, tapfd;
if ((tapfd = recvfd(sock)) < 0) {
Expand All @@ -271,6 +276,22 @@ static int parent(int sock, int ready_fd, int exit_fd, const char *api_socket,
"--disable-host-loopback to prohibit connecting to 127.0.0.1:*)\n",
inet_ntoa(cfg->vhost));
}
if (cfg->create_sandbox && geteuid() != 0) {
if ((rc = nsenter(target_pid, NULL, NULL, true)) < 0) {
close(tapfd);
return rc;
}
if ((rc = setegid(0)) < 0) {
fprintf(stderr, "setegid(0)\n");
close(tapfd);
return rc;
}
if ((rc = seteuid(0)) < 0) {
fprintf(stderr, "seteuid(0)\n");
close(tapfd);
return rc;
}
}
if ((rc = do_slirp(tapfd, ready_fd, exit_fd, api_socket, cfg)) < 0) {
fprintf(stderr, "do_slirp failed\n");
close(tapfd);
Expand Down Expand Up @@ -693,7 +714,7 @@ int main(int argc, char *const argv[])
goto finish;
}
if (parent(sv[0], options.ready_fd, options.exit_fd, options.api_socket,
&slirp4netns_config) < 0) {
&slirp4netns_config, options.target_pid) < 0) {
fprintf(stderr, "parent failed\n");
exit_status = EXIT_FAILURE;
goto finish;
Expand Down
2 changes: 1 addition & 1 deletion tests/test-slirp4netns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ child=$!

wait_for_network_namespace $child

nsenter --preserve-credentials -U --target=$child slirp4netns --ready-fd=3 --create-sandbox $child tun11 3>ready.file &
slirp4netns --ready-fd=3 --create-sandbox $child tun11 3>ready.file &
slirp_pid=$!

# Wait that the sandbox is created
Expand Down

0 comments on commit 45072b0

Please sign in to comment.