summaryrefslogtreecommitdiffstats
path: root/libmount/src/context_loopdev.c
diff options
context:
space:
mode:
authorStanislav Brabec2016-07-14 15:29:44 +0200
committerKarel Zak2016-08-03 11:53:28 +0200
commit8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd (patch)
treee541991ecf2447a1280cc6e30e54da1fb84f2665 /libmount/src/context_loopdev.c
parentImplement loopcxt_check_conflict() (diff)
downloadkernel-qcow2-util-linux-8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd.tar.gz
kernel-qcow2-util-linux-8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd.tar.xz
kernel-qcow2-util-linux-8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd.zip
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>
Diffstat (limited to 'libmount/src/context_loopdev.c')
-rw-r--r--libmount/src/context_loopdev.c65
1 files changed, 52 insertions, 13 deletions
diff --git a/libmount/src/context_loopdev.c b/libmount/src/context_loopdev.c
index 8a5706af0..37e49b0bd 100644
--- a/libmount/src/context_loopdev.c
+++ b/libmount/src/context_loopdev.c
@@ -215,23 +215,62 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
* 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(LOOP, 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(LOOP, 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(LOOP, ul_debugobj(cxt, "failed to get crypt type 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_LOOPDEV;
+ goto done;
+ }
+ if (lc_encrypt_type != LO_CRYPT_NONE) {
+ DBG(LOOP, ul_debugobj(cxt, "encryption no longer supported for device %s",
+ loopcxt_get_device(&lc)));
+ 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)