diff options
author | Xiaoming Ni | 2022-11-15 14:54:05 +0100 |
---|---|---|
committer | Denys Vlasenko | 2022-11-15 14:54:05 +0100 |
commit | cb8d2ea8c91b5671b05e06ab2282496104453378 (patch) | |
tree | 10cb02d9620037a7195728c985ec2d1ded1184e4 | |
parent | 707a7ef4c72d1d00ff61221511a70eada19185ca (diff) | |
download | busybox-cb8d2ea8c91b5671b05e06ab2282496104453378.zip busybox-cb8d2ea8c91b5671b05e06ab2282496104453378.tar.gz |
loop: fix a race when a free loop device is snatched
When /dev/loop-control exists and *device is empty,
the mount may fail if a concurrent mount is running.
function old new delta
set_loop 809 807 -2
Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/loop.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/libbb/loop.c b/libbb/loop.c index cb8fa24..750642a 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -218,8 +218,17 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse } /* failure, undo LOOP_SET_FD */ ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary + } else { + /* device is not free (rc == 0), or error other than ENXIO */ + if (rc == 0 /* device is not free? */ + && !*device /* racing with other mount? */ + && try != dev /* tried a _kernel-offered_ loopN? */ + ) { + free(try); + close(lfd); + goto get_free_loopN; + } } - /* else: device is not free (rc == 0) or error other than ENXIO */ close_and_try_next_loopN: close(lfd); try_next_loopN: |