Skip to content
Snippets Groups Projects
  • Simon McVittie's avatar
    959fd338
    wrap: Take out a lock on the container's runtime for the duration · 959fd338
    Simon McVittie authored
    
    If we upgrade from runtime 0.20191024.0 to 0.20191108.0 while an app
    or game is still running under runtime 0.20191024.0, then deleting
    the app or game's shared libraries out from under it will probably
    break it.
    
    Flatpak solves this problem with a read/write lock on the file
    `files/.ref` - for runtimes this is `/usr/.ref` in the container.
    Each instance of `flatpak run` takes a read-lock on that file. Any
    number of processes can hold a read-lock at the same time.
    Before a package-manager-style operation like `flatpak uninstall`
    does anything destructive to a runtime, it takes a write-lock, which
    only succeeds if there are currently no read- or write-locks.
    Depending on the operation, the lock is either taken directly or by
    asking bubblewrap to do it.
    
    We'll use the same scheme. Different families of locking APIs interact
    unpredictably, so it's important that we use the same locking API as
    bubblewrap, namely POSIX byte-range (record) advisory locks via
    fcntl F_SETLK. In particular, this means flock(1) and flock(2) are
    not going to help us: they use POSIX file-level advisory locks.
    
    One difference between our locking and flatpak's is that we support
    runtimes that are not "merged /usr". In this case, we could either
    take a lock on files/.ref (/.ref in the container) or on files/usr/.ref
    (/usr/.ref in the container). I've chosen to do the former here, so that
    it's always files/.ref. It doesn't matter, as long as we're consistent.
    
    (For apps the lock file is `/app/.ref` and for extensions it's
    `$mountpoint/.ref`, but pressure-vessel doesn't have an equivalent of
    Flatpak apps or extensions yet.)
    
    This version is only a partial solution. We can't use bwrap --lock-file
    or bwrap --sync-fd without also using --unshare-pid, which breaks
    gameoverlayrenderer.so; so we do the next best thing, by leaking the
    lock fd to the bubblewrap process, which will leak it to the game's
    main process. This won't work if the game forks background processes,
    but it's good enough for a straightforward execve() chain.
    
    Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
    959fd338
    History
    wrap: Take out a lock on the container's runtime for the duration
    Simon McVittie authored
    
    If we upgrade from runtime 0.20191024.0 to 0.20191108.0 while an app
    or game is still running under runtime 0.20191024.0, then deleting
    the app or game's shared libraries out from under it will probably
    break it.
    
    Flatpak solves this problem with a read/write lock on the file
    `files/.ref` - for runtimes this is `/usr/.ref` in the container.
    Each instance of `flatpak run` takes a read-lock on that file. Any
    number of processes can hold a read-lock at the same time.
    Before a package-manager-style operation like `flatpak uninstall`
    does anything destructive to a runtime, it takes a write-lock, which
    only succeeds if there are currently no read- or write-locks.
    Depending on the operation, the lock is either taken directly or by
    asking bubblewrap to do it.
    
    We'll use the same scheme. Different families of locking APIs interact
    unpredictably, so it's important that we use the same locking API as
    bubblewrap, namely POSIX byte-range (record) advisory locks via
    fcntl F_SETLK. In particular, this means flock(1) and flock(2) are
    not going to help us: they use POSIX file-level advisory locks.
    
    One difference between our locking and flatpak's is that we support
    runtimes that are not "merged /usr". In this case, we could either
    take a lock on files/.ref (/.ref in the container) or on files/usr/.ref
    (/usr/.ref in the container). I've chosen to do the former here, so that
    it's always files/.ref. It doesn't matter, as long as we're consistent.
    
    (For apps the lock file is `/app/.ref` and for extensions it's
    `$mountpoint/.ref`, but pressure-vessel doesn't have an equivalent of
    Flatpak apps or extensions yet.)
    
    This version is only a partial solution. We can't use bwrap --lock-file
    or bwrap --sync-fd without also using --unshare-pid, which breaks
    gameoverlayrenderer.so; so we do the next best thing, by leaking the
    lock fd to the bubblewrap process, which will leak it to the game's
    main process. This won't work if the game forks background processes,
    but it's good enough for a straightforward execve() chain.
    
    Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>