Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
apk-tools
apk-tools
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 59
    • Issues 59
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 14
    • Merge Requests 14
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • alpine
  • apk-toolsapk-tools
  • Issues
  • #9634

Closed
Open
Opened Nov 09, 2018 by Tony Garnock-Jones@tonyg
  • Report abuse
  • New issue
Report abuse New issue

apk symbolic link handling

I suspect there is a bug in `apk add`’s handling of symlinks when
using `—root` pointing to an area of the file system not on the same
mount as the running root directory, when the symlink is to end up in
the root directory.

I had an APKBUILD with with a `package()` routine that included:

…
ln -s /media/data “$pkgdir”/data
ln -s /etc/crontabs “$pkgdir”/var/spool/cron/crontabs
ln -s /proc/mounts “$pkgdir”/etc/mtab
…

When installing the package using

apk —root targetroot —initdb add …(many packages)…

where `targetroot` was a mount point for the file system under
construction, it produced an error in apk’s `src/database.c`
[here](https://github.com/alpinelinux/apk-tools/blob/8fa193ecda2a71de3ff5f826205351b185d15054/src/database.c\#L2731-L2736),

/* Overwrite the old file */
if (renameat(db->root_fd, tmpname,
db->root_fd, name) != 0) {
apk_error(PKG_VER_FMT“: failed to rename %s to %s.”,
PKG_VER_PRINTF(ipkg->pkg), tmpname, name);
ipkg->broken_files = 1;
}

Adding a `perror(“renameat”)` before the `apk_error` showed that the
cause of the failure was `EXDEV`:

EXDEV oldpath and newpath are not on the same mounted filesystem.
(Linux permits a filesystem to be mounted at multiple points,
but rename() does not work across different mount points, even
if the same filesystem is mounted on both.)

Changing the APKBUILD to omit the first symlink (`/data`), leaving
the other two alone (`/var/spool/cron/crontabs` and `/etc/mtab`), let
the installation complete successfully!

I suspect that the problem is in `format_tmpname` in `src/database.c`.

Specifically, I think that the tmpname is built like

the/target/directory + /.apk. + somerandomstuff

So for examples like the `/etc/mtab` symlink, the tmpname will be

etc + /.apk. + somerandomstuff

i.e. a relative path, BUT in the case where the target directory is
the ROOT directory, the tmpname will be

/.apk. + somerandomstuff

i.e. it will be an ABSOLUTE path.

Now, renameat(2) ignores `db->root_fd` if `tmpname` is an absolute
path, and so it will attempt to move a file from the actual root to
somewhere in the `—root` folder, leading to EXDEV.

I believe the fix COULD involve changing `format_tmpname` to treat an
empty `fdiri>dir->name` specially, resulting in a relative tmpname,
but I am not 100% certain.

For now, I am working around the issue by removing the

ln -s /media/data “$pkgdir”/data

line from APKBUILD’s `package()`, and instead adding `ln -s
/media/data /data` to the `pre-install` script.

(from redmine: issue id 9634, created on 2018-11-09)

Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
3
Labels
Bug New Normal
Assign labels
  • View project labels
Reference: alpine/apk-tools#9634