From 9751b800a6835f7febf99f1dee22a5aedd43f381 Mon Sep 17 00:00:00 2001
From: Nicolas Lacasse <nlacasse@google.com>
Date: Fri, 7 Sep 2018 17:38:34 -0700
Subject: runsc: Support multi-container exec.

We must use a context.Context with a Root Dirent that corresponds to the
container's chroot. Previously we were using the root context, which does not
have a chroot.

Getting the correct context required refactoring some of the path-lookup code.
We can't lookup the path without a context.Context, which requires
kernel.CreateProcArgs, which we only get inside control.Execute.  So we have to
do the path lookup much later than we previously were.

PiperOrigin-RevId: 212064734
Change-Id: I84a5cfadacb21fd9c3ab9c393f7e308a40b9b537
---
 pkg/sentry/control/proc.go | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

(limited to 'pkg/sentry/control')

diff --git a/pkg/sentry/control/proc.go b/pkg/sentry/control/proc.go
index 6949a3ae5..289b8ba0e 100644
--- a/pkg/sentry/control/proc.go
+++ b/pkg/sentry/control/proc.go
@@ -54,6 +54,11 @@ type ExecArgs struct {
 	// Envv is a list of environment variables.
 	Envv []string `json:"envv"`
 
+	// Root defines the root directory for the new process. A reference on
+	// Root must be held for the lifetime of the ExecArgs. If Root is nil,
+	// it will default to the VFS root.
+	Root *fs.Dirent
+
 	// WorkingDirectory defines the working directory for the new process.
 	WorkingDirectory string `json:"wd"`
 
@@ -99,6 +104,7 @@ func (proc *Proc) Exec(args *ExecArgs, waitStatus *uint32) error {
 		Argv:                    args.Argv,
 		Envv:                    args.Envv,
 		WorkingDirectory:        args.WorkingDirectory,
+		Root:                    args.Root,
 		Credentials:             creds,
 		FDMap:                   fdm,
 		Umask:                   0022,
@@ -109,8 +115,18 @@ func (proc *Proc) Exec(args *ExecArgs, waitStatus *uint32) error {
 		AbstractSocketNamespace: proc.Kernel.RootAbstractSocketNamespace(),
 	}
 	ctx := initArgs.NewContext(proc.Kernel)
-	mounter := fs.FileOwnerFromContext(ctx)
 
+	if initArgs.Filename == "" {
+		// Get the full path to the filename from the PATH env variable.
+		paths := fs.GetPath(initArgs.Envv)
+		f, err := proc.Kernel.RootMountNamespace().ResolveExecutablePath(ctx, initArgs.WorkingDirectory, initArgs.Argv[0], paths)
+		if err != nil {
+			return fmt.Errorf("error finding executable %q in PATH %v: %v", initArgs.Argv[0], paths, err)
+		}
+		initArgs.Filename = f
+	}
+
+	mounter := fs.FileOwnerFromContext(ctx)
 	for appFD, f := range args.FilePayload.Files {
 		enableIoctl := args.StdioIsPty && appFD <= 2
 
-- 
cgit v1.2.3