github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/control/server/server.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 /* 16 Package server provides a basic control server interface. 17 18 Note that no objects are registered by default. Users must provide their own 19 implementations of the control interface. 20 */ 21 package server 22 23 import ( 24 "os" 25 "time" 26 27 "github.com/nicocha30/gvisor-ligolo/pkg/log" 28 "github.com/nicocha30/gvisor-ligolo/pkg/sync" 29 "github.com/nicocha30/gvisor-ligolo/pkg/unet" 30 "github.com/nicocha30/gvisor-ligolo/pkg/urpc" 31 ) 32 33 // curUID is the unix user ID of the user that the control server is running as. 34 var curUID = os.Getuid() 35 36 // Server is a basic control server. 37 type Server struct { 38 // socket is our bound socket. 39 socket *unet.ServerSocket 40 41 // server is our rpc server. 42 server *urpc.Server 43 44 // wg waits for the accept loop to terminate. 45 wg sync.WaitGroup 46 } 47 48 // New returns a new bound control server. 49 func New(socket *unet.ServerSocket) *Server { 50 return &Server{ 51 socket: socket, 52 server: urpc.NewServer(), 53 } 54 } 55 56 // FD returns the file descriptor that the server is running on. 57 func (s *Server) FD() int { 58 return s.socket.FD() 59 } 60 61 // Wait waits for the main server goroutine to exit. This should be 62 // called after a call to Serve. 63 func (s *Server) Wait() { 64 s.wg.Wait() 65 } 66 67 // Stop stops the server. Note that this function should only be called once 68 // and the server should not be used afterwards. 69 func (s *Server) Stop(timeout time.Duration) { 70 s.socket.Close() 71 s.Wait() 72 73 // This will cause existing clients to be terminated safely. If the 74 // registered handlers have a Stop callback, it will be called. 75 s.server.Stop(timeout) 76 } 77 78 // StartServing starts listening for connect and spawns the main service 79 // goroutine for handling incoming control requests. StartServing does not 80 // block; to wait for the control server to exit, call Wait. 81 func (s *Server) StartServing() error { 82 // Actually start listening. 83 if err := s.socket.Listen(); err != nil { 84 return err 85 } 86 87 s.wg.Add(1) 88 go func() { // S/R-SAFE: does not impact state directly. 89 s.serve() 90 s.wg.Done() 91 }() 92 93 return nil 94 } 95 96 // serve is the body of the main service goroutine. It handles incoming control 97 // connections and dispatches requests to registered objects. 98 func (s *Server) serve() { 99 for { 100 // Accept clients. 101 conn, err := s.socket.Accept() 102 if err != nil { 103 return 104 } 105 106 ucred, err := conn.GetPeerCred() 107 if err != nil { 108 log.Warningf("Control couldn't get credentials: %s", err.Error()) 109 conn.Close() 110 continue 111 } 112 113 // Only allow this user and root. 114 if int(ucred.Uid) != curUID && ucred.Uid != 0 { 115 // Authentication failed. 116 log.Warningf("Control auth failure: other UID = %d, current UID = %d", ucred.Uid, curUID) 117 conn.Close() 118 continue 119 } 120 121 // Handle the connection non-blockingly. 122 s.server.StartHandling(conn) 123 } 124 } 125 126 // Register registers a specific control interface with the server. 127 func (s *Server) Register(obj any) { 128 s.server.Register(obj) 129 } 130 131 // CreateFromFD creates a new control bound to the given 'fd'. It has no 132 // registered interfaces and will not start serving until StartServing is 133 // called. 134 func CreateFromFD(fd int) (*Server, error) { 135 socket, err := unet.NewServerSocket(fd) 136 if err != nil { 137 return nil, err 138 } 139 return New(socket), nil 140 } 141 142 // Create creates a new control server with an abstract unix socket 143 // with the given address, which must must be unique and a valid 144 // abstract socket name. 145 func Create(addr string) (*Server, error) { 146 socket, err := unet.Bind(addr, false) 147 if err != nil { 148 return nil, err 149 } 150 return New(socket), nil 151 } 152 153 // CreateSocket creates a socket that can be used with control server, 154 // but doesn't start control server. 'addr' must be a valid and unique 155 // abstract socket name. Returns socket's FD, -1 in case of error. 156 func CreateSocket(addr string) (int, error) { 157 socket, err := unet.Bind(addr, false) 158 if err != nil { 159 return -1, err 160 } 161 return socket.Release() 162 }