Skip to content

Make --symlink idempotent, or introduce a new --symlink-idempotent #549

Closed
@smcv

Description

We've had several Flatpak issues of this general form:

  • Flatpak bind-mounts some directory /dir into the sandbox (read-only or read/write)
  • Flatpak also wants to set up some symlink /dir/symlink -> target below that directory
  • The symlink already exists in the bind-mounted directory
  • ... so bwrap --symlink target /dir/symlink fails with EEXIST

or this:

  • Flatpak explicitly creates a symlink /var/run -> /run
  • The host system also has a symlink /var/run -> /run
  • Flatpak has been asked to share some filesystem with the container which happens to be below /var/run, like /var/run/media, which it does by creating the symlink /var/run -> /run and mounting /run/media onto the sandbox's /run/media
  • ... so it ends up with bwrap --symlink /run /var/run ... --symlink /run /var/run which fails with EEXIST

I see two ways this could be addressed.

The most general solution would be for Flatpak (and other projects that use bwrap) to be more aware of what it is mounting and how, so that if it wants to create a symlink below a directory it is sharing with the sandbox, it creates it in the source directory on the host instead of asking bwrap to create it below the destination mount point. Flatpak already has FlatpakExports, which is aware of every --filesystem that it is going to share with the sandbox, but is currently unaware of things like --persist, leading to bugs; so this solution would involve extending FlatpakExports to be aware of more locations. However, this general solution is going to be quite complicated.

A 90% solution would be to make bwrap --symlink idempotent, or leave bwrap --symlink as-is for bug-for-bug compatibility but introduce a new --symlink-idempotent (or an --idempotent modifier to be used like --size, or something). How this would work:

  • if the symlink doesn't already exist in /newroot, still create it, like --symlink
  • if the symlink already exists in /newroot, and it has the same target we want to create, new behaviour: do nothing
  • if the symlink already exists in /newroot, and it has a different target but works out to be equivalent (like we want /var/run -> /run when /var/run -> ../run exists), maybe new behaviour: also do nothing (I am unsure whether this is desirable or not)
  • if the desired path already exists in /newroot but is not a symlink, or is a symlink pointing somewhere different, still fail like --symlink would

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions