martinjungblut/go-cryptsetup

libcryptsetup function 'crypt_resize' returned error with code '-22'

Opened this issue · 13 comments

=== RUN   Test_LUKS1_Resize
    main_test.go:30: libcryptsetup function 'crypt_resize' returned error with code '-22'.

Test System

Kernel: Linux 5.17.9-xanmod1-x64v2 #0~git20220518.d88d798 SMP Wed May 18 22:47:17 UTC 2022 x86_64 GNU/Linux
Root Library Origin: cryptsetup (2:2.4.3-1)
Virtualization: None, bare metal

Test Results

(consistent)

=== RUN   Test_Device_Init_Works_If_Device_Is_Found
--- PASS: Test_Device_Init_Works_If_Device_Is_Found (0.01s)
=== RUN   Test_Device_Init_Fails_If_Device_Is_Not_Found
Device nonExistingDevicePath does not exist or access denied.
--- PASS: Test_Device_Init_Fails_If_Device_Is_Not_Found (0.00s)
=== RUN   Test_Device_InitByName_Fails_If_Device_Is_Not_Active
Device nonExistingMappedDevice is not active.
--- PASS: Test_Device_InitByName_Fails_If_Device_Is_Not_Active (0.00s)
=== RUN   Test_Device_Free_Works
Dump operation is not supported for this device type.
--- PASS: Test_Device_Free_Works (1.37s)
=== RUN   Test_Device_Free_Doesnt_Fail_For_Empty_Device
--- PASS: Test_Device_Free_Doesnt_Fail_For_Empty_Device (0.00s)
=== RUN   Test_Device_Free_Doesnt_Fail_If_Called_Multiple_Times
--- PASS: Test_Device_Free_Doesnt_Fail_If_Called_Multiple_Times (1.33s)
=== RUN   Test_Device_Deactivate_Fails_If_Device_Is_Not_Active
Device testDeviceName is not active.
--- PASS: Test_Device_Deactivate_Fails_If_Device_Is_Not_Active (0.00s)
=== RUN   Test_Device_ActivateByPassphrase_Fails_If_Device_Has_No_Type
Device type is not properly initialized.
--- PASS: Test_Device_ActivateByPassphrase_Fails_If_Device_Has_No_Type (0.00s)
=== RUN   Test_Device_ActivateByVolumeKey_Fails_If_Device_Has_No_Type
Device type is not properly initialized.
--- PASS: Test_Device_ActivateByVolumeKey_Fails_If_Device_Has_No_Type (0.00s)
=== RUN   Test_Device_KeyslotAddByVolumeKey_Fails_If_Device_Has_No_Type
Cannot determine device type. Incompatible activation of device?
This operation is supported only for LUKS device.
--- PASS: Test_Device_KeyslotAddByVolumeKey_Fails_If_Device_Has_No_Type (0.00s)
=== RUN   Test_Device_KeyslotAddByPassphrase_Fails_If_Device_Has_No_Type
Cannot determine device type. Incompatible activation of device?
This operation is supported only for LUKS device.
--- PASS: Test_Device_KeyslotAddByPassphrase_Fails_If_Device_Has_No_Type (0.00s)
=== RUN   Test_Device_KeyslotChangeByPassphrase_Fails_If_Device_Has_No_Type
Cannot determine device type. Incompatible activation of device?
This operation is supported only for LUKS device.
--- PASS: Test_Device_KeyslotChangeByPassphrase_Fails_If_Device_Has_No_Type (0.00s)
=== RUN   Test_Device_VolumeKeyGet
--- PASS: Test_Device_VolumeKeyGet (13.57s)
=== RUN   Test_Device_VolumeKeyGet_Fails_If_Wrong_Passphrase
--- PASS: Test_Device_VolumeKeyGet_Fails_If_Wrong_Passphrase (7.82s)
=== RUN   Test_Device_GetDeviceName
--- PASS: Test_Device_GetDeviceName (1.35s)
=== RUN   Test_Device_GetUUID
--- PASS: Test_Device_GetUUID (2.69s)
=== RUN   Test_Log
--- PASS: Test_Log (0.00s)
=== RUN   Test_LUKS1_Format
--- PASS: Test_LUKS1_Format (1.49s)
=== RUN   Test_LUKS1_Load_ActivateByPassphrase_Deactivate
--- PASS: Test_LUKS1_Load_ActivateByPassphrase_Deactivate (6.83s)
=== RUN   Test_LUKS1_Load_ActivateByPassphrase_Free_InitByName_Deactivate
--- PASS: Test_LUKS1_Load_ActivateByPassphrase_Free_InitByName_Deactivate (6.79s)
=== RUN   Test_LUKS1_ActivateByVolumeKey_Deactivate
--- PASS: Test_LUKS1_ActivateByVolumeKey_Deactivate (1.46s)
=== RUN   Test_LUKS1_ActivateByAutoGeneratedVolumeKey_Deactivate
--- PASS: Test_LUKS1_ActivateByAutoGeneratedVolumeKey_Deactivate (1.46s)
=== RUN   Test_LUKS1_KeyslotAddByVolumeKey
--- PASS: Test_LUKS1_KeyslotAddByVolumeKey (4.67s)
=== RUN   Test_LUKS1_KeyslotAddByPassphrase
--- PASS: Test_LUKS1_KeyslotAddByPassphrase (9.98s)
=== RUN   Test_LUKS1_KeyslotChangeByPassphrase
--- PASS: Test_LUKS1_KeyslotChangeByPassphrase (14.14s)
=== RUN   Test_LUKS1_Resize
    main_test.go:30: libcryptsetup function 'crypt_resize' returned error with code '-22'.
--- FAIL: Test_LUKS1_Resize (1.60s)
=== RUN   Test_LUKS2_Format
--- PASS: Test_LUKS2_Format (1.49s)
=== RUN   Test_LUKS2_Format_Using_PbkdfType
--- PASS: Test_LUKS2_Format_Using_PbkdfType (1.16s)
=== RUN   Test_LUKS2_Format_Using_IntegrityParams_Should_Fail_For_Invalid_Parameters
--- PASS: Test_LUKS2_Format_Using_IntegrityParams_Should_Fail_For_Invalid_Parameters (0.00s)
=== RUN   Test_LUKS2_Format_Using_IntegrityParams
--- PASS: Test_LUKS2_Format_Using_IntegrityParams (1.56s)
=== RUN   Test_LUKS2_Load_ActivateByPassphrase_Deactivate
--- PASS: Test_LUKS2_Load_ActivateByPassphrase_Deactivate (10.56s)
=== RUN   Test_LUKS2_Load_ActivateByPassphrase_Free_InitByName_Deactivate
--- PASS: Test_LUKS2_Load_ActivateByPassphrase_Free_InitByName_Deactivate (7.91s)
=== RUN   Test_LUKS2_ActivateByVolumeKey_Deactivate
--- PASS: Test_LUKS2_ActivateByVolumeKey_Deactivate (1.99s)
=== RUN   Test_LUKS2_ActivateByAutoGeneratedVolumeKey_Deactivate
--- PASS: Test_LUKS2_ActivateByAutoGeneratedVolumeKey_Deactivate (1.48s)
=== RUN   Test_LUKS2_KeyslotAddByVolumeKey
--- PASS: Test_LUKS2_KeyslotAddByVolumeKey (6.87s)
=== RUN   Test_LUKS2_KeyslotAddByPassphrase
--- PASS: Test_LUKS2_KeyslotAddByPassphrase (9.92s)
=== RUN   Test_LUKS2_KeyslotChangeByPassphrase
--- PASS: Test_LUKS2_KeyslotChangeByPassphrase (14.59s)
=== RUN   Test_LUKS2_Wipe
    luks2_test.go:347: Wipe in progress: 0.00%
    luks2_test.go:347: Wipe in progress: 2.25%
    luks2_test.go:347: Wipe in progress: 4.49%
    luks2_test.go:347: Wipe in progress: 6.74%
    luks2_test.go:347: Wipe in progress: 8.98%
    luks2_test.go:347: Wipe in progress: 11.23%
    luks2_test.go:347: Wipe in progress: 13.48%
    luks2_test.go:347: Wipe in progress: 15.72%
    luks2_test.go:347: Wipe in progress: 17.97%
    luks2_test.go:347: Wipe in progress: 20.21%
    luks2_test.go:347: Wipe in progress: 22.46%
    luks2_test.go:347: Wipe in progress: 24.71%
    luks2_test.go:347: Wipe in progress: 26.95%
    luks2_test.go:347: Wipe in progress: 29.20%
    luks2_test.go:347: Wipe in progress: 31.44%
    luks2_test.go:347: Wipe in progress: 33.69%
    luks2_test.go:347: Wipe in progress: 35.94%
    luks2_test.go:347: Wipe in progress: 38.18%
    luks2_test.go:347: Wipe in progress: 40.43%
    luks2_test.go:347: Wipe in progress: 42.67%
    luks2_test.go:347: Wipe in progress: 44.92%
    luks2_test.go:347: Wipe in progress: 47.17%
    luks2_test.go:347: Wipe in progress: 49.41%
    luks2_test.go:347: Wipe in progress: 51.66%
    luks2_test.go:347: Wipe in progress: 53.90%
    luks2_test.go:347: Wipe in progress: 56.15%
    luks2_test.go:347: Wipe in progress: 58.40%
    luks2_test.go:347: Wipe in progress: 60.64%
    luks2_test.go:347: Wipe in progress: 62.89%
    luks2_test.go:347: Wipe in progress: 65.13%
    luks2_test.go:347: Wipe in progress: 67.38%
    luks2_test.go:347: Wipe in progress: 69.63%
    luks2_test.go:347: Wipe in progress: 71.87%
    luks2_test.go:347: Wipe in progress: 74.12%
    luks2_test.go:347: Wipe in progress: 76.36%
    luks2_test.go:347: Wipe in progress: 78.61%
    luks2_test.go:347: Wipe in progress: 80.86%
    luks2_test.go:347: Wipe in progress: 83.10%
    luks2_test.go:347: Wipe in progress: 85.35%
    luks2_test.go:347: Wipe in progress: 87.59%
    luks2_test.go:347: Wipe in progress: 89.84%
    luks2_test.go:347: Wipe in progress: 92.09%
    luks2_test.go:347: Wipe in progress: 94.33%
    luks2_test.go:347: Wipe in progress: 96.58%
    luks2_test.go:347: Wipe in progress: 98.82%
    luks2_test.go:347: Wipe in progress: 100.00%
--- PASS: Test_LUKS2_Wipe (1.78s)
=== RUN   Test_LUKS2_Resize
    main_test.go:30: libcryptsetup function 'crypt_resize' returned error with code '-22'.
--- FAIL: Test_LUKS2_Resize (1.62s)
=== RUN   Test_Plain_ActivateByPassphrase_Deactivate
--- PASS: Test_Plain_ActivateByPassphrase_Deactivate (0.08s)
=== RUN   Test_Plain_ActivateByPassphrase_Free_InitByName_Deactivate
--- PASS: Test_Plain_ActivateByPassphrase_Free_InitByName_Deactivate (0.04s)
=== RUN   Test_Plain_ActivateByVolumeKey_Deactivate
--- PASS: Test_Plain_ActivateByVolumeKey_Deactivate (0.10s)
=== RUN   Test_Plain_Format_Should_Not_Be_Supported
--- PASS: Test_Plain_Format_Should_Not_Be_Supported (0.01s)
=== RUN   Test_Plain_KeyslotAddByVolumeKey_Should_Not_Be_Supported
--- PASS: Test_Plain_KeyslotAddByVolumeKey_Should_Not_Be_Supported (0.00s)
=== RUN   Test_Plain_KeyslotAddByPassphrase_Should_Not_Be_Supported
--- PASS: Test_Plain_KeyslotAddByPassphrase_Should_Not_Be_Supported (0.00s)
=== RUN   Test_Plain_KeyslotChangeByPassphrase_Should_Not_Be_Supported
--- PASS: Test_Plain_KeyslotChangeByPassphrase_Should_Not_Be_Supported (0.00s)
=== RUN   Test_Plain_Resize
    main_test.go:30: libcryptsetup function 'crypt_resize' returned error with code '-22'.
--- FAIL: Test_Plain_Resize (0.16s)
FAIL
FAIL	github.com/martinjungblut/go-cryptsetup	137.942s
FAIL

Hi @yunginnanet,

Just so I'm aware, what distro are you using?
I'll dig deeper into this issue over the next few days, get back to you ASAP.

Thanks for submitting this.

cat /etc/issue && cat /etc/issue.net

Welcome to antiX. Powered by Debian.
Debian GNU/Linux bookworm/sid

Thanks for the prompt response! Let me know what else I can do to help

@yunginnanet Ok, I'm able to reproduce this, seems to be related to cryptsetup's 2.4 release.
I'm investigating the situation, will come up with a fix soon.

@yunginnanet Hi, hope you've been doing well.

So I'm still working on this issue, started working heavily on it a couple of days ago. Bit of a puzzler. When trying to resize the device, libcryptsetup logs the following message:

Level: -1 Message: Data devices do not match.

I have traced the exact line that produces this message in the upstream C code. I think I'll have a solution soon, but I'm still not sure why this is happening.

Thanks

I am quite fascinated by this, and while I may not be overflowing with free time, I'd love to see what you've found out! Maybe I can help :)

I am quite fascinated by this, and while I may not be overflowing with free time, I'd love to see what you've found out! Maybe I can help :)

@yunginnanet Thanks, that's great! Started following you as well, btw.

This is what I get when I run the following modified test:

func Test_LUKS1_Resize(test *testing.T) {
	SetDebugLevel(CRYPT_DEBUG_ALL)
	SetLogCallback(func(level int, message string) {
		fmt.Printf("Level: %d Message: %s\n", level, message)
	})

	testWrapper := TestWrapper{test}

	genericParams := GenericParams{
		Cipher:        "aes",
		CipherMode:    "xts-plain64",
		VolumeKey:     generateKey(512/8, test),
		VolumeKeySize: 512 / 8,
	}

	device, err := Init(DevicePath)
	testWrapper.AssertNoError(err)
	defer device.Free()

	err = device.Format(LUKS1{Hash: "sha256"}, genericParams)
	testWrapper.AssertNoError(err)

	err = device.ActivateByVolumeKey(DeviceName, genericParams.VolumeKey, genericParams.VolumeKeySize, CRYPT_ACTIVATE_READONLY)
	testWrapper.AssertNoError(err)
	defer device.Deactivate(DeviceName)

	resize(DevicePath)

	err = device.Resize(DeviceName, 0)
	testWrapper.AssertNoError(err)
	SetDebugLevel(CRYPT_DEBUG_NONE)
}
=== RUN   Test_LUKS1_Resize
Level: -1 Message: Allocating context for crypt device testDevice.

Level: -1 Message: Trying to open and read device testDevice with direct-io.

Level: -1 Message: Initialising device-mapper backend library.

Level: -1 Message: Formatting device testDevice as type LUKS1.

Level: -1 Message: Crypto backend (OpenSSL 3.0.5 5 Jul 2022 [default][legacy]) initialized in cryptsetup library version 2.4.3.

Level: -1 Message: Detected kernel Linux 5.19.15-201.fc36.x86_64 x86_64.

Level: -1 Message: PBKDF pbkdf2-sha256, time_ms 2000 (iterations 0).

Level: -1 Message: Topology info for testDevice not supported, using default offset 1048576 bytes.

Level: -1 Message: Checking if cipher aes-xts-plain64 is usable.

Level: -1 Message: Using userspace crypto wrapper to access keyslot area.

Level: -1 Message: Generating LUKS header version 1 using hash sha256, aes, xts-plain64, MK 64 bytes

Level: -1 Message: Running pbkdf2(sha256) benchmark.

Level: -1 Message: PBKDF benchmark: memory cost = 0, iterations = 862315, threads = 0 (took 38 ms)

Level: -1 Message: PBKDF benchmark: memory cost = 0, iterations = 918192, threads = 0 (took 571 ms)

Level: -1 Message: Benchmark returns pbkdf2(sha256) 918192 iterations, 0 memory, 0 threads (for 512-bits key).

Level: -1 Message: Data offset 4096, UUID fe30ebe1-0b5c-4e48-acaf-d954dcd88fed, digest iterations 114774

Level: -1 Message: Wiping LUKS areas (0x000000 - 0x200000) with zeroes.

Level: -1 Message: Wiping keyslot 0 area (0x001000 - 0x03f800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 1 area (0x040000 - 0x07e800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 2 area (0x07f000 - 0x0bd800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 3 area (0x0be000 - 0x0fc800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 4 area (0x0fd000 - 0x13b800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 5 area (0x13c000 - 0x17a800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 6 area (0x17b000 - 0x1b9800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Wiping keyslot 7 area (0x1ba000 - 0x1f8800) with random data.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Updating LUKS header of size 1024 on device testDevice

Level: -1 Message: Key length 64, device size 131072 sectors, header size 4036 sectors.

Level: -1 Message: Reusing open rw fd on device testDevice

Level: -1 Message: Reading LUKS header of size 1024 from device testDevice

Level: -1 Message: Reusing open ro fd on device testDevice

Level: -1 Message: Key length 64, device size 131072 sectors, header size 4036 sectors.

Level: -1 Message: Activating volume testDeviceName by volume key.

Level: -1 Message: dm version   [ opencount flush ]   [16384] (*1)

Level: -1 Message: dm versions   [ opencount flush ]   [16384] (*1)

Level: -1 Message: Detected dm-ioctl version 4.47.0.

Level: -1 Message: Detected dm-crypt version 1.24.0.

Level: -1 Message: Device-mapper backend running with UDEV support enabled.

Level: -1 Message: dm status testDeviceName  [ opencount noflush ]   [16384] (*1)

Level: -1 Message: dm versions   [ opencount flush ]   [16384] (*1)

Level: -1 Message: dm status testDeviceName  [ opencount noflush ]   [16384] (*1)

Level: -1 Message: Allocating a free loop device (block size: 512).

Level: -1 Message: Trying to open and read device /dev/loop0 with direct-io.

Level: -1 Message: Attached loop device block size is 512 bytes.

Level: -1 Message: Calculated device size is 126976 sectors (RW), offset 4096.

Level: -1 Message: DM-UUID is CRYPT-LUKS1-fe30ebe10b5c4e48acafd954dcd88fed-testDeviceName

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) created

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) incremented to 1

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) incremented to 2

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) assigned to CREATE task(0) with flags DISABLE_LIBRARY_FALLBACK         (0x20)

Level: -1 Message: dm create testDeviceName CRYPT-LUKS1-fe30ebe10b5c4e48acafd954dcd88fed-testDeviceName [ opencount flush ]   [16384] (*1)

Level: -1 Message: dm reload   (253:0) [ opencount flush readonly securedata ]   [16384] (*1)

Level: -1 Message: dm resume testDeviceName  [ opencount flush readonly securedata ]   [16384] (*1)

Level: -1 Message: testDeviceName: Stacking NODE_ADD (253,0) 0:6 0660 [trust_udev]

Level: -1 Message: testDeviceName: Stacking NODE_READ_AHEAD 256 (flags=1)

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) decremented to 1

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) waiting for zero

Level: -1 Message: Udev cookie 0xd4d23fd (semid 98352) destroyed

Level: -1 Message: testDeviceName: Skipping NODE_ADD (253,0) 0:6 0660 [trust_udev]

Level: -1 Message: testDeviceName: Processing NODE_READ_AHEAD 256 (flags=1)

Level: -1 Message: testDeviceName (253:0): read ahead is 256

Level: -1 Message: testDeviceName: retaining kernel read ahead of 256 (requested 256)

Level: -1 Message: Resizing device testDeviceName to 0 sectors.

Level: -1 Message: dm versions   [ opencount flush ]   [16384] (*1)

Level: -1 Message: dm table testDeviceName  [ opencount flush securedata ]   [16384] (*1)

Level: -1 Message: Trying to resize underlying loop device /dev/loop0.

Level: -1 Message: Calculated device size is 192512 sectors (RW), offset 4096.

Level: -1 Message: dm versions   [ opencount flush ]   [16384] (*1)

Level: -1 Message: dm table testDeviceName  [ opencount flush securedata ]   [16384] (*1)

Level: -1 Message: Trying to open and read device /dev/loop0 with direct-io.

Level: -1 Message: Data devices do not match.

Level: 1 Message: Mismatching parameters on device testDeviceName.

    main_test.go:30: libcryptsetup function 'crypt_resize' returned error with code '-22'.
--- FAIL: Test_LUKS1_Resize (1.16s)
FAIL
FAIL	github.com/martinjungblut/go-cryptsetup	1.228s
FAIL

@yunginnanet That "Data devices do not match" messages, from what I gathered, comes from this line:

https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/setup.c#L2494

I've also tested on Arch Linux, linking against libcryptsetup 2.5.0 (slightly newer version than I have on Fedora 36, 2.4.3). Same issue.

@yunginnanet Hey, I found the solution. I'll update the main branch at some point in the next few days, and report the solution here.

@yunginnanet Ok, ignore my previous comment. I'm getting really close to finding the solution, but it's still broken for LUKS2.

But I know what is happening: whenever crypt_resize is called, there's an internal comparison between the device's current state, and its target state (what its state should be after it's been successfully resized).
However, when these two states are compared, different filesystem paths are being used. One of the states is reported as being bound to the loopback device /dev/loop0. The other state is reported as being bound to the underlying device node, what would normally be /dev/sdX or testDevice, in case of our test suite. Thus, the comparison fails, and crypt_resize returns EINVAL.

This might be an issue with upstream libcryptsetup.
The actual resize command, if we're simply running the cryptsetup binary directly, will actually initialise another device handle, and then the problem goes away, because that's a newly initialised device handle, just pointing to a device that's already been formatted, and is currently active.

So I'll write a detailed issue over there, together with a C program trying to replicate this issue, see if they can help us out.

you're awesome. sorry I haven't had time to help :(

@yunginnanet Thanks, and no worries, man!

I have the C code ready to submit the bug report. I'll be doing that tomorrow :)

Is LUKS2 support just broken in general? I am getting a -22 error with crypt_activate_by_passphrase and wondering if it is the same issue. I am able to Init/Format/KeyslotAddByVolumeKey,KeyslotAddByPassphrase, but just can't ActivateByPassphrase without the error:

libcryptsetup function 'crypt_activate_by_passphrase' returned error with code '-22'.