Skip to content

starting a task with /dev/null for stdin, stdout or stderr causes entire /dev to be deleted #4019

@deitch

Description

@deitch

Description

When deleting a task that was started with one of its three standard file descriptors (stdin, stdout, stderr) as /dev/null (or anything else in /dev), the entire /dev directory is wiped out.

Steps to reproduce the issue:

  1. Create a container
  2. Create a task with at least one of stdin/stdout/stderr as /dev/null. I was unable replicate the issue when started via ctr command, but yes via code (below)
  3. Kill the task ctr t kill foo
  4. Delete the task ctr t delete foo
  5. Your entire /dev is emptied out
          io := cio.Config{
                                Stdin:    "/dev/null",
                                Stdout:   stdoutFile,
                                Stderr:   stderrFile,
                                Terminal: false,
        }
        task, err := ctr.NewTask(ctx, io)

Describe the results you received:

emptied /dev

Describe the results you expected:

No collateral damage

Output of containerd --version:

$ containerd --version
containerd github.com/containerd/containerd v1.3.2-1-g49b826bf 49b826bfdf925d41764f6ed77cbe332ec56fd6c7
$ ctr --version
ctr github.com/containerd/containerd v1.3.2-1-g49b826bf

Any other relevant information:

I traced the source of the issue, and can replicate it with latest code in git. The problem specifically is here:

	path := getFifoDir([]string{
		response.Process.Stdin,
		response.Process.Stdout,
		response.Process.Stderr,
	})
	closer := func() error {
		return os.RemoveAll(path)
	}

The getFifoDir() assumes:

  • all stdin/stdout/stderr are in a single directory
  • that directory is dedicated to this task

Thus, upon deletion of the task, it does os.RemoveAll().

This isn't strictly true, or at least isn't so in the docs that I found; e.g. /dev/null is used, or some other existing file is used; or some file in a directory that is shared with other files.

There are several ways to fix this, but I think first of all, os.RemoveAll() should be made optional. Let the caller indicate if the fifos (and/or the directory they are in) is meant to be removed on cleanup.

cc @justincormack @rvs @rn

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions