init: switch away from stateDirFd entirely

While we have significant protections in place against CVE-2016-9962, we
still were holding onto a file descriptor that referenced the host
filesystem. This meant that in certain scenarios it was still possible
for a semi-privileged container to gain access to the host filesystem
(if they had CAP_SYS_PTRACE).

Instead, open the FIFO itself using a O_PATH. This allows us to
reference the FIFO directly without providing the ability for
directory-level access. When opening the FIFO inside the init process,
open it through procfs to re-open the actual FIFO (this is currently the
only supported way to open such a file descriptor).

Signed-off-by: Aleksa Sarai <asarai@suse.de>
This commit is contained in:
Aleksa Sarai
2017-08-24 17:37:26 +10:00
parent ae2948042b
commit 7d66aab77a
5 changed files with 42 additions and 29 deletions
+7 -7
View File
@@ -233,10 +233,10 @@ func (l *LinuxFactory) Type() string {
// This is a low level implementation detail of the reexec and should not be consumed externally
func (l *LinuxFactory) StartInitialization() (err error) {
var (
pipefd, rootfd int
pipefd, fifofd int
consoleSocket *os.File
envInitPipe = os.Getenv("_LIBCONTAINER_INITPIPE")
envStateDir = os.Getenv("_LIBCONTAINER_STATEDIR")
envFifoFd = os.Getenv("_LIBCONTAINER_FIFOFD")
envConsole = os.Getenv("_LIBCONTAINER_CONSOLE")
)
@@ -252,11 +252,11 @@ func (l *LinuxFactory) StartInitialization() (err error) {
)
defer pipe.Close()
// Only init processes have STATEDIR.
rootfd = -1
// Only init processes have FIFOFD.
fifofd = -1
if it == initStandard {
if rootfd, err = strconv.Atoi(envStateDir); err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_STATEDIR=%s to int: %s", envStateDir, err)
if fifofd, err = strconv.Atoi(envFifoFd); err != nil {
return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD=%s to int: %s", envFifoFd, err)
}
}
@@ -291,7 +291,7 @@ func (l *LinuxFactory) StartInitialization() (err error) {
}
}()
i, err := newContainerInit(it, pipe, consoleSocket, rootfd)
i, err := newContainerInit(it, pipe, consoleSocket, fifofd)
if err != nil {
return err
}