From 969bb49cc36e65246bc7a77d96a8f05d06916388 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 6 Sep 2017 22:13:47 +1000 Subject: [PATCH] nsenter: do not resolve path in nsexec context With the addition of our new{uid,gid}map support, we used to call execvp(3) from inside nsexec. This would mean that the path resolution for the binaries would happen in nsexec. Move the resolution to the initial setup code, and pass the absolute path to nsexec. Signed-off-by: Aleksa Sarai --- libcontainer/nsenter/nsexec.c | 7 ++++--- utils_linux.go | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index aea9b8c6..a6a107e6 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -211,7 +211,7 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len) int child; /* - * If @app is NULL, execvp will segfault. Just check it here and bail (if + * If @app is NULL, execve will segfault. Just check it here and bail (if * we're in this path, the caller is already getting desparate and there * isn't a backup to this failing). This usually would be a configuration * or programming issue. @@ -226,6 +226,7 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len) if (!child) { #define MAX_ARGV 20 char *argv[MAX_ARGV]; + char *envp[] = {NULL}; char pid_fmt[16]; int argc = 0; char *next; @@ -252,8 +253,8 @@ static int try_mapping_tool(const char *app, int pid, char *map, size_t map_len) map = next + strspn(next, "\n "); } - execvp(app, argv); - bail("failed to execvp"); + execve(app, argv, envp); + bail("failed to execv"); } else { int status; diff --git a/utils_linux.go b/utils_linux.go index f1bb5944..85ec3c84 100644 --- a/utils_linux.go +++ b/utils_linux.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "os" + "os/exec" "path/filepath" "strconv" @@ -35,6 +36,9 @@ func loadFactory(context *cli.Context) (libcontainer.Factory, error) { if err != nil { return nil, err } + + // We default to cgroupfs, and can only use systemd if the system is a + // systemd box. cgroupManager := libcontainer.Cgroupfs if context.GlobalBool("systemd-cgroup") { if systemd.UseSystemd() { @@ -49,10 +53,22 @@ func loadFactory(context *cli.Context) (libcontainer.Factory, error) { intelRdtManager = nil } + // We resolve the paths for {newuidmap,newgidmap} from the context of runc, + // to avoid doing a path lookup in the nsexec context. TODO: The binary + // names are not currently configurable. + newuidmap, err := exec.LookPath("newuidmap") + if err != nil { + newuidmap = "" + } + newgidmap, err := exec.LookPath("newgidmap") + if err != nil { + newgidmap = "" + } + return libcontainer.New(abs, cgroupManager, intelRdtManager, libcontainer.CriuPath(context.GlobalString("criu")), - libcontainer.NewuidmapPath("newuidmap"), - libcontainer.NewgidmapPath("newgidmap")) + libcontainer.NewuidmapPath(newuidmap), + libcontainer.NewgidmapPath(newgidmap)) } // getContainer returns the specified container instance by loading it from state