github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/domain/infra/abi/system.go (about) 1 // +build ABISupport 2 3 package abi 4 5 import ( 6 "context" 7 "fmt" 8 "io/ioutil" 9 "net" 10 "os" 11 "strconv" 12 "strings" 13 "syscall" 14 15 "github.com/containers/common/pkg/config" 16 "github.com/containers/libpod/libpod/define" 17 api "github.com/containers/libpod/pkg/api/server" 18 "github.com/containers/libpod/pkg/cgroups" 19 "github.com/containers/libpod/pkg/domain/entities" 20 "github.com/containers/libpod/pkg/rootless" 21 "github.com/containers/libpod/pkg/util" 22 iopodman "github.com/containers/libpod/pkg/varlink" 23 iopodmanAPI "github.com/containers/libpod/pkg/varlinkapi" 24 "github.com/containers/libpod/utils" 25 "github.com/containers/libpod/version" 26 "github.com/pkg/errors" 27 "github.com/sirupsen/logrus" 28 "github.com/spf13/cobra" 29 "github.com/varlink/go/varlink" 30 ) 31 32 func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) { 33 return ic.Libpod.Info() 34 } 35 36 func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error { 37 var ( 38 listener net.Listener 39 err error 40 ) 41 42 if opts.URI != "" { 43 fields := strings.Split(opts.URI, ":") 44 if len(fields) == 1 { 45 return errors.Errorf("%s is an invalid socket destination", opts.URI) 46 } 47 address := strings.Join(fields[1:], ":") 48 listener, err = net.Listen(fields[0], address) 49 if err != nil { 50 return errors.Wrapf(err, "unable to create socket %s", opts.URI) 51 } 52 } 53 54 server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, &listener) 55 if err != nil { 56 return err 57 } 58 defer func() { 59 if err := server.Shutdown(); err != nil { 60 logrus.Warnf("Error when stopping API service: %s", err) 61 } 62 }() 63 64 err = server.Serve() 65 _ = listener.Close() 66 return err 67 } 68 69 func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.ServiceOptions) error { 70 var varlinkInterfaces = []*iopodman.VarlinkInterface{ 71 iopodmanAPI.New(opts.Command, ic.Libpod), 72 } 73 74 service, err := varlink.NewService( 75 "Atomic", 76 "podman", 77 version.Version, 78 "https://github.com/containers/libpod", 79 ) 80 if err != nil { 81 return errors.Wrapf(err, "unable to create new varlink service") 82 } 83 84 for _, i := range varlinkInterfaces { 85 if err := service.RegisterInterface(i); err != nil { 86 return errors.Errorf("unable to register varlink interface %v", i) 87 } 88 } 89 90 // Run the varlink server at the given address 91 if err = service.Listen(opts.URI, opts.Timeout); err != nil { 92 switch err.(type) { 93 case varlink.ServiceTimeoutError: 94 logrus.Infof("varlink service expired (use --timeout to increase session time beyond %s ms, 0 means never timeout)", opts.Timeout.String()) 95 return nil 96 default: 97 return errors.Wrapf(err, "unable to start varlink service") 98 } 99 } 100 return nil 101 } 102 103 func (ic *ContainerEngine) SetupRootless(cmd *cobra.Command) error { 104 // do it only after podman has already re-execed and running with uid==0. 105 if os.Geteuid() == 0 { 106 ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup() 107 if err != nil { 108 logrus.Warnf("Failed to detect the owner for the current cgroup: %v", err) 109 } 110 if !ownsCgroup { 111 conf, err := ic.Config(context.Background()) 112 if err != nil { 113 return err 114 } 115 unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) 116 if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { 117 if conf.Engine.CgroupManager == config.SystemdCgroupsManager { 118 logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err) 119 } else { 120 logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) 121 } 122 } 123 } 124 } 125 126 if !executeCommandInUserNS(cmd) { 127 return nil 128 } 129 130 pausePidPath, err := util.GetRootlessPauseProcessPidPath() 131 if err != nil { 132 return errors.Wrapf(err, "could not get pause process pid file path") 133 } 134 135 became, ret, err := rootless.TryJoinPauseProcess(pausePidPath) 136 if err != nil { 137 return err 138 } 139 if became { 140 os.Exit(ret) 141 } 142 143 // if there is no pid file, try to join existing containers, and create a pause process. 144 ctrs, err := ic.Libpod.GetRunningContainers() 145 if err != nil { 146 logrus.WithError(err).Fatal("") 147 } 148 149 paths := []string{} 150 for _, ctr := range ctrs { 151 paths = append(paths, ctr.Config().ConmonPidFile) 152 } 153 154 became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths) 155 if err := movePauseProcessToScope(); err != nil { 156 conf, err := ic.Config(context.Background()) 157 if err != nil { 158 return err 159 } 160 if conf.Engine.CgroupManager == config.SystemdCgroupsManager { 161 logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err) 162 } else { 163 logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err) 164 } 165 } 166 if err != nil { 167 logrus.WithError(err).Fatal("") 168 } 169 if became { 170 os.Exit(ret) 171 } 172 return nil 173 } 174 175 // Most podman commands when run in rootless mode, need to be executed in the 176 // users usernamespace. This function is updated with a list of commands that 177 // should NOT be run within the user namespace. 178 func executeCommandInUserNS(cmd *cobra.Command) bool { 179 return os.Geteuid() == 0 180 // if os.Geteuid() == 0 { 181 // return false 182 // } 183 // switch cmd { 184 // case _migrateCommand, 185 // _mountCommand, 186 // _renumberCommand, 187 // _searchCommand, 188 // _versionCommand: 189 // return false 190 // } 191 // return true 192 } 193 194 func movePauseProcessToScope() error { 195 pausePidPath, err := util.GetRootlessPauseProcessPidPath() 196 if err != nil { 197 return errors.Wrapf(err, "could not get pause process pid file path") 198 } 199 200 data, err := ioutil.ReadFile(pausePidPath) 201 if err != nil { 202 return errors.Wrapf(err, "cannot read pause pid file") 203 } 204 pid, err := strconv.ParseUint(string(data), 10, 0) 205 if err != nil { 206 return errors.Wrapf(err, "cannot parse pid file %s", pausePidPath) 207 } 208 209 return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope") 210 } 211 212 func setRLimits() error { // nolint:deadcode,unused 213 rlimits := new(syscall.Rlimit) 214 rlimits.Cur = 1048576 215 rlimits.Max = 1048576 216 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { 217 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { 218 return errors.Wrapf(err, "error getting rlimits") 219 } 220 rlimits.Cur = rlimits.Max 221 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { 222 return errors.Wrapf(err, "error setting new rlimits") 223 } 224 } 225 return nil 226 } 227 228 func setUMask() { // nolint:deadcode,unused 229 // Be sure we can create directories with 0755 mode. 230 syscall.Umask(0022) 231 } 232 233 // checkInput can be used to verify any of the globalopt values 234 func checkInput() error { // nolint:deadcode,unused 235 return nil 236 } 237 238 // func getCNIPluginsDir() string { 239 // if rootless.IsRootless() { 240 // return "" 241 // } 242 // 243 // return registry.PodmanOptions.Network.CNIPluginDirs[0] 244 // }