11package nsenter
22
33import (
4+ "bytes"
45 "encoding/json"
5- "fmt "
6+ "io "
67 "os"
78 "os/exec"
89 "strings"
10+ "syscall"
911 "testing"
12+
13+ "github.com/opencontainers/runc/libcontainer"
14+ "github.com/vishvananda/netlink/nl"
1015)
1116
1217type pid struct {
@@ -15,24 +20,30 @@ type pid struct {
1520
1621func TestNsenterAlivePid (t * testing.T ) {
1722 args := []string {"nsenter-exec" }
18- r , w , err := os . Pipe ()
23+ parent , child , err := newPipe ()
1924 if err != nil {
2025 t .Fatalf ("failed to create pipe %v" , err )
2126 }
2227
2328 cmd := & exec.Cmd {
2429 Path : os .Args [0 ],
2530 Args : args ,
26- ExtraFiles : []* os.File {w },
27- Env : []string {fmt . Sprintf ( "_LIBCONTAINER_INITPID=%d" , os . Getpid ()) , "_LIBCONTAINER_INITPIPE=3" },
31+ ExtraFiles : []* os.File {child },
32+ Env : []string {"_LIBCONTAINER_INITTYPE=setns" , "_LIBCONTAINER_INITPIPE=3" },
2833 }
2934
3035 if err := cmd .Start (); err != nil {
3136 t .Fatalf ("nsenter failed to start %v" , err )
3237 }
33- w .Close ()
34-
35- decoder := json .NewDecoder (r )
38+ r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
39+ r .AddData (& libcontainer.Int32msg {
40+ Type : libcontainer .PidAttr ,
41+ Value : uint32 (os .Getpid ()),
42+ })
43+ if _ , err := io .Copy (parent , bytes .NewReader (r .Serialize ())); err != nil {
44+ t .Fatal (err )
45+ }
46+ decoder := json .NewDecoder (parent )
3647 var pid * pid
3748
3849 if err := decoder .Decode (& pid ); err != nil {
@@ -51,34 +62,67 @@ func TestNsenterAlivePid(t *testing.T) {
5162
5263func TestNsenterInvalidPid (t * testing.T ) {
5364 args := []string {"nsenter-exec" }
65+ parent , child , err := newPipe ()
66+ if err != nil {
67+ t .Fatalf ("failed to create pipe %v" , err )
68+ }
5469
5570 cmd := & exec.Cmd {
56- Path : os .Args [0 ],
57- Args : args ,
58- Env : []string {"_LIBCONTAINER_INITPID=-1" },
71+ Path : os .Args [0 ],
72+ Args : args ,
73+ ExtraFiles : []* os.File {child },
74+ Env : []string {"_LIBCONTAINER_INITTYPE=setns" , "_LIBCONTAINER_INITPIPE=3" },
75+ }
76+
77+ if err := cmd .Start (); err != nil {
78+ t .Fatal ("nsenter exits with a zero exit status" )
79+ }
80+ r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
81+ r .AddData (& libcontainer.Int32msg {
82+ Type : libcontainer .PidAttr ,
83+ Value : 0 ,
84+ })
85+ if _ , err := io .Copy (parent , bytes .NewReader (r .Serialize ())); err != nil {
86+ t .Fatal (err )
5987 }
6088
61- err := cmd .Run ()
62- if err == nil {
89+ if err := cmd .Wait (); err == nil {
6390 t .Fatal ("nsenter exits with a zero exit status" )
6491 }
6592}
6693
6794func TestNsenterDeadPid (t * testing.T ) {
68- dead_cmd := exec .Command ("true" )
69- if err := dead_cmd .Run (); err != nil {
95+ deadCmd := exec .Command ("true" )
96+ if err := deadCmd .Run (); err != nil {
7097 t .Fatal (err )
7198 }
7299 args := []string {"nsenter-exec" }
100+ parent , child , err := newPipe ()
101+ if err != nil {
102+ t .Fatalf ("failed to create pipe %v" , err )
103+ }
73104
74105 cmd := & exec.Cmd {
75- Path : os .Args [0 ],
76- Args : args ,
77- Env : []string {fmt .Sprintf ("_LIBCONTAINER_INITPID=%d" , dead_cmd .Process .Pid )},
106+ Path : os .Args [0 ],
107+ Args : args ,
108+ ExtraFiles : []* os.File {child },
109+ Env : []string {"_LIBCONTAINER_INITTYPE=setns" , "_LIBCONTAINER_INITPIPE=3" },
78110 }
79111
80- err := cmd .Run ()
81- if err == nil {
112+ if err := cmd .Start (); err != nil {
113+ t .Fatal ("nsenter exits with a zero exit status" )
114+ }
115+
116+ r := nl .NewNetlinkRequest (int (libcontainer .InitMsg ), 0 )
117+ r .AddData (& libcontainer.Int32msg {
118+ Type : libcontainer .PidAttr ,
119+ Value : uint32 (deadCmd .Process .Pid ),
120+ })
121+ if _ , err := io .Copy (parent , bytes .NewReader (r .Serialize ())); err != nil {
122+ t .Fatal (err )
123+ }
124+
125+ if err := cmd .Wait (); err == nil {
82126 t .Fatal ("nsenter exits with a zero exit status" )
83127 }
84128}
@@ -89,3 +133,11 @@ func init() {
89133 }
90134 return
91135}
136+
137+ func newPipe () (parent * os.File , child * os.File , err error ) {
138+ fds , err := syscall .Socketpair (syscall .AF_LOCAL , syscall .SOCK_STREAM | syscall .SOCK_CLOEXEC , 0 )
139+ if err != nil {
140+ return nil , nil , err
141+ }
142+ return os .NewFile (uintptr (fds [1 ]), "parent" ), os .NewFile (uintptr (fds [0 ]), "child" ), nil
143+ }
0 commit comments