mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-10-22 06:12:35 +00:00
Linux: detect write protection after opening block devices
Some protected block devices accept writable opens. Check BLKROGET and report EROFS so the existing mount retry selects read only protection. Cover automatic detection with read only loop devices on both backends.
This commit is contained in:
@@ -5,6 +5,8 @@ Requires the same tools as test_linux_loop_identity.py, plus blockdev and
|
||||
debugfs. Read-only cases reject raw writes and preserve the encrypted host's
|
||||
SHA-256. Dirty ext4 cases must refuse journal recovery without changing the
|
||||
host or leaking devices; an explicit noload mount is the positive control.
|
||||
Volumes hosted on read only loop devices also test automatic detection when
|
||||
the kernel permits opening the protected device with write access.
|
||||
Run:
|
||||
python3 Tests/test_linux_read_only_integration.py --binary /usr/bin/veracrypt
|
||||
|
||||
@@ -163,6 +165,21 @@ def check(checks, path, kernel, readonly, filesystem, layers, effective_readonly
|
||||
checks.cleanup()
|
||||
|
||||
|
||||
def check_read_only_block_device(checks, path, layers):
|
||||
label = path.name + "-readonly-host"
|
||||
host = checks.run(label + "-attach", ["losetup", "--find", "--show", "--read-only", path]).stdout.strip()
|
||||
# This is the backing device, so each mount must leave it attached.
|
||||
checks.existing_loops.add(host)
|
||||
try:
|
||||
for kernel in (True, False):
|
||||
for filesystem in (False, True):
|
||||
check(checks, Path(host), kernel, False, filesystem, layers, effective_readonly=True)
|
||||
checks.expect(label + "-kept", host in loop_devices(), "backing loop remains attached")
|
||||
finally:
|
||||
checks.run(label + "-detach", ["losetup", "-d", host])
|
||||
checks.existing_loops.discard(host)
|
||||
|
||||
|
||||
def check_journal_recovery(checks, path, kernel):
|
||||
label = f"{path.name}-{'native' if kernel else 'fuse'}-journal"
|
||||
args = ["--mount", path, checks.mountpoint, f"--slot={checks.slot}",
|
||||
@@ -238,8 +255,9 @@ def main():
|
||||
for readonly in (True, False):
|
||||
for filesystem in (False, True):
|
||||
check(checks, source, kernel, readonly, filesystem, layers)
|
||||
# A read-only host mount makes the initial O_RDWR open fail with
|
||||
# EROFS. A block device's read-only flag alone need not reject open().
|
||||
check_read_only_block_device(checks, path, layers)
|
||||
# A read-only host filesystem rejects O_RDWR itself, while a block
|
||||
# device's protection flag need not prevent the open from succeeding.
|
||||
checks.run("host-bind", ["mount", "--bind", path, path])
|
||||
try:
|
||||
checks.run("host-readonly", ["mount", "-o", "remount,bind,ro", path])
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
</li>
|
||||
<li><strong>Linux:</strong>
|
||||
<ul>
|
||||
<li>Automatically mount volumes as read only when the backing block device reports write protection, even if it permits an open request with write access.</li>
|
||||
<li>Forward sync requests for volumes mounted through FUSE to the backing file or device and report flush failures. Previously, a successful sync could leave data in the host cache.</li>
|
||||
<li>Check that devices belong to the selected volume before dismount or filesystem checks. Leave externally supplied host devices attached and refuse normal dismount while a decrypted loop device remains in use.</li>
|
||||
<li>Support writable volume files on shares that restrict root access, including GVfs and NFS with <code>root_squash</code> (GH #23). Keep the share mounted and the user session active until dismount.</li>
|
||||
|
||||
@@ -347,6 +347,24 @@ namespace VeraCrypt
|
||||
#endif
|
||||
throw_sys_sub_if (FileHandle == -1, wstring (path));
|
||||
|
||||
#ifdef TC_LINUX
|
||||
if (mode != OpenRead)
|
||||
{
|
||||
// Some block devices accept writable opens even when write protected.
|
||||
// Report EROFS so the volume mount can retry with read only protection.
|
||||
struct stat statData;
|
||||
int readOnly = 0;
|
||||
if (fstat (FileHandle, &statData) == 0 && S_ISBLK (statData.st_mode)
|
||||
&& ioctl (FileHandle, BLKROGET, &readOnly) == 0 && readOnly)
|
||||
{
|
||||
close (FileHandle);
|
||||
FileHandle = -1;
|
||||
errno = EROFS;
|
||||
throw SystemException (SRC_POS, wstring (path));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 // File locking is disabled to avoid remote filesystem locking issues
|
||||
try
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user