github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/sandbox_externalkey_unix.go (about) 1 //go:build linux || freebsd 2 // +build linux freebsd 3 4 package libnetwork 5 6 import ( 7 "encoding/json" 8 "flag" 9 "fmt" 10 "io" 11 "net" 12 "os" 13 "path/filepath" 14 15 "github.com/docker/docker/libnetwork/types" 16 "github.com/docker/docker/pkg/stringid" 17 "github.com/opencontainers/runtime-spec/specs-go" 18 "github.com/sirupsen/logrus" 19 ) 20 21 const ( 22 execSubdir = "libnetwork" 23 defaultExecRoot = "/run/docker" 24 success = "success" 25 ) 26 27 // processSetKeyReexec is a private function that must be called only on an reexec path 28 // It expects 3 args { [0] = "libnetwork-setkey", [1] = <container-id>, [2] = <short-controller-id> } 29 // It also expects specs.State as a json string in <stdin> 30 // Refer to https://github.com/opencontainers/runc/pull/160/ for more information 31 // The docker exec-root can be specified as "-exec-root" flag. The default value is "/run/docker". 32 func processSetKeyReexec() { 33 var err error 34 35 // Return a failure to the calling process via ExitCode 36 defer func() { 37 if err != nil { 38 logrus.Fatalf("%v", err) 39 } 40 }() 41 42 execRoot := flag.String("exec-root", defaultExecRoot, "docker exec root") 43 flag.Parse() 44 45 // expecting 3 os.Args {[0]="libnetwork-setkey", [1]=<container-id>, [2]=<short-controller-id> } 46 // (i.e. expecting 2 flag.Args()) 47 args := flag.Args() 48 if len(args) < 2 { 49 err = fmt.Errorf("Re-exec expects 2 args (after parsing flags), received : %d", len(args)) 50 return 51 } 52 containerID, shortCtlrID := args[0], args[1] 53 54 // We expect specs.State as a json string in <stdin> 55 stateBuf, err := io.ReadAll(os.Stdin) 56 if err != nil { 57 return 58 } 59 var state specs.State 60 if err = json.Unmarshal(stateBuf, &state); err != nil { 61 return 62 } 63 64 err = SetExternalKey(shortCtlrID, containerID, fmt.Sprintf("/proc/%d/ns/net", state.Pid), *execRoot) 65 } 66 67 // SetExternalKey provides a convenient way to set an External key to a sandbox 68 func SetExternalKey(shortCtlrID string, containerID string, key string, execRoot string) error { 69 keyData := setKeyData{ 70 ContainerID: containerID, 71 Key: key} 72 73 uds := filepath.Join(execRoot, execSubdir, shortCtlrID+".sock") 74 c, err := net.Dial("unix", uds) 75 if err != nil { 76 return err 77 } 78 defer c.Close() 79 80 if err = sendKey(c, keyData); err != nil { 81 return fmt.Errorf("sendKey failed with : %v", err) 82 } 83 return processReturn(c) 84 } 85 86 func sendKey(c net.Conn, data setKeyData) error { 87 var err error 88 defer func() { 89 if err != nil { 90 c.Close() 91 } 92 }() 93 94 var b []byte 95 if b, err = json.Marshal(data); err != nil { 96 return err 97 } 98 99 _, err = c.Write(b) 100 return err 101 } 102 103 func processReturn(r io.Reader) error { 104 buf := make([]byte, 1024) 105 n, err := r.Read(buf[:]) 106 if err != nil { 107 return fmt.Errorf("failed to read buf in processReturn : %v", err) 108 } 109 if string(buf[0:n]) != success { 110 return fmt.Errorf(string(buf[0:n])) 111 } 112 return nil 113 } 114 115 func (c *controller) startExternalKeyListener() error { 116 execRoot := defaultExecRoot 117 if v := c.Config().ExecRoot; v != "" { 118 execRoot = v 119 } 120 udsBase := filepath.Join(execRoot, execSubdir) 121 if err := os.MkdirAll(udsBase, 0600); err != nil { 122 return err 123 } 124 shortCtlrID := stringid.TruncateID(c.id) 125 uds := filepath.Join(udsBase, shortCtlrID+".sock") 126 l, err := net.Listen("unix", uds) 127 if err != nil { 128 return err 129 } 130 if err := os.Chmod(uds, 0600); err != nil { 131 l.Close() 132 return err 133 } 134 c.Lock() 135 c.extKeyListener = l 136 c.Unlock() 137 138 go c.acceptClientConnections(uds, l) 139 return nil 140 } 141 142 func (c *controller) acceptClientConnections(sock string, l net.Listener) { 143 for { 144 conn, err := l.Accept() 145 if err != nil { 146 if _, err1 := os.Stat(sock); os.IsNotExist(err1) { 147 logrus.Debugf("Unix socket %s doesn't exist. cannot accept client connections", sock) 148 return 149 } 150 logrus.Errorf("Error accepting connection %v", err) 151 continue 152 } 153 go func() { 154 defer conn.Close() 155 156 err := c.processExternalKey(conn) 157 ret := success 158 if err != nil { 159 ret = err.Error() 160 } 161 162 _, err = conn.Write([]byte(ret)) 163 if err != nil { 164 logrus.Errorf("Error returning to the client %v", err) 165 } 166 }() 167 } 168 } 169 170 func (c *controller) processExternalKey(conn net.Conn) error { 171 buf := make([]byte, 1280) 172 nr, err := conn.Read(buf) 173 if err != nil { 174 return err 175 } 176 var s setKeyData 177 if err = json.Unmarshal(buf[0:nr], &s); err != nil { 178 return err 179 } 180 181 var sandbox Sandbox 182 search := SandboxContainerWalker(&sandbox, s.ContainerID) 183 c.WalkSandboxes(search) 184 if sandbox == nil { 185 return types.BadRequestErrorf("no sandbox present for %s", s.ContainerID) 186 } 187 188 return sandbox.SetKey(s.Key) 189 } 190 191 func (c *controller) stopExternalKeyListener() { 192 c.extKeyListener.Close() 193 }