Skip to content

Commit

Permalink
libct: move StartInitialization from factory to init
Browse files Browse the repository at this point in the history
This is where it should belong.

No code changes, just cut-n-paste.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin committed May 12, 2022
1 parent 8181865 commit 2a295a8
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 105 deletions.
105 changes: 0 additions & 105 deletions libcontainer/factory_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import (
"fmt"
"os"
"regexp"
"runtime/debug"
"strconv"

securejoin "github.com/cyphar/filepath-securejoin"
"golang.org/x/sys/unix"
Expand Down Expand Up @@ -154,109 +152,6 @@ func Load(root, id string) (*Container, error) {
return c, nil
}

// StartInitialization loads a container by opening the pipe fd from the parent
// to read the configuration and state. This is a low level implementation
// detail of the reexec and should not be consumed externally.
func StartInitialization() (err error) {
// Set up logging.
level := int(logrus.DebugLevel) // default to debug
// Passing log level is optional; currently libcontainer/integration does not do it.
if levelStr := os.Getenv("_LIBCONTAINER_LOGLEVEL"); levelStr != "" {
level, err = strconv.Atoi(levelStr)
if err != nil {
panic(fmt.Errorf("unable to convert _LIBCONTAINER_LOGLEVEL: %w", err))
}
}

logPipeFd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_LOGPIPE"))
if err != nil {
panic(fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err))
}

logrus.SetLevel(logrus.Level(level))
logrus.SetOutput(os.NewFile(uintptr(logPipeFd), "logpipe"))
logrus.SetFormatter(new(logrus.JSONFormatter))
logrus.Debug("child process in init()")

// Once logging is all set, we can use logrus to log errors.

// Get the INITPIPE.
envInitPipe := os.Getenv("_LIBCONTAINER_INITPIPE")
pipefd, err := strconv.Atoi(envInitPipe)
if err != nil {
err = fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE: %w", err)
logrus.Error(err)
return err
}
pipe := os.NewFile(uintptr(pipefd), "pipe")
defer pipe.Close()

// Once init pipe is set, we can send error back to parent. If this
// defer is ever called, this means initialization has failed.
defer func() {
// We have an error during the initialization of the container's init,
// send it back to the parent process in the form of an initError.
if werr := writeSync(pipe, procError); werr != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if werr := utils.WriteJSON(pipe, &initError{Message: err.Error()}); werr != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}()

// Only init processes have FIFOFD.
fifofd := -1
envInitType := os.Getenv("_LIBCONTAINER_INITTYPE")
it := initType(envInitType)
if it == initStandard {
envFifoFd := os.Getenv("_LIBCONTAINER_FIFOFD")
if fifofd, err = strconv.Atoi(envFifoFd); err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err)
}
}

var consoleSocket *os.File
if envConsole := os.Getenv("_LIBCONTAINER_CONSOLE"); envConsole != "" {
console, err := strconv.Atoi(envConsole)
if err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_CONSOLE: %w", err)
}
consoleSocket = os.NewFile(uintptr(console), "console-socket")
defer consoleSocket.Close()
}

// Get mount files (O_PATH).
mountFds, err := parseMountFds()
if err != nil {
return err
}

// clear the current process's environment to clean any libcontainer
// specific env vars.
os.Clearenv()

defer func() {
if e := recover(); e != nil {
if e, ok := e.(error); ok {
err = fmt.Errorf("panic from initialization: %w, %s", e, debug.Stack())
} else {
//nolint:errorlint // here e is not of error type
err = fmt.Errorf("panic from initialization: %v, %s", e, debug.Stack())
}
}
}()

i, err := newContainerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds)
if err != nil {
return err
}

// If Init succeeds, syscall.Exec will not return, hence none of the defers will be called.
return i.Init()
}

func loadState(root string) (*State, error) {
stateFilePath, err := securejoin.SecureJoin(root, stateFilename)
if err != nil {
Expand Down
105 changes: 105 additions & 0 deletions libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"io"
"net"
"os"
"runtime/debug"
"strconv"
"strings"
"unsafe"

Expand Down Expand Up @@ -71,6 +73,109 @@ type initConfig struct {
Cgroup2Path string `json:"cgroup2_path,omitempty"`
}

// StartInitialization loads a container by opening the pipe fd from the parent
// to read the configuration and state. This is a low level implementation
// detail of the reexec and should not be consumed externally.
func StartInitialization() (err error) {
// Set up logging.
level := int(logrus.DebugLevel) // default to debug
// Passing log level is optional; currently libcontainer/integration does not do it.
if levelStr := os.Getenv("_LIBCONTAINER_LOGLEVEL"); levelStr != "" {
level, err = strconv.Atoi(levelStr)
if err != nil {
panic(fmt.Errorf("unable to convert _LIBCONTAINER_LOGLEVEL: %w", err))
}
}

logPipeFd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_LOGPIPE"))
if err != nil {
panic(fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err))
}

logrus.SetLevel(logrus.Level(level))
logrus.SetOutput(os.NewFile(uintptr(logPipeFd), "logpipe"))
logrus.SetFormatter(new(logrus.JSONFormatter))
logrus.Debug("child process in init()")

// Once logging is all set, we can use logrus to log errors.

// Get the INITPIPE.
envInitPipe := os.Getenv("_LIBCONTAINER_INITPIPE")
pipefd, err := strconv.Atoi(envInitPipe)
if err != nil {
err = fmt.Errorf("unable to convert _LIBCONTAINER_INITPIPE: %w", err)
logrus.Error(err)
return err
}
pipe := os.NewFile(uintptr(pipefd), "pipe")
defer pipe.Close()

// Once init pipe is set, we can send error back to parent. If this
// defer is ever called, this means initialization has failed.
defer func() {
// We have an error during the initialization of the container's init,
// send it back to the parent process in the form of an initError.
if werr := writeSync(pipe, procError); werr != nil {
fmt.Fprintln(os.Stderr, err)
return
}
if werr := utils.WriteJSON(pipe, &initError{Message: err.Error()}); werr != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}()

// Only init processes have FIFOFD.
fifofd := -1
envInitType := os.Getenv("_LIBCONTAINER_INITTYPE")
it := initType(envInitType)
if it == initStandard {
envFifoFd := os.Getenv("_LIBCONTAINER_FIFOFD")
if fifofd, err = strconv.Atoi(envFifoFd); err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err)
}
}

var consoleSocket *os.File
if envConsole := os.Getenv("_LIBCONTAINER_CONSOLE"); envConsole != "" {
console, err := strconv.Atoi(envConsole)
if err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_CONSOLE: %w", err)
}
consoleSocket = os.NewFile(uintptr(console), "console-socket")
defer consoleSocket.Close()
}

// Get mount files (O_PATH).
mountFds, err := parseMountFds()
if err != nil {
return err
}

// clear the current process's environment to clean any libcontainer
// specific env vars.
os.Clearenv()

defer func() {
if e := recover(); e != nil {
if e, ok := e.(error); ok {
err = fmt.Errorf("panic from initialization: %w, %s", e, debug.Stack())
} else {
//nolint:errorlint // here e is not of error type
err = fmt.Errorf("panic from initialization: %v, %s", e, debug.Stack())
}
}
}()

i, err := newContainerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds)
if err != nil {
return err
}

// If Init succeeds, syscall.Exec will not return, hence none of the defers will be called.
return i.Init()
}

type initer interface {
Init() error
}
Expand Down

0 comments on commit 2a295a8

Please sign in to comment.