[PATCH 1/2] loop device race condition

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fix race in mount -o loop

Retry acquiring a loop device if the setup failed with EBUSY.

Signed-Off-By: Matthias Koenig <mkoenig@xxxxxxx>

Index: util-linux-devel/mount/lomount.c
===================================================================
--- util-linux-devel.orig/mount/lomount.c
+++ util-linux-devel/mount/lomount.c
@@ -341,8 +341,17 @@ set_loop(const char *device, const char 
 	}
 
 	if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
-		perror("ioctl: LOOP_SET_FD");
-		return 1;
+		close(fd);
+		close(ffd);
+ 		switch (errno) {
+ 		case EBUSY:
+ 			if (verbose)
+ 				perror("ioctl: LOOP_SET_FD");
+ 			return 2;
+ 		default:
+ 			perror("ioctl: LOOP_SET_FD");
+ 			return 1;
+ 		}
 	}
 	close (ffd);
 
Index: util-linux-devel/mount/mount.c
===================================================================
--- util-linux-devel.orig/mount/mount.c
+++ util-linux-devel/mount/mount.c
@@ -846,20 +846,39 @@ loop_check(const char **spec, const char
 	printf(_("mount: skipping the setup of a loop device\n"));
     } else {
       int loopro = (*flags & MS_RDONLY);
+      int res;
 
-      if (!*loopdev || !**loopdev)
-	*loopdev = find_unused_loop_device();
-      if (!*loopdev)
-	return EX_SYSERR;	/* no more loop devices */
-      if (verbose)
-	printf(_("mount: going to use the loop device %s\n"), *loopdev);
-      offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
-      if (set_loop(*loopdev, *loopfile, offset,
-		   opt_encryption, pfd, &loopro)) {
+      do {
+        if (!*loopdev || !**loopdev)
+	  *loopdev = find_unused_loop_device();
+	if (!*loopdev)
+	  return EX_SYSERR;	/* no more loop devices */
 	if (verbose)
-	  printf(_("mount: failed setting up loop device\n"));
-	return EX_FAIL;
-      }
+ 	  printf(_("mount: going to use the loop device %s\n"), *loopdev);
+        offset = opt_offset ? strtoull(opt_offset, NULL, 0) : 0;
+ 	if (res = set_loop (*loopdev, *loopfile, offset,
+			    opt_encryption, pfd, &loopro)) {
+ 	  switch(res) {
+ 	  case 2:
+ 		  /* loop dev has been grabbed by some other process,
+ 		     try again, if not given explicitly */
+		  if (!opt_loopdev) { 	
+ 		    if (verbose)
+ 		      printf("mount: stolen loop=%s ...trying again\n", *loopdev);
+		    free(*loopdev);
+ 		    *loopdev = NULL;
+ 		    continue;
+		  }
+		  printf("mount: stolen loop=%s\n", *loopdev);
+		  return EX_FAIL;
+ 	  default:
+ 		  if (verbose)
+ 		    printf(_("mount: failed setting up loop device\n"));
+ 		  return EX_FAIL;
+ 	  }
+ 	}
+      } while (!*loopdev);
+
       if (verbose > 1)
 	printf(_("mount: setup loop device successfully\n"));
       *spec = *loopdev;

-
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux