File util-linux-loop-reuse-06.patch of Package util-linux.4136

From 8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Thu, 14 Jul 2016 15:29:44 +0200
Subject: [PATCH 6/20] libmout: Reuse loop device safely

Add a safety check to mnt_context_setup_loopdev(). Only a loop device with equal
offset and sizelimit will be reused. If any overlapping loop device exists,
MNT_ERR_LOOPOVERLAP is returned.

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
---
 libmount/src/context_loopdev.c | 65 +++++++++++++++++++++++++++++++++---------
 1 file changed, 52 insertions(+), 13 deletions(-)

Index: util-linux-2.25/libmount/src/context_loopdev.c
===================================================================
--- util-linux-2.25.orig/libmount/src/context_loopdev.c
+++ util-linux-2.25/libmount/src/context_loopdev.c
@@ -223,23 +223,62 @@ int mnt_context_setup_loopdev(struct lib
 	 * mechanism to detect it. To prevent data corruption, the same loop
 	 * device has to be recycled.
 	*/
-	rc = loopcxt_init(&lc, 0);
-	if (rc)
-		goto done_no_deinit;
-	if (backing_file && !(loopcxt_find_by_backing_file(&lc,
-			backing_file, offset, sizelimit, LOOPDEV_FL_OFFSET))) {
-		DBG(CXT, ul_debugobj(cxt, "using existing loop device %s",
+	if (backing_file) {
+		rc = loopcxt_init(&lc, 0);
+		if (rc)
+			goto done_no_deinit;
+
+		rc = loopcxt_find_by_backing_file(&lc,
+				backing_file, offset, sizelimit,
+				LOOPDEV_FL_OFFSET | LOOPDEV_FL_SIZELIMIT);
+		if (rc < 0)
+			goto done;
+		if (rc == 0) {
+			uint32_t lc_encrypt_type;
+
+			DBG(CXT, ul_debugobj(cxt, "using existing loop device %s",
+				loopcxt_get_device(&lc)));
+
+			/* Once a loop is initialized RO, there is no
+			   way to change its parameters. */
+			if (loopcxt_is_readonly(&lc) && !(lo_flags & LO_FLAGS_READ_ONLY)) {
+				rc = -EROFS;
+				goto done;
+			}
+
+			/* This is no more supported, but check to be
+			 * safe. */
+			if (loopcxt_get_encrypt_type(&lc, &lc_encrypt_type)) {
+				DBG(CXT, ul_debugobj(cxt, "failed to get crypt type for device %s",
+					loopcxt_get_device(&lc)));
+				rc = -MNT_ERR_LOOPDEV;
+				goto done;
+			}
+			if (lc_encrypt_type != LO_CRYPT_NONE) {
+				DBG(CXT, ul_debugobj(cxt, "encryption no longer supported for device %s",
 					loopcxt_get_device(&lc)));
-		/* Once a loop is initialized RO, there is no way to safely
-		   mount that file in R/W mode. */
-		if (loopcxt_is_readonly(&lc) && !(lo_flags & LO_FLAGS_READ_ONLY)) {
-			rc = -EROFS;
+				rc = -MNT_ERR_LOOPOVERLAP;
+				goto done;
+			}
+			goto success;
+		}
+		loopcxt_deinit(&lc);
+		/* No existing loop device matches. Now we need to
+		 * check that no loop device overlaps our target range
+		 * inside the backing file. */
+		rc = loopcxt_init(&lc, 0);
+		if (rc)
+			goto done_no_deinit;
+		rc = loopcxt_check_conflict(&lc,
+			backing_file, offset, sizelimit);
+		if (rc < 0)
+			goto done;
+		if (rc == 0) {
+			rc = -MNT_ERR_LOOPOVERLAP;
 			goto done;
 		}
-
-		goto success;
+		loopcxt_deinit(&lc);
 	}
-	loopcxt_deinit(&lc);
 
 	rc = loopcxt_init(&lc, 0);
 	if (rc)
openSUSE Build Service is sponsored by