Add tests to verify gofer is chroot'ed
PiperOrigin-RevId: 216472439 Change-Id: Ic4cb86c8e0a9cb022d3ceed9dc5615266c307cf9
This commit is contained in:
parent
c36d2ef373
commit
20508bafb8
|
@ -85,7 +85,7 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
|
|||
if err != nil {
|
||||
Fatalf("error loading container %q: %v", id, err)
|
||||
}
|
||||
if candidate.Pid() == d.pid {
|
||||
if candidate.SandboxPid() == d.pid {
|
||||
c = candidate
|
||||
break
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func (l *List) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
|
|||
for _, c := range containers {
|
||||
fmt.Fprintf(w, "%s\t%d\t%s\t%s\t%s\t%s\n",
|
||||
c.ID,
|
||||
c.Pid(),
|
||||
c.SandboxPid(),
|
||||
c.Status,
|
||||
c.BundleDir,
|
||||
c.CreatedAt.Format(time.RFC3339Nano),
|
||||
|
|
|
@ -316,7 +316,7 @@ func Create(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSo
|
|||
// Write the PID file. Containerd considers the create complete after
|
||||
// this file is created, so it must be the last thing we do.
|
||||
if pidFile != "" {
|
||||
if err := ioutil.WriteFile(pidFile, []byte(strconv.Itoa(c.Pid())), 0644); err != nil {
|
||||
if err := ioutil.WriteFile(pidFile, []byte(strconv.Itoa(c.SandboxPid())), 0644); err != nil {
|
||||
c.Destroy()
|
||||
return nil, fmt.Errorf("error writing PID file: %v", err)
|
||||
}
|
||||
|
@ -426,9 +426,9 @@ func (c *Container) Event() (*boot.Event, error) {
|
|||
return c.Sandbox.Event(c.ID)
|
||||
}
|
||||
|
||||
// Pid returns the Pid of the sandbox the container is running in, or -1 if the
|
||||
// SandboxPid returns the Pid of the sandbox the container is running in, or -1 if the
|
||||
// container is not running.
|
||||
func (c *Container) Pid() int {
|
||||
func (c *Container) SandboxPid() int {
|
||||
if err := c.requireStatus("get PID", Created, Running, Paused); err != nil {
|
||||
return -1
|
||||
}
|
||||
|
@ -566,7 +566,7 @@ func (c *Container) State() specs.State {
|
|||
Version: specs.Version,
|
||||
ID: c.ID,
|
||||
Status: c.Status.String(),
|
||||
Pid: c.Pid(),
|
||||
Pid: c.SandboxPid(),
|
||||
Bundle: c.BundleDir,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
|
@ -91,6 +92,75 @@ func TestChroot(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestChrootGofer(t *testing.T) {
|
||||
d := testutil.MakeDocker("chroot-test")
|
||||
if err := d.Run("alpine", "sleep", "10000"); err != nil {
|
||||
t.Fatalf("docker run failed: %v", err)
|
||||
}
|
||||
defer d.CleanUp()
|
||||
|
||||
// It's tricky to find gofers. Get sandbox PID first, then find parent. From
|
||||
// parent get all immediate children, remove the sandbox, and everything else
|
||||
// are gofers.
|
||||
sandPID, err := d.SandboxPid()
|
||||
if err != nil {
|
||||
t.Fatalf("Docker.SandboxPid(): %v", err)
|
||||
}
|
||||
|
||||
// Find sandbox's parent PID.
|
||||
cmd := fmt.Sprintf("grep PPid /proc/%d/status | awk '{print $2}'", sandPID)
|
||||
parent, err := exec.Command("sh", "-c", cmd).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to fetch runsc (%d) parent PID: %v, out:\n%s", sandPID, err, string(parent))
|
||||
}
|
||||
parentPID, err := strconv.Atoi(strings.TrimSpace(string(parent)))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse PPID %q: %v", string(parent), err)
|
||||
}
|
||||
|
||||
// Get all children from parent.
|
||||
childrenOut, err := exec.Command("/usr/bin/pgrep", "-P", strconv.Itoa(parentPID)).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to fetch containerd-shim children: %v", err)
|
||||
}
|
||||
children := strings.Split(strings.TrimSpace(string(childrenOut)), "\n")
|
||||
|
||||
// This where the root directory is mapped on the host and that's where the
|
||||
// gofer must have chroot'd to.
|
||||
root, err := d.RootDirInHost()
|
||||
if err != nil {
|
||||
t.Fatalf("Docker.RootDirInHost(): %v", err)
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
childPID, err := strconv.Atoi(child)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse child PID %q: %v", child, err)
|
||||
}
|
||||
if childPID == sandPID {
|
||||
// Skip the sandbox, all other immediate children are gofers.
|
||||
continue
|
||||
}
|
||||
|
||||
// Check that gofer is chroot'ed.
|
||||
chroot, err := filepath.EvalSymlinks(filepath.Join("/proc", child, "root"))
|
||||
if err != nil {
|
||||
t.Fatalf("error resolving /proc/<pid>/root symlink: %v", err)
|
||||
}
|
||||
if root != chroot {
|
||||
t.Errorf("gofer chroot is wrong, want: %q, got: %q", root, chroot)
|
||||
}
|
||||
|
||||
path, err := filepath.EvalSymlinks(filepath.Join("/proc", child, "cwd"))
|
||||
if err != nil {
|
||||
t.Fatalf("error resolving /proc/<pid>/cwd symlink: %v", err)
|
||||
}
|
||||
if root != path {
|
||||
t.Errorf("gofer current dir is wrong, want: %q, got: %q", root, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.EnsureSupportedDockerVersion()
|
||||
|
||||
|
|
|
@ -280,6 +280,15 @@ func (d *Docker) SandboxPid() (int, error) {
|
|||
return pid, nil
|
||||
}
|
||||
|
||||
// RootDirInHost returns where the root directory is mapped on the host.
|
||||
func (d *Docker) RootDirInHost() (string, error) {
|
||||
out, err := do("inspect", "-f={{.GraphDriver.Data.MergedDir}}", d.Name)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error retrieving pid: %v", err)
|
||||
}
|
||||
return strings.TrimSuffix(string(out), "\n"), nil
|
||||
}
|
||||
|
||||
// WaitForOutput calls 'docker logs' to retrieve containers output and searches
|
||||
// for the given pattern.
|
||||
func (d *Docker) WaitForOutput(pattern string, timeout time.Duration) (string, error) {
|
||||
|
|
Loading…
Reference in New Issue