repart: when keeping ref to backing inode/devnode, use fd_reopen() rathern than F_DUPFD
authorLennart Poettering <lennart@poettering.net>
Tue, 2 Aug 2022 16:16:21 +0000 (18:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 3 Aug 2022 07:09:04 +0000 (09:09 +0200)
commit38f81e937426993cfc899aa09298f69f00935852
treeb93adf194bd2232ff1375d6a1a6bad130ee56a99
parenta268e7f4021072e120a03b42660fad21e465c44e
repart: when keeping ref to backing inode/devnode, use fd_reopen() rathern than F_DUPFD

Via the "backing_fd" variable we intend to pin the backing inode through
our entire code. So far we typically created the fd via F_DUPFD_CLOEXEC,
and thus any BSD lock taken one the original fd is shared with our
backing_fd reference. And if the origina fd is closed but our backing_fd
is not, we'll keep the BSD lock open, even if we then reopen the block
device through the backing_fd. If hit, this results in a deadlock.

Let's fix that by creating the backing_fd via fd_reopen(), so that the
locks are no longer shared, and if the original fd is closed all BSD
locks on it that are in effect are auto-released.

(Note the deadlock is only triggered if multiple operations on the same
backing inode are executed, i.e. factory reset, resize and applying of
partitions.)

Replaces: #24181
src/partition/repart.c