Skip to content
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

tmpfs and symlink resolution #2683

Closed
zhangyoufu opened this issue Nov 17, 2020 · 2 comments · Fixed by #2715
Closed

tmpfs and symlink resolution #2683

zhangyoufu opened this issue Nov 17, 2020 · 2 comments · Fixed by #2715
Labels
Milestone

Comments

@zhangyoufu
Copy link

# docker run --rm -i --tmpfs /conf/stack quay.io/projectquay/quay:vader
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"rootfs_linux.go:58: mounting \\\"tmpfs\\\" to rootfs \\\"/var/lib/docker/overlay2/698f55615c6cb50d3cd3eaa1b6ab38ab8ffdc32366fa410d8fbc596039ad8890/merged\\\" at \\\"/conf/stack\\\" caused \\\"mkdir /var/lib/docker/overlay2/698f55615c6cb50d3cd3eaa1b6ab38ab8ffdc32366fa410d8fbc596039ad8890/merged/conf: file exists\\\"\"": unknown.

/conf is a symlink pointing to /quay-registry/conf, which confuses --tmpfs.
Of course I can pass resolved path /quay-registry/conf/stack to --tmpfs as a workaround. However, this produces an unnamed volume for the original path /conf/stack, which is unwanted.

@kolyshkin
Copy link
Contributor

kolyshkin commented Dec 10, 2020

Reproduced with bare runc.

  1. Add the following into config.json (same as what docker run --tmpfs /conf/stack adds):
    {
      "destination": "/conf/stack",
      "type": "tmpfs",
      "source": "tmpfs",
      "options": [
        "noexec",
        "nosuid",
        "nodev",
        "rprivate"
      ]
    }
$ cd rootfs
$ mkdir -p /real/conf
$ ln -s /real/conf conf
$ ls -l conf 
lrwxrwxrwx. 1 kir kir 10 Dec  9 18:31 conf -> /real/conf
$ cd ..
$ runc run  -d xxx
WARN[0000] unable to terminate initProcess               error="exit status 1"
ERRO[0000] container_linux.go:367: starting container process caused: process_linux.go:495: container init caused: rootfs_linux.go:60: mounting "tmpfs" to rootfs at "/conf/stack" caused: mkdir /home/kir/go/src/github.com/opencontainers/runc/tst/rootfs/conf: file exists 

This is caused by the fact that the symlink is broken in the host context, so MkdirAll is called:

func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
var (
dest = m.Destination
)
if !strings.HasPrefix(dest, rootfs) {
dest = filepath.Join(rootfs, dest)
}
switch m.Device {

...
case "tmpfs":
copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
tmpDir := ""
stat, err := os.Stat(dest)
if err != nil {
if err := os.MkdirAll(dest, 0755); err != nil {
return err

To fix, we need to have Stat() and MkdirAll in container root scope. I'll take a look.

@zhangyoufu a workaround would be to use a relative symlink in your image, i.e.

-/conf -> /quay-registry/conf
+/conf -> quay-registry/conf

@kolyshkin kolyshkin self-assigned this Dec 10, 2020
@kolyshkin
Copy link
Contributor

Now, this can be fixed, but I am not sure if it is possible to do so without introducing any new and interesting attack vectors similar to say #2197.

Looking.

kolyshkin added a commit to kolyshkin/runc that referenced this issue Jan 5, 2021
In case a tmpfs mount path contains absolute symlinks, runc errors out
because those symlinks are resolved in the host (rather than container)
filesystem scope.

The fix is similar to that for bind mounts -- resolve the destination
in container rootfs scope using securejoin, and use the resolved path.

A simple integration test case is added to prevent future regressions.

Fixes opencontainers#2683.

Signed-off-by: Kir Kolyshkin <[email protected]>
kolyshkin added a commit to kolyshkin/runc that referenced this issue Jan 5, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
kolyshkin added a commit to kolyshkin/runc that referenced this issue Jan 6, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
@cyphar cyphar closed this as completed in 637f82d Jan 27, 2021
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Jan 29, 2021
In case a tmpfs mount path contains absolute symlinks, runc errors out
because those symlinks are resolved in the host (rather than container)
filesystem scope.

The fix is similar to that for bind mounts -- resolve the destination
in container rootfs scope using securejoin, and use the resolved path.

A simple integration test case is added to prevent future regressions.

Fixes opencontainers/runc#2683.

Signed-off-by: Kir Kolyshkin <[email protected]>
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Jan 29, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers/runc#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Jan 30, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers/runc#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
@kolyshkin kolyshkin added this to the 1.0.0-rc93 milestone Feb 3, 2021
dqminh pushed a commit to dqminh/runc that referenced this issue Feb 3, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
dqminh pushed a commit to dqminh/runc that referenced this issue Feb 3, 2021
In case a tmpfs mount path contains absolute symlinks, runc errors out
because those symlinks are resolved in the host (rather than container)
filesystem scope.

The fix is similar to that for bind mounts -- resolve the destination
in container rootfs scope using securejoin, and use the resolved path.

A simple integration test case is added to prevent future regressions.

Fixes opencontainers#2683.

Signed-off-by: Kir Kolyshkin <[email protected]>
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Feb 10, 2021
In case a tmpfs mount path contains absolute symlinks, runc errors out
because those symlinks are resolved in the host (rather than container)
filesystem scope.

The fix is similar to that for bind mounts -- resolve the destination
in container rootfs scope using securejoin, and use the resolved path.

A simple integration test case is added to prevent future regressions.

Fixes opencontainers/runc#2683.

Signed-off-by: Kir Kolyshkin <[email protected]>
(cherry-picked from 637f82d6)
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Feb 10, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers/runc#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
(cherry-picked from d7df3018)
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Feb 10, 2021
In case a tmpfs mount path contains absolute symlinks, runc errors out
because those symlinks are resolved in the host (rather than container)
filesystem scope.

The fix is similar to that for bind mounts -- resolve the destination
in container rootfs scope using securejoin, and use the resolved path.

A simple integration test case is added to prevent future regressions.

Fixes opencontainers/runc#2683.

Signed-off-by: Kir Kolyshkin <[email protected]>
(cherry-picked from 637f82d6)
ctalledo pushed a commit to nestybox/sysbox-runc that referenced this issue Feb 10, 2021
While working on a test case for [1], I got the following warning:

> level=warning msg="unable to terminate initProcess" error="exit status 1"

Obviously, the warning is bogus since the initProcess is terminated.

This is happening because terminate() can return errors from either
Kill() or Wait(), and the latter returns an error if the process has
not finished successfully (i.e. exit status is not 0 or it was killed).

Check for a particular error type and filter out those errors.

[1] opencontainers/runc#2683

Signed-off-by: Kir Kolyshkin <[email protected]>
(cherry-picked from d7df3018)
@kolyshkin kolyshkin removed their assignment May 4, 2021
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 a pull request may close this issue.

2 participants