diff options
author | Stanislav Brabec | 2016-07-14 15:29:44 +0200 |
---|---|---|
committer | Karel Zak | 2016-08-03 11:53:28 +0200 |
commit | 8efad715b9cf9746f77fa1fda17b0af1f5ed4fcd (patch) | |
tree | e541991ecf2447a1280cc6e30e54da1fb84f2665 /libmount/src | |
parent | Implement loopcxt_check_conflict() (diff) | |
download | kernel-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')
-rw-r--r-- | libmount/src/context_loopdev.c | 65 |
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) |