chainguard-dev / melange

build APKs from source code
Apache License 2.0
412 stars 97 forks source link

File Ownership not preserved #501

Closed amouat closed 10 months ago

amouat commented 1 year ago

When using chown or similar in melange, I would expect the changes to make it into the tar file, but this doesn't seem to be the case.

For example, with this melange file:

package:
  name: owntest
  version: 0.0.0
  epoch: 0
  dependencies:
    runtime:

environment:
  contents:
    repositories:
      - https://packages.wolfi.dev/os
    packages:
      - busybox
  accounts:
    users:
      - username: test
        uid: 1001

pipeline:
  - name: testy
  - runs: |
      touch file
      install -m744 -o test -D file ${{targets.destdir}}/etc/test/file
      chown test file
      cp file ${{targets.destdir}}/etc/
      chown test ${{targets.destdir}}/etc/file
      ls -l ${{targets.destdir}}/etc/file
      ls -l /${{targets.destdir}}/etc/test/file
      ls -l ${{targets.destdir}}/etc/test

I get the following results:

tar --same-owner -tpvf packages/aarch64/owntest-0.0.0-r0.apk
-rw-r--r--  0 root   root      209  1 Jan  1970 .PKGINFO
drwxr-xr-x  0 root   root        0  1 Jan  1970 etc
-rw-r--r--  0 root   root        0  1 Jan  1970 etc/file
drwxr-xr-x  0 root   root        0  1 Jan  1970 etc/test
-rwxr--r--  0 root   root        0  1 Jan  1970 etc/test/file
drwxr-xr-x  0 root   root        0  1 Jan  1970 var
drwxr-xr-x  0 root   root        0  1 Jan  1970 var/lib
drwxr-xr-x  0 root   root        0  1 Jan  1970 var/lib/db
drwxr-xr-x  0 root   root        0  1 Jan  1970 var/lib/db/sbom
-rw-r--r--  0 root   root     2875  1 Jan  1970 var/lib/db/sbom/owntest-0.0.0-r0.spdx.json

But I expected /etc/file and /etc/test/file to be owned by test.

The owner is test in the debug output from melange.

kaniini commented 1 year ago

This used to work in the past. Maybe this is due to our DirFS?

Elizafox commented 11 months ago

I confirmed this is a problem. I will investigate soon.

epsilon-phase commented 11 months ago

I have a few observations of what seems to be causing this

  1. emitDataSection explicitly overrides the UID/GID/uname/gname to be root https://github.com/chainguard-dev/melange/blob/4cdad80d1b38f4dc01692effc070ec32c9d1ba53/pkg/build/package.go#L746C1-L752C3
  2. The tarball writer has a uid/gid mapping that it reads from etc/passwd or other files, but this file is not exposed to the filesystem view of the tarball context. This empty table cannot fix this issue then
  3. The docker melange runner, at least on MacOS on arm64 utilizes a gRPC fuse filesystem where UID/GID are set to the user reading the fuse filesystem. This exposes an xattr called com.docker.grpcfuse.ownership which is set to values such as {"UID":-1,"GID":-1,"mode":755}. This can be read to correct the issues. Doing this properly may require wrapping DirFS in some interlocutor that would read that instead of the UID/GID.

The combination of these issues indicates that all packages from melange will have all files owned by root. Removing the override in 1) results in the docker runner, at least on macOS arm64 having the username and UID/GID of the user building the package due to 3)

2 Would be a side issue which is probably a good idea to fix, probably by passing the environment directory as an extra parameter to the tarball writer so it can successfully read the etc/passwds for UIDS

Elizafox commented 10 months ago

This appears to still be a problem.

Elizafox commented 10 months ago

Resolved