Skip to content

Docker should use /var/lib/docker/tmp for large temporary files. #6456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 6, 2014

Conversation

rhatdan
Copy link
Contributor

@rhatdan rhatdan commented Jun 16, 2014

/tmp is often a tmpfs file system and large temporary files could cause
docker commands to fail.

Fixes #4396

Docker-DCO-1.1-Signed-off-by: Dan Walsh dwalsh@redhat.com (github: rhatdan)

@tianon
Copy link
Member

tianon commented Jun 16, 2014

Oh good call! +1

@ewindisch
Copy link
Contributor

I'm okay with this unless anyone has illusions of running Docker on non-Unixy machines, although I'd prefer if we could set this as a runtime flag. The old code allowed setting a TMPDIR environment variable.

@timthelion
Copy link
Contributor

Link related issue: #4396

@SvenDowideit
Copy link
Contributor

-1 - we have used TMPDIR in boot2docker, and in other setups.

If hardcoding to /var/tmp is considered ok, then it needs to be well documented.

@timthelion
Copy link
Contributor

Is it possible to use /var/tmp as default and let TMPDIR over-ride that?

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 17, 2014

I think maybe the best fix would be to set TMPDIR=/var/tmp by default iff TMPDIR is not set.

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 17, 2014

This patch will basically replace the TempDir patch from OS with one that defaults to /var/tmp.

I am not sure if the is should also be done for the non daemon code path. Should continue to work on non Unix systems.

@SvenDowideit
Copy link
Contributor

I wonder if this needs documentation, as i assume that most users will think the default will be /tmp - mmm, and I think I need to look to see if this would change how we setup boot2docker too

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 23, 2014

Not sure we document anything about the handling of temp content within docker. At least in the man pages I see no mention of tmp or temp. In a perfect world, I would not want the docker daemon saving this content to /tmp or /var/tmp. It should be saved in a place like /var/lib/docker so that evil users could not attempt to muck around with it.

@SvenDowideit
Copy link
Contributor

agreed - thing is, if we are using TMPDIR, we should be consistent with expectations.

I wonder if we can consistently ensure no-one unwittingly uses /tmp or TMPDIR - or ... can we just default to /var/lib/docker/tmp, document that users can over-ride it with TMPDIR and be happy...

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 24, 2014

I kind of like defaulting it to /var/lib/docker/tmp and then modifying all of the calls to MKTMP to use it. Not sure how this would effect non unit machines.

@unclejack
Copy link
Contributor

@rhatdan What about manually setting TMPDIR for those particular systems which want to use /var/lib/docker/tmp?

It's possible to reconfigure Docker today using TMPDIR to store large files in /var/lib/docker/tmp or /var/tmp.

We can also change the code to default to /var/tmp by setting TMPDIR to that unless it's manually specified.

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 24, 2014

Why not set this to /var/lib/docker/tmp and then allow it to be overridden by the user to be in /var/tmp or /tmp. Then make /var/lib/docker/tmp not searchable by anyone but root and docker users

root docker 660

This would guarantee that a non priv user would not be able to attack/steal the image while it is in temporary storage.

@timthelion
Copy link
Contributor

I don't really understand why we are discussing the security of /tmp. From my reading of documentation most programming languages provide a secure mktemp function, does golang not do so? Is this broken on weird kernels?

@tianon
Copy link
Member

tianon commented Jun 24, 2014

Nobody here is discussing the security of /tmp. We're discussing the appropriateness of /tmp for large files, which it's ordinarily not well-suited for (especially since it's often tmpfs and thus in RAM).

@timthelion
Copy link
Contributor

@tianon um, to quote @rhatdan "It should be saved in a place like /var/lib/docker so that evil users could not attempt to muck around with it."

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 25, 2014

Well I actually believe this is a potential security issue as well as a space issue.

I wrote this blog in 2007 about this.

https://danwalsh.livejournal.com/11467.html

Having a privileged process write to /tmp or /var/tmp is potentially dangerous, mkstemp and friends are attempts of mitigating this danger. They probably will prevent well known guess attempts at the name, but the image could contain content that you might not want to leak to a unpriv user. and for a period of time this content could be stored in a temporary file. Do we make sure of the permissions on this temp content? Such that the user could not read it? I don't know? Are we sure in the future that no programmer will make a mistake on the protection flags. If we make /var/lib/docker/tmp as 660, and then default all tmp functions in docker to use it, there is a much smaller attack surface.

The secondary issue is that these images can be large and we have already told people the images are stored in /var/lib/docker, so I would assume that the temporary content for the images would also fit there. Relying on /tmp or /var/tmp which would probably be on a different partition could be problematic.

@timthelion
Copy link
Contributor

@rhatdan You say "If we make /var/lib/docker/tmp as 660, and then default all tmp functions in docker to use it, there is a much smaller attack surface." Does it actually reduce attack surface? It's only advantage is that it reduces the risk that a programmer would forget to set the file mode. If the file mode is set correctly and the mktemp function is implemented correctly(and really, a correctly implemented mktemp function should set the file mode correctly when you are root ;) ) there is no security risk.

However, I agree that large files don't belong in /tmp especially now that everyone with an SSD has to make /tmp into a ramdisk or end up screwing their drive :(

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 25, 2014

Yes if Programmers do not create bugs we have nothing to worry about. :^(

@SvenDowideit
Copy link
Contributor

I'm +1 to using /var/lib/docker/tmp (really I mean -g-path/tmp) by default, as this sidesteps all sorts of /tmp pain - and our graph dir is already storing all the container's underwear.

/var/lib/docker is already 700 as all access to it is via the docker daemon - i (i think) we don't need to make /var/lib/docker/tmp accessible to group users?

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 26, 2014

Updated the patch to use /var/lib/docker/tmp. Also added to utils utils.RootDir to save the setting of the -g command.

@erikh erikh added the Runtime label Jun 26, 2014
@SvenDowideit
Copy link
Contributor

@rhatdan can you please push it :)

@rhatdan
Copy link
Contributor Author

rhatdan commented Jun 27, 2014

@SvenDowideit oops.

vincentbernat added a commit to vincentbernat/docker that referenced this pull request Jun 27, 2014
Additionally, this can be overridden by setting the TMPDIR variable,
like this was already the case for the generic `mkimage.sh` script.

As explained in moby#6456, the rationale to use `/var/tmp` instead of `/tmp`
is that `/tmp` is often a small tmpfs filesystem with more restricted
rights.

Docker-DCO-1.1-Signed-off-by: Vincent Bernat <vincent@bernat.im> (github: vincentbernat)
@rhatdan rhatdan changed the title Docker should use /var/tmp for large temporary files. Docker should use /var/lib/docker/tmp for large temporary files. Jun 27, 2014
RootDir = "/var/lib/docker"
)

func SetRootDir(tmpdir string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What has this got to do with tmpdir? I presume dir string would be more what you mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@SvenDowideit
Copy link
Contributor

I feel it would be worth mentioning that the tmp dir defaults to /tmp under the --graph dir, and that it can be over-ridden using the TMPDIR env var in the daemon docs in cli.md.

otherwise its one of those hidden secrets only the code readers know.

but on the other hand - maybe they are the only ones that have a good reason?

@rhatdan
Copy link
Contributor Author

rhatdan commented Jul 9, 2014

I updated to patch to use DOCKER_TMPDIR, is this what you meant?

@tianon
Copy link
Member

tianon commented Jul 9, 2014

So, I meant something more like:

var tmpDir string
if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
    tmpDir = filepath.Join(RootDir, "tmp")
}
os.MkdirAll(...)
return tmpDir

rootdir = RootDir
}
dir := fmt.Sprintf("%s/tmp", rootdir)
if _, err := os.Stat(dir); os.IsNotExist(err) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From godoc: If path is already a directory, MkdirAll does nothing and returns nil.
So no need for the if.

@rhatdan
Copy link
Contributor Author

rhatdan commented Jul 11, 2014

Renamed to tmpdir_unix.go

@@ -48,7 +48,7 @@ func main() {
bridgeName = flag.String([]string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking")
bridgeIp = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
pidfile = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
flRoot = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the Docker runtime")
flRoot = flag.String([]string{"g", "-graph"}, utils.RootDir, "Path to use as the root of the Docker runtime")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think it makes more sense to store the RootDir variable not in utils, but in the var section of this file, just like dockerConfDir, unexported so rootDir. Then you could have utils.TempDir take the rootDir as a parameter. It just feels wrong to have the RootDir variable in the utils package. Let me know if you disagree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping @rhatdan

@rhatdan
Copy link
Contributor Author

rhatdan commented Jul 16, 2014

Switched to use @tiborvass method.

@unclejack
Copy link
Contributor

LGTM

ping @crosbymichael @tiborvass @vieux

@tiborvass
Copy link
Contributor

TestBuldForbiddenContextPath fails: docker_cli_build_test.go:1300: Wrong error, must be about forbidden ../../ path

@tiborvass
Copy link
Contributor

#assignee=tiborvass

@rhatdan
Copy link
Contributor Author

rhatdan commented Jul 19, 2014

@tiborvass What does this mean?

I have rebased.

@tiborvass
Copy link
Contributor

@rhatdan rebasing was without conflict so it was mainly about fixing that test case.
We're sometimes carrying PRs to cut the back and forth between reviewers and contributors to save everyone's time. It helps merging faster. So no worries :)

@rhatdan
Copy link
Contributor Author

rhatdan commented Jul 28, 2014

@tiborvass How does it look now?

@tiborvass
Copy link
Contributor

LGTM

if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
tmpDir = filepath.Join(rootdir, "tmp")
}
os.MkdirAll(tmpDir, 0700)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason we're ignoring any errors from MkdirAll? Would it be prudent to either not do that, or add a comment as to why we're doing that?

@SvenDowideit
Copy link
Contributor

Docs LGTM - @jamtur01 @fredlf @ostezer

@ghost
Copy link

ghost commented Jul 29, 2014

LGTM

1 similar comment
@jamtur01
Copy link
Contributor

LGTM

@fredlf
Copy link
Contributor

fredlf commented Jul 31, 2014

LGTM (that's a docs quorum). ping @vieux @crosbymichael

/tmp is often a tmpfs file system and large temporary files could cause
docker commands to fail.  Also using /tmp potentially allows users on the
system to get access to content, or even attack the content.  Moving the tmpdir to
/var/lib/container/tmp will protect the data.

Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)

Conflicts:
	docker/docker.go
@rhatdan
Copy link
Contributor Author

rhatdan commented Aug 5, 2014

Rebased to current docker. Can we get this pull request upstream.

@rhatdan
Copy link
Contributor Author

rhatdan commented Aug 6, 2014

ping @vieux @crosbymichael

@unclejack
Copy link
Contributor

@crosbymichael This PR is good to go. Can you review it, please?

unclejack added a commit that referenced this pull request Aug 6, 2014
Docker should use /var/lib/docker/tmp for large temporary files.
@unclejack unclejack merged commit 66c8f87 into moby:master Aug 6, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

docker save writes a, potentially, large file to /tmp