Skip to content

Commit 216342b

Browse files
committed
crypsetup: only activate disks with detached header
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
1 parent 032ae60 commit 216342b

File tree

4 files changed

+93
-37
lines changed

4 files changed

+93
-37
lines changed

csi/test/mount_integration_test.go

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import (
2727
)
2828

2929
const (
30-
devicePath string = "testDevice"
31-
deviceName string = "testDeviceName"
30+
defaultBackingImage = "testDevice"
31+
deviceName = "testDeviceName"
3232
)
3333

3434
var toolsEnvs = []string{"CP", "DD", "RM", "FSCK_EXT4", "MKFS_EXT4", "BLKID", "FSCK", "MOUNT", "UMOUNT"}
@@ -57,20 +57,35 @@ func addToolsToPATH() error {
5757
return nil
5858
}
5959

60-
func setup(devicePath string) {
61-
if err := exec.Command("dd", "if=/dev/zero", fmt.Sprintf("of=%s", devicePath), "bs=64M", "count=1").Run(); err != nil {
60+
func setup(backingDisk string) string {
61+
if err := exec.Command("dd", "if=/dev/zero", fmt.Sprintf("of=%s", backingDisk), "bs=64M", "count=1").Run(); err != nil {
6262
panic(err)
6363
}
64+
out, err := exec.Command("losetup", "-f", "--show", backingDisk).CombinedOutput()
65+
if err != nil {
66+
panic(err)
67+
}
68+
return strings.TrimSpace(string(out))
6469
}
6570

66-
func teardown(devicePath string) {
67-
if err := exec.Command("rm", "-f", devicePath).Run(); err != nil {
71+
func teardown(backingImage, devicePath string) {
72+
if err := exec.Command("losetup", "-d", devicePath).Run(); err != nil {
73+
panic(err)
74+
}
75+
if err := exec.Command("rm", "-f", backingImage).Run(); err != nil {
6876
panic(err)
6977
}
7078
}
7179

72-
func cp(source, target string) error {
73-
return exec.Command("cp", source, target).Run()
80+
func cp(source, target string) (string, error) {
81+
if err := exec.Command("cp", source, target).Run(); err != nil {
82+
return "", err
83+
}
84+
out, err := exec.Command("losetup", "-f", "--show", target).CombinedOutput()
85+
if err != nil {
86+
return "", err
87+
}
88+
return strings.TrimSpace(string(out)), nil
7489
}
7590

7691
func resize(devicePath string) {
@@ -100,8 +115,8 @@ func TestMain(m *testing.M) {
100115
func TestOpenAndClose(t *testing.T) {
101116
assert := assert.New(t)
102117
require := require.New(t)
103-
setup(devicePath)
104-
defer teardown(devicePath)
118+
devicePath := setup(defaultBackingImage)
119+
defer teardown(defaultBackingImage, devicePath)
105120

106121
mapper := cryptmapper.New(&fakeKMS{})
107122

@@ -124,7 +139,7 @@ func TestOpenAndClose(t *testing.T) {
124139
assert.Equal(newPath, newPath2)
125140

126141
// Resize the device
127-
resize(devicePath)
142+
resize(defaultBackingImage)
128143

129144
resizedPath, err := mapper.ResizeCryptDevice(t.Context(), deviceName)
130145
require.NoError(err)
@@ -145,8 +160,8 @@ func TestOpenAndClose(t *testing.T) {
145160
func TestOpenAndCloseIntegrity(t *testing.T) {
146161
assert := assert.New(t)
147162
require := require.New(t)
148-
setup(devicePath)
149-
defer teardown(devicePath)
163+
devicePath := setup(defaultBackingImage)
164+
defer teardown(defaultBackingImage, devicePath)
150165

151166
mapper := cryptmapper.New(&fakeKMS{})
152167

@@ -167,7 +182,7 @@ func TestOpenAndCloseIntegrity(t *testing.T) {
167182
assert.Equal(newPath, newPath2)
168183

169184
// integrity devices do not support resizing
170-
resize(devicePath)
185+
resize(defaultBackingImage)
171186
_, err = mapper.ResizeCryptDevice(t.Context(), deviceName)
172187
assert.Error(err)
173188

@@ -189,18 +204,19 @@ func TestOpenAndCloseIntegrity(t *testing.T) {
189204
func TestDeviceCloning(t *testing.T) {
190205
assert := assert.New(t)
191206
require := require.New(t)
192-
setup(devicePath)
193-
defer teardown(devicePath)
207+
devicePath := setup(defaultBackingImage)
208+
defer teardown(defaultBackingImage, devicePath)
194209

195210
mapper := cryptmapper.New(&dynamicKMS{})
196211

197212
_, err := mapper.OpenCryptDevice(t.Context(), devicePath, deviceName, false)
198213
assert.NoError(err)
199214

200-
require.NoError(cp(devicePath, devicePath+"-copy"))
201-
defer teardown(devicePath + "-copy")
215+
cpDevice, err := cp(defaultBackingImage, defaultBackingImage+"-copy")
216+
require.NoError(err)
217+
defer teardown(defaultBackingImage+"-copy", cpDevice)
202218

203-
_, err = mapper.OpenCryptDevice(t.Context(), devicePath+"-copy", deviceName+"-copy", false)
219+
_, err = mapper.OpenCryptDevice(t.Context(), cpDevice, deviceName+"-copy", false)
204220
assert.NoError(err)
205221

206222
assert.NoError(mapper.CloseCryptDevice(deviceName))
@@ -209,12 +225,12 @@ func TestDeviceCloning(t *testing.T) {
209225

210226
func TestConcurrency(t *testing.T) {
211227
assert := assert.New(t)
212-
setup(devicePath)
213-
defer teardown(devicePath)
228+
devicePath := setup(defaultBackingImage)
229+
defer teardown(defaultBackingImage, devicePath)
214230

215-
device2 := devicePath + "-2"
216-
setup(device2)
217-
defer teardown(device2)
231+
backingImage2 := defaultBackingImage + "-2"
232+
device2 := setup(backingImage2)
233+
defer teardown(backingImage2, device2)
218234

219235
mapper := cryptmapper.New(&fakeKMS{})
220236

disk-mapper/internal/test/integration_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package integration
1010

1111
import (
1212
"encoding/json"
13+
"errors"
1314
"flag"
1415
"fmt"
1516
"log/slog"
@@ -31,10 +32,12 @@ import (
3132
)
3233

3334
const (
34-
devicePath = "testDevice"
35+
backingDisk = "testDevice"
3536
mappedDevice = "mappedDevice"
3637
)
3738

39+
var devicePath string
40+
3841
var diskPath = flag.String("disk", "", "Path to the disk to use for the benchmark")
3942

4043
var toolsEnvs = []string{"DD", "RM"}
@@ -64,11 +67,22 @@ func addToolsToPATH() error {
6467
}
6568

6669
func setup(sizeGB int) error {
67-
return exec.Command("dd", "if=/dev/random", fmt.Sprintf("of=%s", devicePath), "bs=1G", fmt.Sprintf("count=%d", sizeGB)).Run()
70+
if err := exec.Command("dd", "if=/dev/random", fmt.Sprintf("of=%s", backingDisk), "bs=1G", fmt.Sprintf("count=%d", sizeGB)).Run(); err != nil {
71+
return err
72+
}
73+
cmd := exec.Command("losetup", "-f", "--show", backingDisk)
74+
out, err := cmd.CombinedOutput()
75+
if err != nil {
76+
return fmt.Errorf("losetup failed: %w\nOutput: %s", err, out)
77+
}
78+
devicePath = strings.TrimSpace(string(out))
79+
return nil
6880
}
6981

7082
func teardown() error {
71-
return exec.Command("rm", "-f", devicePath).Run()
83+
err := exec.Command("losetup", "-d", devicePath).Run()
84+
errors.Join(err, exec.Command("rm", "-f", backingDisk).Run())
85+
return err
7286
}
7387

7488
func TestMain(m *testing.M) {

internal/cryptsetup/cryptsetup.go

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ func (c *CryptSetup) Free() {
121121
func (c *CryptSetup) ActivateByPassphrase(deviceName string, keyslot int, passphrase string, flags int) error {
122122
packageLock.Lock()
123123
defer packageLock.Unlock()
124-
device, err := c.getActiveDevice()
125-
if err != nil {
126-
return err
124+
if !c.hasDetachedHeaderDevice() {
125+
if err := c.reload(); err != nil {
126+
return fmt.Errorf("re-loading crypt device for activation: %w", err)
127+
}
127128
}
128-
if err := device.ActivateByPassphrase(deviceName, keyslot, passphrase, flags); err != nil {
129+
if err := c.deviceWithDetachedHeader.ActivateByPassphrase(deviceName, keyslot, passphrase, flags); err != nil {
129130
return fmt.Errorf("activating crypt device %q using passphrase: %w", deviceName, err)
130131
}
131132
return nil
@@ -136,11 +137,12 @@ func (c *CryptSetup) ActivateByPassphrase(deviceName string, keyslot int, passph
136137
func (c *CryptSetup) ActivateByVolumeKey(deviceName, volumeKey string, volumeKeySize, flags int) error {
137138
packageLock.Lock()
138139
defer packageLock.Unlock()
139-
device, err := c.getActiveDevice()
140-
if err != nil {
141-
return err
140+
if !c.hasDetachedHeaderDevice() {
141+
if err := c.reload(); err != nil {
142+
return fmt.Errorf("re-loading crypt device for activation: %w", err)
143+
}
142144
}
143-
if err := device.ActivateByVolumeKey(deviceName, volumeKey, volumeKeySize, flags); err != nil {
145+
if err := c.deviceWithDetachedHeader.ActivateByVolumeKey(deviceName, volumeKey, volumeKeySize, flags); err != nil {
144146
return fmt.Errorf("activating crypt device %q using volume key: %w", deviceName, err)
145147
}
146148
return nil
@@ -441,6 +443,30 @@ func (c *CryptSetup) free() {
441443
}
442444
}
443445

446+
func (c *CryptSetup) reload() error {
447+
if !c.hasAttachedHeaderDevice() {
448+
return errDeviceNotOpen
449+
}
450+
451+
backingDevice := c.deviceWithAttachedHeader.GetDeviceName()
452+
c.free()
453+
var err error
454+
c.deviceWithDetachedHeader, c.deviceWithAttachedHeader, c.headerDevice, c.headerFile, err = c.pathInit(backingDevice)
455+
if err != nil {
456+
return fmt.Errorf("re-loading crypt device: %w", err)
457+
}
458+
459+
if !c.hasDetachedHeaderDevice() {
460+
return errors.New("failed to reload device without detached header")
461+
}
462+
463+
if err := loadLUKS2(c.deviceWithDetachedHeader); err != nil {
464+
return err
465+
}
466+
467+
return nil
468+
}
469+
444470
// getActiveDevice returns a handle to the active cryptsetup device with detached header if set,
445471
// or one with attached header otherwise.
446472
func (c *CryptSetup) getActiveDevice() (cryptDevice, error) {

internal/cryptsetup/cryptsetup_cgo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func initByDevicePath(devicePath string) (deviceDetachedHeader, deviceAttachedHe
9797
}
9898
// If the device is not LUKS2 formatted, this is treated as a new device,
9999
// meaning no header exists yet
100-
if tmpDevice.Load(cryptsetup.LUKS2{}) != nil {
100+
if err := tmpDevice.Load(cryptsetup.LUKS2{}); err != nil {
101101
return nil, tmpDevice, "", "", nil
102102
}
103103
defer tmpDevice.Free()
@@ -133,7 +133,7 @@ func initByName(name string) (deviceDetachedHeader, deviceAttachedHeader cryptDe
133133
}
134134
// If the device is not LUKS2 formatted, this is treated as a new device,
135135
// meaning no header exists yet
136-
if tmpDevice.Load(cryptsetup.LUKS2{}) != nil {
136+
if err := tmpDevice.Load(cryptsetup.LUKS2{}); err != nil {
137137
return nil, tmpDevice, "", "", nil
138138
}
139139
defer tmpDevice.Free()

0 commit comments

Comments
 (0)