When /dev/loop-control exists and *device is empty, the mounting fails
due to concurrent contention.
Code Execution Flow:
try = xasprintf(LOOP_FORMAT, i);
for (i = 0; i <= 0xfffff; i++) { // The value of "try" is not changed.
...
lfd = rc = open(try, mode);
...
rc = repeat_on_eagain(ioctl(lfd, BB_LOOP_GET_STATUS,
&loopinfo));
// Because of race, the value of "rc" is 0. and the value of
"try" is not changed
...
close(lfd);
}
add/remove: 0/0 grow/shrink: 1/0 up/down: 5/0 (5)
Function old new delta
set_loop 773 778 +5
Fixes: 4bc59a4cf ("mount: fix a race when a free loop device is snatched
under us by another mount")
Fiexe: 3b69ba799 ("mount,losetup: use /dev/loop-control is it exists")
Signed-off-by: Xiaoming Ni <[email protected]>
---
libbb/loop.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libbb/loop.c b/libbb/loop.c
index cb8fa2442..845565d7b 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -218,8 +218,13 @@ 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 {
+ if (rc == 0 && *device == NULL && try != dev) {
+ 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:
--
2.27.0
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox