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)