buildah icon indicating copy to clipboard operation
buildah copied to clipboard

Permissions of /tmp are set to 755 after a bind mount is placed under /tmp under specific conditions

Open limwa opened this issue 2 months ago • 3 comments

Issue Description

Under specific situations, podman build (does not happen when running buildah directly) resets the permissions of /tmp to 755. Those conditions seem to be:

  1. A folder already exists under /tmp (e.g. /tmp/a)
  2. In the same RUN instruction, a bind mount is placed under /tmp (e.g. mounted at /tmp/b) and a file is created under the pre-existing folder (e.g. /tmp/a/example.txt).

I became aware of this problem due to an existing issue with devcontainers caused by this bug. Here is the relevant devcontainers issue: https://github.com/devcontainers/images/issues/1556.

Steps to reproduce the issue

  1. Create an empty folder with the following Containerfile:
FROM docker.io/library/ubuntu:22.04

RUN ls -la /tmp/

RUN mkdir -p /tmp/a/
RUN --mount=type=bind,source=.,target=/tmp/b/ touch /tmp/a/example.txt

RUN ls -la /tmp/
  1. Run podman build --no-cache .
  2. See the permissions of /tmp printed in the last ls -la /tmp.

Describe the results you received

Running podman build --no-cache . yields the following logs:

STEP 1/5: FROM docker.io/library/ubuntu:22.04
STEP 2/5: RUN ls -la /tmp/
total 0
drwxrwxrwt 1 root root  0 Oct  1 02:10 .
dr-xr-xr-x 1 root root 18 Nov 13 21:36 ..
--> 9400d67ec242
STEP 3/5: RUN mkdir -p /tmp/a/
--> c06a6049730a
STEP 4/5: RUN --mount=type=bind,source=.,target=/tmp/b/ touch /tmp/a/example.txt
--> c290d15ac7bd
STEP 5/5: RUN ls -la /tmp/
total 0
drwxr-xr-x 1 root root  2 Nov 13 21:36 .
dr-xr-xr-x 1 root root 18 Nov 13 21:36 ..
drwxr-xr-x 1 root root 22 Nov 13 21:36 a
COMMIT
--> 96f5267ab511
96f5267ab5112e128eeddf6307f603f31e3430104f99872dff44868f2a7aa75b

As you can see from the line drwxr-xr-x 1 root root 2 Nov 13 21:36 ., the permissions of the /tmp directory are set to 755 even though no chmod command was executed.

Describe the results you expected

I expected the result yielded by buildah build --no-cache .:

STEP 1/5: FROM docker.io/library/ubuntu:22.04
STEP 2/5: RUN ls -la /tmp/
total 0
drwxrwxrwt 1 root root  0 Oct  1 02:10 .
dr-xr-xr-x 1 root root 24 Nov 13 21:36 ..
STEP 3/5: RUN mkdir -p /tmp/a/
STEP 4/5: RUN --mount=type=bind,source=.,target=/tmp/b/ touch /tmp/a/example.txt
STEP 5/5: RUN ls -la /tmp/
total 0
drwxrwxrwt 1 root root  2 Nov 13 21:36 .
dr-xr-xr-x 1 root root 30 Nov 13 21:36 ..
drwxr-xr-x 1 root root 22 Nov 13 21:36 a
COMMIT
--> dcba70ab0e9d
dcba70ab0e9db48ed7c0561025b894e228d0d0bc3ce3817285cdb555b295a533

As you can see, the /tmp directory has the correct permissions.

podman version output

Client:       Podman Engine
Version:      5.7.0
API Version:  5.7.0
Go Version:   go1.25.2
Built:        Tue Jan  1 00:00:00 1980
OS/Arch:      linux/amd64

podman info output

host:
  arch: amd64
  buildahVersion: 1.42.0
  cgroupControllers:
  - cpu
  - io
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: Unknown
    path: /nix/store/6ar9ipnqm47pfnvgh036d8jbwj5dfwj0-podman-helper-binary-wrapper/bin/conmon
    version: 'conmon version 2.1.13, commit: '
  cpuUtilization:
    idlePercent: 94.02
    systemPercent: 1.17
    userPercent: 4.81
  cpus: 16
  databaseBackend: sqlite
  distribution:
    codename: xantusia
    distribution: nixos
    version: "25.11"
  eventLogger: journald
  freeLocks: 2037
  hostname: AAAAAAAA
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 100
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
  kernel: 6.17.7
  linkmode: dynamic
  logDriver: journald
  memFree: 5910265856
  memTotal: 32267067392
  networkBackend: netavark
  networkBackendInfo:
    backend: netavark
    dns:
      package: Unknown
      path: /nix/store/9y4b9qj24z3wkyf5dwr8s8ycffgmr2rn-podman-5.7.0/libexec/podman/aardvark-dns
      version: aardvark-dns 1.16.0
    package: Unknown
    path: /nix/store/9y4b9qj24z3wkyf5dwr8s8ycffgmr2rn-podman-5.7.0/libexec/podman/netavark
    version: netavark 1.16.1
  ociRuntime:
    name: crun
    package: Unknown
    path: /nix/store/6ar9ipnqm47pfnvgh036d8jbwj5dfwj0-podman-helper-binary-wrapper/bin/crun
    version: |-
      crun version 1.24
      commit: 1.24
      rundir: /run/user/1000/crun
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +YAJL
  os: linux
  pasta:
    executable: /nix/store/9y4b9qj24z3wkyf5dwr8s8ycffgmr2rn-podman-5.7.0/libexec/podman/pasta
    package: Unknown
    version: |
      pasta 2025_09_19.623dbf6
      Copyright Red Hat
      GNU General Public License, version 2 or later
        <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law.
  remoteSocket:
    exists: true
    path: /run/user/1000/podman/podman.sock
  rootlessNetworkCmd: pasta
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    seccompProfilePath: ""
    selinuxEnabled: false
  serviceIsRemote: false
  slirp4netns:
    executable: ""
    package: ""
    version: ""
  swapFree: 38654701568
  swapTotal: 38654701568
  uptime: 0h 58m 51.00s
  variant: ""
plugins:
  authorization: null
  log:
  - k8s-file
  - none
  - passthrough
  - journald
  network:
  - bridge
  - macvlan
  - ipvlan
  volume:
  - local
registries:
  search:
  - docker.io
  - quay.io
store:
  configFile: /home/lima/.config/containers/storage.conf
  containerStore:
    number: 10
    paused: 0
    running: 0
    stopped: 10
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /home/lima/.local/share/containers/storage
  graphRootAllocated: 961024098304
  graphRootUsed: 761307258880
  graphStatus:
    Backing Filesystem: btrfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Supports shifting: "false"
    Supports volatile: "true"
    Using metacopy: "false"
  imageCopyTmpDir: /var/tmp
  imageStore:
    number: 924
  runRoot: /run/user/1000/containers
  transientStore: false
  volumePath: /home/lima/.local/share/containers/storage/volumes
version:
  APIVersion: 5.7.0
  Built: 315532800
  BuiltTime: Tue Jan  1 00:00:00 1980
  GitCommit: ""
  GoVersion: go1.25.2
  Os: linux
  OsArch: linux/amd64
  Version: 5.7.0

Provide your storage.conf

[storage]
driver = "overlay"
graphroot = "/var/lib/containers/storage"
runroot = "/run/containers/storage"

Podman in a container

No

Privileged Or Rootless

Rootless

Upstream Latest Release

Yes

Installation Source

Distribution package (DNF, apt, yay)

Additional environment details

Running NixOS unstable, with a patch to upgrade Podman to version 5.7.0.

Additional information

The issue only happens with podman build and not with buildah build.

limwa avatar Nov 13 '25 21:11 limwa

This looks like a consequence of us not adding an entry for "tmp" in the layer that creates "tmp/a/example.txt" when the --layers flag is used (the flag is enabled by default for podman build but not buildah build), in combination with using the overlay storage driver. In the overlay driver, the contents of each layer are stored in a separate directory tree. When the layer that includes "tmp/a/example.txt" is being written to disk, because the layer blob doesn't include an entry that would cause "tmp" to have already been created for that layer with known permissions and ownership, the directory has to be created by the driver, and the driver currently uses the same default permissions and ownership for any such directory that it has to create. I started working on something to address this in https://github.com/containers/storage/pull/1653, but didn't finish it.

nalind avatar Nov 13 '25 22:11 nalind

Okay, that's good to know!

By the way, while investigating this bug, I found another example, but with a weirder behavior - sometimes the permissions are right, and other times the permissions are wrong:

FROM docker.io/library/ubuntu:22.04

RUN ls -la /tmp/

RUN mkdir -p /tmp/a/
RUN --mount=type=bind,source=.,target=/tmp/b/ touch /tmp/example.txt

RUN ls -la /tmp/

The only difference is that the file is created directly under /tmp instead of /tmp/a.

Sometimes the /tmp directory has 755 permissions, but there are runs in which it has 1777 permissions. And the weirder thing is, this doesn't seem to happen without the RUN mkdir -p /tmp/a/ instruction.

Is this the same bug, or should I file another issue?

limwa avatar Nov 13 '25 23:11 limwa

A friendly reminder that this issue had no activity for 30 days.

github-actions[bot] avatar Dec 14 '25 00:12 github-actions[bot]

Ping to prevent the issue from going stale. I also observe this issue when installing stuff via apt using podman buildx (buildah). It tries to copy some GPG keys to /tmp for verification, which fails and prevents the installation of packages.

MexHigh avatar Dec 21 '25 10:12 MexHigh