-
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:
Simon McVittie <smcv@collabora.com>
Simon McVittie authoredIf 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:
Simon McVittie <smcv@collabora.com>