github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/nsenter/nsenter_test.go (about)

     1  package nsenter
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"syscall"
    13  	"testing"
    14  
    15  	"github.com/opencontainers/runc/libcontainer"
    16  	"github.com/vishvananda/netlink/nl"
    17  )
    18  
    19  type pid struct {
    20  	Pid int `json:"Pid"`
    21  }
    22  
    23  func TestNsenterValidPaths(t *testing.T) {
    24  	args := []string{"nsenter-exec"}
    25  	parent, child, err := newPipe()
    26  	if err != nil {
    27  		t.Fatalf("failed to create pipe %v", err)
    28  	}
    29  
    30  	namespaces := []string{
    31  		// join pid ns of the current process
    32  		fmt.Sprintf("pid:/proc/%d/ns/pid", os.Getpid()),
    33  	}
    34  	cmd := &exec.Cmd{
    35  		Path:       os.Args[0],
    36  		Args:       args,
    37  		ExtraFiles: []*os.File{child},
    38  		Env:        []string{"_LIBCONTAINER_INITPIPE=3"},
    39  		Stdout:     os.Stdout,
    40  		Stderr:     os.Stderr,
    41  	}
    42  
    43  	if err := cmd.Start(); err != nil {
    44  		t.Fatalf("nsenter failed to start %v", err)
    45  	}
    46  	// write cloneFlags
    47  	r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0)
    48  	r.AddData(&libcontainer.Int32msg{
    49  		Type:  libcontainer.CloneFlagsAttr,
    50  		Value: uint32(syscall.CLONE_NEWNET),
    51  	})
    52  	r.AddData(&libcontainer.Bytemsg{
    53  		Type:  libcontainer.NsPathsAttr,
    54  		Value: []byte(strings.Join(namespaces, ",")),
    55  	})
    56  	if _, err := io.Copy(parent, bytes.NewReader(r.Serialize())); err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	decoder := json.NewDecoder(parent)
    61  	var pid *pid
    62  
    63  	if err := cmd.Wait(); err != nil {
    64  		t.Fatalf("nsenter exits with a non-zero exit status")
    65  	}
    66  	if err := decoder.Decode(&pid); err != nil {
    67  		dir, _ := ioutil.ReadDir(fmt.Sprintf("/proc/%d/ns", os.Getpid()))
    68  		for _, d := range dir {
    69  			t.Log(d.Name())
    70  		}
    71  		t.Fatalf("%v", err)
    72  	}
    73  
    74  	p, err := os.FindProcess(pid.Pid)
    75  	if err != nil {
    76  		t.Fatalf("%v", err)
    77  	}
    78  	p.Wait()
    79  }
    80  
    81  func TestNsenterInvalidPaths(t *testing.T) {
    82  	args := []string{"nsenter-exec"}
    83  	parent, child, err := newPipe()
    84  	if err != nil {
    85  		t.Fatalf("failed to create pipe %v", err)
    86  	}
    87  
    88  	namespaces := []string{
    89  		// join pid ns of the current process
    90  		fmt.Sprintf("pid:/proc/%d/ns/pid", -1),
    91  	}
    92  	cmd := &exec.Cmd{
    93  		Path:       os.Args[0],
    94  		Args:       args,
    95  		ExtraFiles: []*os.File{child},
    96  		Env:        []string{"_LIBCONTAINER_INITPIPE=3"},
    97  	}
    98  
    99  	if err := cmd.Start(); err != nil {
   100  		t.Fatal(err)
   101  	}
   102  	// write cloneFlags
   103  	r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0)
   104  	r.AddData(&libcontainer.Int32msg{
   105  		Type:  libcontainer.CloneFlagsAttr,
   106  		Value: uint32(syscall.CLONE_NEWNET),
   107  	})
   108  	r.AddData(&libcontainer.Bytemsg{
   109  		Type:  libcontainer.NsPathsAttr,
   110  		Value: []byte(strings.Join(namespaces, ",")),
   111  	})
   112  	if _, err := io.Copy(parent, bytes.NewReader(r.Serialize())); err != nil {
   113  		t.Fatal(err)
   114  	}
   115  
   116  	if err := cmd.Wait(); err == nil {
   117  		t.Fatalf("nsenter exits with a zero exit status")
   118  	}
   119  }
   120  
   121  func TestNsenterIncorrectPathType(t *testing.T) {
   122  	args := []string{"nsenter-exec"}
   123  	parent, child, err := newPipe()
   124  	if err != nil {
   125  		t.Fatalf("failed to create pipe %v", err)
   126  	}
   127  
   128  	namespaces := []string{
   129  		// join pid ns of the current process
   130  		fmt.Sprintf("net:/proc/%d/ns/pid", os.Getpid()),
   131  	}
   132  	cmd := &exec.Cmd{
   133  		Path:       os.Args[0],
   134  		Args:       args,
   135  		ExtraFiles: []*os.File{child},
   136  		Env:        []string{"_LIBCONTAINER_INITPIPE=3"},
   137  	}
   138  
   139  	if err := cmd.Start(); err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	// write cloneFlags
   143  	r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0)
   144  	r.AddData(&libcontainer.Int32msg{
   145  		Type:  libcontainer.CloneFlagsAttr,
   146  		Value: uint32(syscall.CLONE_NEWNET),
   147  	})
   148  	r.AddData(&libcontainer.Bytemsg{
   149  		Type:  libcontainer.NsPathsAttr,
   150  		Value: []byte(strings.Join(namespaces, ",")),
   151  	})
   152  	if _, err := io.Copy(parent, bytes.NewReader(r.Serialize())); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	if err := cmd.Wait(); err == nil {
   157  		t.Fatalf("nsenter exits with a zero exit status")
   158  	}
   159  }
   160  
   161  func init() {
   162  	if strings.HasPrefix(os.Args[0], "nsenter-") {
   163  		os.Exit(0)
   164  	}
   165  	return
   166  }
   167  
   168  func newPipe() (parent *os.File, child *os.File, err error) {
   169  	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
   170  	if err != nil {
   171  		return nil, nil, err
   172  	}
   173  	return os.NewFile(uintptr(fds[1]), "parent"), os.NewFile(uintptr(fds[0]), "child"), nil
   174  }