moby: /proc/self/fd/{0,1,2} are not valid (with --tty)

This is probably the root cause of #6880 and #8755.

Reproduced on 1.4.1 and 1.5.0.

Steps to reproduce:

$ docker run -ti --rm ubuntu ls -l /proc/self/fd
lrwx------ 1 root root 64 Mar 18 11:32 0 -> /25
lrwx------ 1 root root 64 Mar 18 11:32 1 -> /25
lrwx------ 1 root root 64 Mar 18 11:32 2 -> /25
lr-x------ 1 root root 64 Mar 18 11:32 3 -> /proc/1/fd

Expected: /fd/{0,1,2} symlinks should point to the same thing as docker run -ti --rm ubuntu tty.

Got: they point to some random point on the root of the filesystem which doesn’t exist.

Effect: This breaks the command tty (and therefore tmux and various other programs) from a docker exec into the container. The reason is that readlink(/proc/self/fd/0) returns a path that doesn’t exist. It also breaks any program which uses /dev/std{in,out,err}, because these are symlinks to items in the /proc/self/fd/ directory.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 34 (34 by maintainers)

Commits related to this issue

Most upvoted comments

When docker is creating the container, it’s launching the main process with a TTY that was created using the host’s devpts mount. Thus things like /proc/$pid/fd/0 are pointing to where the TTY is on the host’s devpts mount. Docker isn’t doing any magic here, it’s simply mounting a new devpts inside the container, so its contents don’t match the host’s. Also, docker also doesn’t control where /proc/$pid/fd/$fd points to. That’s controlled by the kernel. /dev/stdin (and stdout/stderr) however are just vanilla symlinks that point to /proc/self/fd/0 (and 1/2). /proc/$pid/fd/$fd are "magic"ish. When you open one of these files (talking about the system level open() call), the kernel is duplicating that process’s file descriptor. It’s not resolving the symlink and opening what it points to.

The only (yes, only, there is no other) way to solve this (meaning to have /proc/$pid/fd/$fd point to valid paths in /dev/pts) is for the process that docker launches inside the container, to have a TTY that was created using the container’s devpts mount.