2014-12-10 16:39:00 +08:00
|
|
|
package integration
|
|
|
|
|
|
|
|
import (
|
2015-03-05 08:04:20 +08:00
|
|
|
"bytes"
|
2015-09-14 08:35:22 +08:00
|
|
|
"fmt"
|
2015-03-05 08:04:20 +08:00
|
|
|
"io"
|
2014-12-10 16:39:00 +08:00
|
|
|
"os"
|
2015-08-27 07:37:24 +08:00
|
|
|
"strconv"
|
2014-12-10 16:39:00 +08:00
|
|
|
"strings"
|
|
|
|
"testing"
|
2015-03-05 08:04:20 +08:00
|
|
|
"time"
|
2014-12-10 16:39:00 +08:00
|
|
|
|
2015-06-22 10:29:59 +08:00
|
|
|
"github.com/opencontainers/runc/libcontainer"
|
2015-09-14 08:35:22 +08:00
|
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
2014-12-10 16:39:00 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestExecIn(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
2015-02-17 05:09:00 +08:00
|
|
|
rootfs, err := newRootfs()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2014-12-10 16:39:00 +08:00
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
2015-02-17 05:09:00 +08:00
|
|
|
container, err := newContainer(config)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-17 05:09:00 +08:00
|
|
|
defer container.Destroy()
|
2015-02-23 17:26:43 +08:00
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-17 05:09:00 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-02-23 17:26:43 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
2015-02-17 05:09:00 +08:00
|
|
|
}
|
2015-02-23 17:26:43 +08:00
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-23 17:26:43 +08:00
|
|
|
|
|
|
|
buffers := newStdBuffers()
|
|
|
|
ps := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-02-17 05:09:00 +08:00
|
|
|
Args: []string{"ps"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: buffers.Stdin,
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: buffers.Stderr,
|
|
|
|
}
|
2015-05-21 01:10:10 +08:00
|
|
|
|
2015-02-23 17:26:43 +08:00
|
|
|
err = container.Start(ps)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(ps, t)
|
2015-02-23 17:26:43 +08:00
|
|
|
stdinW.Close()
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(process, t)
|
|
|
|
|
2014-12-10 16:39:00 +08:00
|
|
|
out := buffers.Stdout.String()
|
2015-02-23 17:26:43 +08:00
|
|
|
if !strings.Contains(out, "cat") || !strings.Contains(out, "ps") {
|
2014-12-10 16:39:00 +08:00
|
|
|
t.Fatalf("unexpected running process, output %q", out)
|
|
|
|
}
|
|
|
|
}
|
2014-12-10 17:13:31 +08:00
|
|
|
|
|
|
|
func TestExecInRlimit(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
2015-02-17 05:09:00 +08:00
|
|
|
rootfs, err := newRootfs()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2014-12-10 17:13:31 +08:00
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
2015-02-17 05:09:00 +08:00
|
|
|
container, err := newContainer(config)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-17 05:09:00 +08:00
|
|
|
defer container.Destroy()
|
2015-02-23 17:26:43 +08:00
|
|
|
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-17 05:09:00 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-02-23 17:26:43 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
2015-02-17 05:09:00 +08:00
|
|
|
}
|
2015-02-23 17:26:43 +08:00
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-23 17:26:43 +08:00
|
|
|
|
|
|
|
buffers := newStdBuffers()
|
|
|
|
ps := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-02-17 05:09:00 +08:00
|
|
|
Args: []string{"/bin/sh", "-c", "ulimit -n"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: buffers.Stdin,
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: buffers.Stderr,
|
|
|
|
}
|
2015-02-23 17:26:43 +08:00
|
|
|
err = container.Start(ps)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(ps, t)
|
|
|
|
|
2015-02-23 17:26:43 +08:00
|
|
|
stdinW.Close()
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(process, t)
|
|
|
|
|
2014-12-10 17:13:31 +08:00
|
|
|
out := buffers.Stdout.String()
|
2015-03-04 17:10:53 +08:00
|
|
|
if limit := strings.TrimSpace(out); limit != "1025" {
|
|
|
|
t.Fatalf("expected rlimit to be 1025, got %s", limit)
|
2014-12-10 17:13:31 +08:00
|
|
|
}
|
|
|
|
}
|
2015-02-28 07:55:53 +08:00
|
|
|
|
|
|
|
func TestExecInError(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-28 07:55:53 +08:00
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
container, err := newContainer(config)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-28 07:55:53 +08:00
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-28 07:55:53 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-02-28 07:55:53 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer func() {
|
|
|
|
stdinW.Close()
|
|
|
|
if _, err := process.Wait(); err != nil {
|
|
|
|
t.Log(err)
|
|
|
|
}
|
|
|
|
}()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-02-28 07:55:53 +08:00
|
|
|
|
2016-03-10 09:48:12 +08:00
|
|
|
for i := 0; i < 42; i++ {
|
|
|
|
var out bytes.Buffer
|
|
|
|
unexistent := &libcontainer.Process{
|
|
|
|
Cwd: "/",
|
|
|
|
Args: []string{"unexistent"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdout: &out,
|
|
|
|
}
|
|
|
|
err = container.Start(unexistent)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Should be an error")
|
|
|
|
}
|
|
|
|
if !strings.Contains(err.Error(), "executable file not found") {
|
|
|
|
t.Fatalf("Should be error about not found executable, got %s", err)
|
|
|
|
}
|
|
|
|
if !bytes.Contains(out.Bytes(), []byte("executable file not found")) {
|
|
|
|
t.Fatalf("executable file not found error not delivered to stdio:\n%s", out.String())
|
2015-10-06 07:38:27 +08:00
|
|
|
}
|
2016-02-26 06:30:49 +08:00
|
|
|
}
|
2015-02-28 07:55:53 +08:00
|
|
|
}
|
2015-03-05 08:04:20 +08:00
|
|
|
|
|
|
|
func TestExecInTTY(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
container, err := newContainer(config)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-03-05 08:04:20 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
|
|
|
|
var stdout bytes.Buffer
|
|
|
|
ps := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-03-05 08:04:20 +08:00
|
|
|
Args: []string{"ps"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
}
|
|
|
|
console, err := ps.NewConsole(0)
|
|
|
|
copy := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
io.Copy(&stdout, console)
|
|
|
|
close(copy)
|
|
|
|
}()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
err = container.Start(ps)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-05 08:04:20 +08:00
|
|
|
select {
|
|
|
|
case <-time.After(5 * time.Second):
|
|
|
|
t.Fatal("Waiting for copy timed out")
|
|
|
|
case <-copy:
|
|
|
|
}
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(ps, t)
|
|
|
|
|
2015-03-05 08:04:20 +08:00
|
|
|
stdinW.Close()
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(process, t)
|
|
|
|
|
2015-03-05 08:04:20 +08:00
|
|
|
out := stdout.String()
|
|
|
|
if !strings.Contains(out, "cat") || !strings.Contains(string(out), "ps") {
|
|
|
|
t.Fatalf("unexpected running process, output %q", out)
|
|
|
|
}
|
|
|
|
}
|
2015-03-06 06:33:13 +08:00
|
|
|
|
|
|
|
func TestExecInEnvironment(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-06 06:33:13 +08:00
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
container, err := newContainer(config)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-06 06:33:13 +08:00
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-06 06:33:13 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-03-06 06:33:13 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-03-06 06:33:13 +08:00
|
|
|
|
|
|
|
buffers := newStdBuffers()
|
|
|
|
process2 := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-03-06 06:33:13 +08:00
|
|
|
Args: []string{"env"},
|
|
|
|
Env: []string{
|
|
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
|
|
"DEBUG=true",
|
|
|
|
"DEBUG=false",
|
|
|
|
"ENV=test",
|
|
|
|
},
|
|
|
|
Stdin: buffers.Stdin,
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: buffers.Stderr,
|
|
|
|
}
|
|
|
|
err = container.Start(process2)
|
2015-04-05 04:29:50 +08:00
|
|
|
ok(t, err)
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(process2, t)
|
|
|
|
|
2015-03-06 06:33:13 +08:00
|
|
|
stdinW.Close()
|
2015-05-21 01:10:10 +08:00
|
|
|
waitProcess(process, t)
|
|
|
|
|
2015-03-06 06:33:13 +08:00
|
|
|
out := buffers.Stdout.String()
|
|
|
|
// check execin's process environment
|
|
|
|
if !strings.Contains(out, "DEBUG=false") ||
|
|
|
|
!strings.Contains(out, "ENV=test") ||
|
|
|
|
!strings.Contains(out, "HOME=/root") ||
|
|
|
|
!strings.Contains(out, "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") ||
|
|
|
|
strings.Contains(out, "DEBUG=true") {
|
|
|
|
t.Fatalf("unexpected running process, output %q", out)
|
|
|
|
}
|
|
|
|
}
|
2015-04-11 02:23:09 +08:00
|
|
|
|
|
|
|
func TestExecinPassExtraFiles(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
container, err := newContainer(config)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-04-11 02:23:09 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var stdout bytes.Buffer
|
|
|
|
pipeout1, pipein1, err := os.Pipe()
|
|
|
|
pipeout2, pipein2, err := os.Pipe()
|
|
|
|
inprocess := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-04-11 02:23:09 +08:00
|
|
|
Args: []string{"sh", "-c", "cd /proc/$$/fd; echo -n *; echo -n 1 >3; echo -n 2 >4"},
|
|
|
|
Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
|
|
|
|
ExtraFiles: []*os.File{pipein1, pipein2},
|
|
|
|
Stdin: nil,
|
|
|
|
Stdout: &stdout,
|
|
|
|
}
|
|
|
|
err = container.Start(inprocess)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
waitProcess(inprocess, t)
|
2015-04-14 20:56:05 +08:00
|
|
|
stdinW.Close()
|
|
|
|
waitProcess(process, t)
|
2015-04-11 02:23:09 +08:00
|
|
|
|
|
|
|
out := string(stdout.Bytes())
|
|
|
|
// fd 5 is the directory handle for /proc/$$/fd
|
|
|
|
if out != "0 1 2 3 4 5" {
|
|
|
|
t.Fatalf("expected to have the file descriptors '0 1 2 3 4 5' passed to exec, got '%s'", out)
|
|
|
|
}
|
|
|
|
var buf = []byte{0}
|
|
|
|
_, err = pipeout1.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
out1 := string(buf)
|
|
|
|
if out1 != "1" {
|
|
|
|
t.Fatalf("expected first pipe to receive '1', got '%s'", out1)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = pipeout2.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
out2 := string(buf)
|
|
|
|
if out2 != "2" {
|
|
|
|
t.Fatalf("expected second pipe to receive '2', got '%s'", out2)
|
|
|
|
}
|
|
|
|
}
|
2015-08-27 07:37:24 +08:00
|
|
|
|
|
|
|
func TestExecInOomScoreAdj(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
|
|
|
ok(t, err)
|
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
config.OomScoreAdj = 200
|
|
|
|
container, err := newContainer(config)
|
|
|
|
ok(t, err)
|
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
|
|
|
ok(t, err)
|
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-08-27 07:37:24 +08:00
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
|
|
|
ok(t, err)
|
|
|
|
|
|
|
|
buffers := newStdBuffers()
|
|
|
|
ps := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2015-08-27 07:37:24 +08:00
|
|
|
Args: []string{"/bin/sh", "-c", "cat /proc/self/oom_score_adj"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: buffers.Stdin,
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: buffers.Stderr,
|
|
|
|
}
|
|
|
|
err = container.Start(ps)
|
|
|
|
ok(t, err)
|
|
|
|
waitProcess(ps, t)
|
|
|
|
|
|
|
|
stdinW.Close()
|
|
|
|
waitProcess(process, t)
|
|
|
|
|
|
|
|
out := buffers.Stdout.String()
|
|
|
|
if oomScoreAdj := strings.TrimSpace(out); oomScoreAdj != strconv.Itoa(config.OomScoreAdj) {
|
|
|
|
t.Fatalf("expected oomScoreAdj to be %d, got %s", config.OomScoreAdj, oomScoreAdj)
|
|
|
|
}
|
|
|
|
}
|
2015-09-14 08:35:22 +08:00
|
|
|
|
|
|
|
func TestExecInUserns(t *testing.T) {
|
|
|
|
if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) {
|
|
|
|
t.Skip("userns is unsupported")
|
|
|
|
}
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
rootfs, err := newRootfs()
|
|
|
|
ok(t, err)
|
|
|
|
defer remove(rootfs)
|
|
|
|
config := newTemplateConfig(rootfs)
|
|
|
|
config.UidMappings = []configs.IDMap{{0, 0, 1000}}
|
|
|
|
config.GidMappings = []configs.IDMap{{0, 0, 1000}}
|
|
|
|
config.Namespaces = append(config.Namespaces, configs.Namespace{Type: configs.NEWUSER})
|
|
|
|
container, err := newContainer(config)
|
|
|
|
ok(t, err)
|
|
|
|
defer container.Destroy()
|
|
|
|
|
|
|
|
// Execute a first process in the container
|
|
|
|
stdinR, stdinW, err := os.Pipe()
|
|
|
|
ok(t, err)
|
|
|
|
|
|
|
|
process := &libcontainer.Process{
|
|
|
|
Cwd: "/",
|
|
|
|
Args: []string{"cat"},
|
|
|
|
Env: standardEnvironment,
|
|
|
|
Stdin: stdinR,
|
|
|
|
}
|
|
|
|
err = container.Start(process)
|
|
|
|
stdinR.Close()
|
|
|
|
defer stdinW.Close()
|
|
|
|
ok(t, err)
|
|
|
|
|
|
|
|
initPID, err := process.Pid()
|
|
|
|
ok(t, err)
|
|
|
|
initUserns, err := os.Readlink(fmt.Sprintf("/proc/%d/ns/user", initPID))
|
|
|
|
ok(t, err)
|
|
|
|
|
|
|
|
buffers := newStdBuffers()
|
|
|
|
process2 := &libcontainer.Process{
|
|
|
|
Cwd: "/",
|
|
|
|
Args: []string{"readlink", "/proc/self/ns/user"},
|
|
|
|
Env: []string{
|
|
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
|
|
},
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: os.Stderr,
|
|
|
|
}
|
|
|
|
err = container.Start(process2)
|
|
|
|
ok(t, err)
|
|
|
|
waitProcess(process2, t)
|
|
|
|
stdinW.Close()
|
|
|
|
waitProcess(process, t)
|
|
|
|
|
|
|
|
if out := strings.TrimSpace(buffers.Stdout.String()); out != initUserns {
|
|
|
|
t.Errorf("execin userns(%s), wanted %s", out, initUserns)
|
|
|
|
}
|
|
|
|
}
|