1 package libcontainer
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "os/exec"
8 "strconv"
9
10 "github.com/opencontainers/runtime-spec/specs-go"
11 "github.com/opencontainers/selinux/go-selinux"
12 "github.com/sirupsen/logrus"
13 "golang.org/x/sys/unix"
14
15 "github.com/opencontainers/runc/libcontainer/apparmor"
16 "github.com/opencontainers/runc/libcontainer/configs"
17 "github.com/opencontainers/runc/libcontainer/keys"
18 "github.com/opencontainers/runc/libcontainer/seccomp"
19 "github.com/opencontainers/runc/libcontainer/system"
20 "github.com/opencontainers/runc/libcontainer/utils"
21 )
22
23 type linuxStandardInit struct {
24 pipe *os.File
25 consoleSocket *os.File
26 parentPid int
27 fifoFd int
28 logFd int
29 mountFds []int
30 config *initConfig
31 }
32
33 func (l *linuxStandardInit) getSessionRingParams() (string, uint32, uint32) {
34 var newperms uint32
35
36 if l.config.Config.Namespaces.Contains(configs.NEWUSER) {
37
38 newperms = 0x8
39 } else {
40
41 newperms = 0x80000
42 }
43
44
45
46 return "_ses." + l.config.ContainerId, 0xffffffff, newperms
47 }
48
49 func (l *linuxStandardInit) Init() error {
50 if !l.config.Config.NoNewKeyring {
51 if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil {
52 return err
53 }
54 defer selinux.SetKeyLabel("")
55 ringname, keepperms, newperms := l.getSessionRingParams()
56
57
58 if sessKeyId, err := keys.JoinSessionKeyring(ringname); err != nil {
59
60
61
62
63
64
65
66
67 if !errors.Is(err, unix.ENOSYS) {
68 return fmt.Errorf("unable to join session keyring: %w", err)
69 }
70 } else {
71
72
73
74 if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil {
75 return fmt.Errorf("unable to mod keyring permissions: %w", err)
76 }
77 }
78 }
79
80 if err := setupNetwork(l.config); err != nil {
81 return err
82 }
83 if err := setupRoute(l.config.Config); err != nil {
84 return err
85 }
86
87
88 selinux.GetEnabled()
89
90
91 err := prepareRootfs(l.pipe, l.config, l.mountFds)
92 for _, m := range l.mountFds {
93 if m == -1 {
94 continue
95 }
96
97 if err := unix.Close(m); err != nil {
98 return fmt.Errorf("Unable to close mountFds fds: %w", err)
99 }
100 }
101
102 if err != nil {
103 return err
104 }
105
106
107
108
109 if l.config.CreateConsole {
110 if err := setupConsole(l.consoleSocket, l.config, true); err != nil {
111 return err
112 }
113 if err := system.Setctty(); err != nil {
114 return &os.SyscallError{Syscall: "ioctl(setctty)", Err: err}
115 }
116 }
117
118
119 if l.config.Config.Namespaces.Contains(configs.NEWNS) {
120 if err := finalizeRootfs(l.config.Config); err != nil {
121 return err
122 }
123 }
124
125 if hostname := l.config.Config.Hostname; hostname != "" {
126 if err := unix.Sethostname([]byte(hostname)); err != nil {
127 return &os.SyscallError{Syscall: "sethostname", Err: err}
128 }
129 }
130 if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil {
131 return fmt.Errorf("unable to apply apparmor profile: %w", err)
132 }
133
134 for key, value := range l.config.Config.Sysctl {
135 if err := writeSystemProperty(key, value); err != nil {
136 return err
137 }
138 }
139 for _, path := range l.config.Config.ReadonlyPaths {
140 if err := readonlyPath(path); err != nil {
141 return fmt.Errorf("can't make %q read-only: %w", path, err)
142 }
143 }
144 for _, path := range l.config.Config.MaskPaths {
145 if err := maskPath(path, l.config.Config.MountLabel); err != nil {
146 return fmt.Errorf("can't mask path %s: %w", path, err)
147 }
148 }
149 pdeath, err := system.GetParentDeathSignal()
150 if err != nil {
151 return fmt.Errorf("can't get pdeath signal: %w", err)
152 }
153 if l.config.NoNewPrivileges {
154 if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil {
155 return &os.SyscallError{Syscall: "prctl(SET_NO_NEW_PRIVS)", Err: err}
156 }
157 }
158
159
160
161 if err := syncParentReady(l.pipe); err != nil {
162 return fmt.Errorf("sync ready: %w", err)
163 }
164 if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil {
165 return fmt.Errorf("can't set process label: %w", err)
166 }
167 defer selinux.SetExecLabel("")
168
169
170
171 if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges {
172 seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp)
173 if err != nil {
174 return err
175 }
176
177 if err := syncParentSeccomp(l.pipe, seccompFd); err != nil {
178 return err
179 }
180 }
181 if err := finalizeNamespace(l.config); err != nil {
182 return err
183 }
184
185
186 if err := pdeath.Restore(); err != nil {
187 return fmt.Errorf("can't restore pdeath signal: %w", err)
188 }
189
190
191
192
193 if unix.Getppid() != l.parentPid {
194 return unix.Kill(unix.Getpid(), unix.SIGKILL)
195 }
196
197
198 name, err := exec.LookPath(l.config.Args[0])
199 if err != nil {
200 return err
201 }
202
203
204
205
206 if err := eaccess(name); err != nil {
207 return &os.PathError{Op: "eaccess", Path: name, Err: err}
208 }
209
210
211
212
213
214
215 if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges {
216 seccompFd, err := seccomp.InitSeccomp(l.config.Config.Seccomp)
217 if err != nil {
218 return fmt.Errorf("unable to init seccomp: %w", err)
219 }
220
221 if err := syncParentSeccomp(l.pipe, seccompFd); err != nil {
222 return err
223 }
224 }
225
226 logrus.Debugf("init: closing the pipe to signal completion")
227 _ = l.pipe.Close()
228
229
230 if err := unix.Close(l.logFd); err != nil {
231 return &os.PathError{Op: "close log pipe", Path: "fd " + strconv.Itoa(l.logFd), Err: err}
232 }
233
234
235
236
237
238 fifoPath := "/proc/self/fd/" + strconv.Itoa(l.fifoFd)
239 fd, err := unix.Open(fifoPath, unix.O_WRONLY|unix.O_CLOEXEC, 0)
240 if err != nil {
241 return &os.PathError{Op: "open exec fifo", Path: fifoPath, Err: err}
242 }
243 if _, err := unix.Write(fd, []byte("0")); err != nil {
244 return &os.PathError{Op: "write exec fifo", Path: fifoPath, Err: err}
245 }
246
247
248
249
250
251
252
253 _ = unix.Close(l.fifoFd)
254
255 s := l.config.SpecState
256 s.Pid = unix.Getpid()
257 s.Status = specs.StateCreated
258 if err := l.config.Config.Hooks[configs.StartContainer].RunHooks(s); err != nil {
259 return err
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 if err := utils.UnsafeCloseFrom(l.config.PassedFilesCount + 3); err != nil {
278 return err
279 }
280 return system.Exec(name, l.config.Args[0:], os.Environ())
281 }
282
View as plain text