setupConsole sets up the console from inside the container, and sends the master pty fd to the config.Pipe (using cmsg). This is done to ensure that consoles are scoped to a container properly (see runc#814 and the many issues related to that). This has to be run *after* we've pivoted to the new roo
(socket *os.File, config *initConfig, mount bool)
| 373 | // issues related to that). This has to be run *after* we've pivoted to the new |
| 374 | // rootfs (and the users' configuration is entirely set up). |
| 375 | func setupConsole(socket *os.File, config *initConfig, mount bool) error { |
| 376 | defer socket.Close() |
| 377 | // At this point, /dev/ptmx points to something that we would expect. We |
| 378 | // used to change the owner of the slave path, but since the /dev/pts mount |
| 379 | // can have gid=X set (at the users' option). So touching the owner of the |
| 380 | // slave PTY is not necessary, as the kernel will handle that for us. Note |
| 381 | // however, that setupUser (specifically fixStdioPermissions) *will* change |
| 382 | // the UID owner of the console to be the user the process will run as (so |
| 383 | // they can actually control their console). |
| 384 | |
| 385 | pty, peerPty, err := safeAllocPty() |
| 386 | if err != nil { |
| 387 | return err |
| 388 | } |
| 389 | // After we return from here, we don't need the console anymore. |
| 390 | defer pty.Close() |
| 391 | defer peerPty.Close() |
| 392 | |
| 393 | if config.ConsoleHeight != 0 && config.ConsoleWidth != 0 { |
| 394 | err = pty.Resize(console.WinSize{ |
| 395 | Height: config.ConsoleHeight, |
| 396 | Width: config.ConsoleWidth, |
| 397 | }) |
| 398 | if err != nil { |
| 399 | return err |
| 400 | } |
| 401 | } |
| 402 | |
| 403 | // Mount the console inside our rootfs. |
| 404 | if mount { |
| 405 | if err := mountConsole(peerPty); err != nil { |
| 406 | return err |
| 407 | } |
| 408 | } |
| 409 | // While we can access console.master, using the API is a good idea. |
| 410 | if err := cmsg.SendRawFd(socket, pty.Name(), pty.Fd()); err != nil { |
| 411 | return err |
| 412 | } |
| 413 | runtime.KeepAlive(pty) |
| 414 | |
| 415 | // Now, dup over all the things. |
| 416 | return dupStdio(peerPty) |
| 417 | } |
| 418 | |
| 419 | // syncParentReady sends to the given pipe a JSON payload which indicates that |
| 420 | // the init is ready to Exec the child process. It then waits for the parent to |
no test coverage detected
searching dependent graphs…