From 6491f5fc75a89f18eee939d7e34fbccb0994cc3b Mon Sep 17 00:00:00 2001 From: Valentin David Date: Wed, 21 Aug 2024 12:36:40 +0200 Subject: [PATCH] secboot: use uuid of luks2 instead of partition --- osutil/disks/disks_darwin.go | 8 -- osutil/disks/disks_linux.go | 38 ++++---- osutil/disks/disks_linux_test.go | 86 +++---------------- .../devicestate_install_mode_test.go | 8 +- overlord/devicestate/devicestate_test.go | 5 +- overlord/devicestate/export_test.go | 9 +- overlord/devicestate/handlers_install.go | 14 ++- secboot/encrypt_sb.go | 24 +++--- secboot/encrypt_sb_test.go | 52 +++++------ secboot/secboot_sb.go | 18 ++-- secboot/secboot_sb_test.go | 41 ++++++--- 11 files changed, 118 insertions(+), 185 deletions(-) diff --git a/osutil/disks/disks_darwin.go b/osutil/disks/disks_darwin.go index 2e98b5f2795..afc5f81686f 100644 --- a/osutil/disks/disks_darwin.go +++ b/osutil/disks/disks_darwin.go @@ -67,14 +67,6 @@ var diskFromPartitionDeviceNode = func(node string) (Disk, error) { return nil, osutil.ErrDarwin } -func PartitionUUIDFromMountPoint(mountpoint string, opts *Options) (string, error) { - return "", osutil.ErrDarwin -} - -func PartitionUUID(node string) (string, error) { - return "", osutil.ErrDarwin -} - func SectorSize(devname string) (uint64, error) { return 0, osutil.ErrDarwin } diff --git a/osutil/disks/disks_linux.go b/osutil/disks/disks_linux.go index 6781aefa3fd..08d1c4b9c8b 100644 --- a/osutil/disks/disks_linux.go +++ b/osutil/disks/disks_linux.go @@ -29,6 +29,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "sort" "strconv" "strings" @@ -963,41 +964,40 @@ func AllPhysicalDisks() ([]Disk, error) { return disks, nil } -// PartitionUUIDFromMountPoint returns the UUID of the partition which is a -// source of a given mount point. -func PartitionUUIDFromMountPoint(mountpoint string, opts *Options) (string, error) { +var dmUUIDRe = regexp.MustCompile(`^CRYPT-(?P.*)-(?P[0-9a-f]{8})(?P[0-9a-f]{4})(?P[0-9a-f]{4})(?P[0-9a-f]{4})(?P[0-9a-f]{12})-(?P.*)$`) + +func DmCryptUUIDFromMountPoint(mountpoint string) (string, error) { _, props, err := partitionPropsFromMountPoint(mountpoint) if err != nil { return "", err } - if opts != nil && opts.IsDecryptedDevice { - props, err = parentPartitionPropsForOptions(props) - if err != nil { - return "", err - } + dmUUID, hasDmUUID := props["DM_UUID"] + if !hasDmUUID { + return "", fmt.Errorf("device has no DM_UUID") } - partUUID := props["ID_PART_ENTRY_UUID"] - if partUUID == "" { - partDev := filepath.Join("/dev", props["DEVNAME"]) - return "", fmt.Errorf("cannot get required partition UUID udev property for device %s", partDev) + match := dmUUIDRe.FindStringSubmatchIndex(dmUUID) + if match == nil { + return "", fmt.Errorf("value of DM_UUID is not recognized") } - return partUUID, nil + + result := []byte{} + result = dmUUIDRe.ExpandString(result, "${uuid1}-${uuid2}-${uuid3}-${uuid4}-${uuid5}", dmUUID, match) + return string(result), nil } -// PartitionUUID returns the UUID of a given partition -func PartitionUUID(node string) (string, error) { +func FilesystemUUID(node string) (string, error) { props, err := udevPropertiesForName(node) if err != nil && props == nil { // only fail here if props is nil, if it's available we validate it // below return "", fmt.Errorf("cannot process udev properties: %v", err) } - partUUID := props["ID_PART_ENTRY_UUID"] - if partUUID == "" { - return "", fmt.Errorf("cannot get required udev partition UUID property") + uuid := props["ID_FS_UUID"] + if uuid == "" { + return "", fmt.Errorf("cannot get required udev ID_FS_UUID property") } - return partUUID, nil + return uuid, nil } func SectorSize(devname string) (uint64, error) { diff --git a/osutil/disks/disks_linux_test.go b/osutil/disks/disks_linux_test.go index ca180ea250a..add3469cb11 100644 --- a/osutil/disks/disks_linux_test.go +++ b/osutil/disks/disks_linux_test.go @@ -1849,11 +1849,11 @@ func (s *diskSuite) TestAllPhysicalDisks(c *C) { c.Assert(d[3].KernelDeviceNode(), Equals, "/dev/sdb") } -func (s *diskSuite) TestPartitionUUIDFromMopuntPointErrs(c *C) { +func (s *diskSuite) TestDmCryptUUIDFromMountPointErrs(c *C) { restore := osutil.MockMountInfo(``) defer restore() - _, err := disks.PartitionUUIDFromMountPoint("/run/mnt/blah", nil) + _, err := disks.DmCryptUUIDFromMountPoint("/run/mnt/blah") c.Assert(err, ErrorMatches, "cannot find mountpoint \"/run/mnt/blah\"") restore = osutil.MockMountInfo(`130 30 42:1 / /run/mnt/point rw,relatime shared:54 - ext4 /dev/vda4 rw @@ -1870,30 +1870,25 @@ func (s *diskSuite) TestPartitionUUIDFromMopuntPointErrs(c *C) { }) defer restore() - _, err = disks.PartitionUUIDFromMountPoint("/run/mnt/point", nil) - c.Assert(err, ErrorMatches, "cannot get required partition UUID udev property for device /dev/vda4") -} + _, err = disks.DmCryptUUIDFromMountPoint("/run/mnt/point") + c.Assert(err, ErrorMatches, "device has no DM_UUID") -func (s *diskSuite) TestPartitionUUIDFromMountPointPlain(c *C) { - restore := osutil.MockMountInfo(`130 30 42:1 / /run/mnt/point rw,relatime shared:54 - ext4 /dev/vda4 rw -`) - defer restore() restore = disks.MockUdevPropertiesForDevice(func(typeOpt, dev string) (map[string]string, error) { c.Assert(typeOpt, Equals, "--name") c.Assert(dev, Equals, "/dev/vda4") return map[string]string{ - "DEVTYPE": "disk", - "ID_PART_ENTRY_UUID": "foo-uuid", + "DEVNAME": "vda4", + "prop": "hello", + "DM_UUID": "garbage", }, nil }) defer restore() - uuid, err := disks.PartitionUUIDFromMountPoint("/run/mnt/point", nil) - c.Assert(err, IsNil) - c.Assert(uuid, Equals, "foo-uuid") + _, err = disks.DmCryptUUIDFromMountPoint("/run/mnt/point") + c.Assert(err, ErrorMatches, "value of DM_UUID is not recognized") } -func (s *diskSuite) TestPartitionUUIDFromMopuntPointDecrypted(c *C) { +func (s *diskSuite) TestDmCryptUUIDFromMountPoint(c *C) { restore := osutil.MockMountInfo(`130 30 42:1 / /run/mnt/point rw,relatime shared:54 - ext4 /dev/mapper/something rw `) defer restore() @@ -1902,55 +1897,8 @@ func (s *diskSuite) TestPartitionUUIDFromMopuntPointDecrypted(c *C) { switch dev { case "/dev/mapper/something": return map[string]string{ - "DEVTYPE": "disk", - "MAJOR": "242", - "MINOR": "1", - }, nil - case "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304": - return map[string]string{ - "ID_PART_ENTRY_UUID": "foo-uuid", - }, nil - default: - c.Errorf("unexpected udev device properties requested: %s", dev) - return nil, fmt.Errorf("unexpected udev device: %s", dev) - } - }) - defer restore() - - // mock the sysfs dm uuid and name files - dmDir := filepath.Join(filepath.Join(dirs.SysfsDir, "dev", "block"), "242:1", "dm") - err := os.MkdirAll(dmDir, 0755) - c.Assert(err, IsNil) - - b := []byte("something") - err = os.WriteFile(filepath.Join(dmDir, "name"), b, 0644) - c.Assert(err, IsNil) - - b = []byte("CRYPT-LUKS2-5a522809c87e4dfa81a88dc5667d1304-something") - err = os.WriteFile(filepath.Join(dmDir, "uuid"), b, 0644) - c.Assert(err, IsNil) - - uuid, err := disks.PartitionUUIDFromMountPoint("/run/mnt/point", &disks.Options{ - IsDecryptedDevice: true, - }) - c.Assert(err, IsNil) - c.Assert(uuid, Equals, "foo-uuid") -} - -func (s *diskSuite) TestPartitionUUID(c *C) { - restore := disks.MockUdevPropertiesForDevice(func(typeOpt, dev string) (map[string]string, error) { - c.Assert(typeOpt, Equals, "--name") - switch dev { - case "/dev/vda4": - return map[string]string{ - "ID_PART_ENTRY_UUID": "foo-uuid", + "DM_UUID": "CRYPT-LUKS2-5a522809c87e4dfa81a88dc5667d1304-something", }, nil - case "/dev/no-uuid": - return map[string]string{ - "no-uuid": "no-uuid", - }, nil - case "/dev/mock-failure": - return nil, fmt.Errorf("mock failure") default: c.Errorf("unexpected udev device properties requested: %s", dev) return nil, fmt.Errorf("unexpected udev device: %s", dev) @@ -1958,17 +1906,9 @@ func (s *diskSuite) TestPartitionUUID(c *C) { }) defer restore() - uuid, err := disks.PartitionUUID("/dev/vda4") + uuid, err := disks.DmCryptUUIDFromMountPoint("/run/mnt/point") c.Assert(err, IsNil) - c.Assert(uuid, Equals, "foo-uuid") - - uuid, err = disks.PartitionUUID("/dev/no-uuid") - c.Assert(err, ErrorMatches, "cannot get required udev partition UUID property") - c.Check(uuid, Equals, "") - - uuid, err = disks.PartitionUUID("/dev/mock-failure") - c.Assert(err, ErrorMatches, "cannot process udev properties: mock failure") - c.Check(uuid, Equals, "") + c.Assert(uuid, Equals, "5a522809-c87e-4dfa-81a8-8dc5667d1304") } func (s *diskSuite) TestFilesystemTypeForPartition(c *C) { diff --git a/overlord/devicestate/devicestate_install_mode_test.go b/overlord/devicestate/devicestate_install_mode_test.go index 8d237720aa0..5bda0761eae 100644 --- a/overlord/devicestate/devicestate_install_mode_test.go +++ b/overlord/devicestate/devicestate_install_mode_test.go @@ -1643,7 +1643,7 @@ func (s *deviceMgrInstallModeSuite) doRunFactoryResetChange(c *C, model *asserts var chosenBootstrapKey []byte defer devicestate.MockSecbootAddBootstrapKeyOnExistingDisk(func(node string, newKey keys.EncryptionKey) error { if tc.encrypt { - c.Check(node, Equals, "/dev/disk/by-partuuid/fbbb94fb-46ea-4e00-b830-afc72d202449") + c.Check(node, Equals, "/dev/disk/by-uuid/570faa3d-e3bc-49db-979b-e7814b6bd390") chosenBootstrapKey = newKey return nil } @@ -1653,7 +1653,7 @@ func (s *deviceMgrInstallModeSuite) doRunFactoryResetChange(c *C, model *asserts defer devicestate.MockSecbootRenameOrDeleteKeys(func(node string, renames map[string]string) error { if tc.encrypt { - c.Check(node, Equals, "/dev/disk/by-partuuid/fbbb94fb-46ea-4e00-b830-afc72d202449") + c.Check(node, Equals, "/dev/disk/by-uuid/570faa3d-e3bc-49db-979b-e7814b6bd390") c.Check(renames, DeepEquals, map[string]string{ "default": "factory-reset-old", "default-fallback": "factory-reset-old-fallback", @@ -1940,7 +1940,7 @@ echo "mock output of: $(basename "$0") $*" defer disks.MockUdevPropertiesForDevice(func(string, string) (map[string]string, error) { return map[string]string{ - "ID_PART_ENTRY_UUID": "fbbb94fb-46ea-4e00-b830-afc72d202449", + "ID_FS_UUID": "570faa3d-e3bc-49db-979b-e7814b6bd390", }, nil })() @@ -2010,7 +2010,7 @@ echo "mock output of: $(basename "$0") $*" defer disks.MockUdevPropertiesForDevice(func(string, string) (map[string]string, error) { return map[string]string{ - "ID_PART_ENTRY_UUID": "fbbb94fb-46ea-4e00-b830-afc72d202449", + "ID_FS_UUID": "570faa3d-e3bc-49db-979b-e7814b6bd390", }, nil })() diff --git a/overlord/devicestate/devicestate_test.go b/overlord/devicestate/devicestate_test.go index ddf82f4fd60..7356d5f8c00 100644 --- a/overlord/devicestate/devicestate_test.go +++ b/overlord/devicestate/devicestate_test.go @@ -44,7 +44,6 @@ import ( "github.com/snapcore/snapd/kernel/fde" "github.com/snapcore/snapd/logger" "github.com/snapcore/snapd/osutil" - "github.com/snapcore/snapd/osutil/disks" "github.com/snapcore/snapd/overlord" "github.com/snapcore/snapd/overlord/assertstate" "github.com/snapcore/snapd/overlord/assertstate/assertstatetest" @@ -2199,7 +2198,7 @@ func (s *deviceMgrSuite) TestDeviceManagerEnsurePostFactoryResetEncrypted(c *C) }) defer restore() - restore = devicestate.MockDisksPartitionUUIDFromMountPoint(func(mountpoint string, opts *disks.Options) (string, error) { + restore = devicestate.MockDisksDmCryptUUIDFromMountPoint(func(mountpoint string) (string, error) { c.Check(mountpoint, Equals, boot.InitramfsUbuntuSaveDir) return "FOOUUID", nil }) @@ -2207,7 +2206,7 @@ func (s *deviceMgrSuite) TestDeviceManagerEnsurePostFactoryResetEncrypted(c *C) deleteOldSaveKey := 0 restore = devicestate.MockSecbootDeleteKeys(func(node string, matches map[string]bool) error { - c.Check(node, Equals, "/dev/disk/by-partuuid/FOOUUID") + c.Check(node, Equals, "/dev/disk/by-uuid/FOOUUID") c.Check(matches, DeepEquals, map[string]bool{ "factory-reset-old": true, "factory-reset-old-fallback": true, diff --git a/overlord/devicestate/export_test.go b/overlord/devicestate/export_test.go index edeb8f85b47..de60bb3121c 100644 --- a/overlord/devicestate/export_test.go +++ b/overlord/devicestate/export_test.go @@ -33,7 +33,6 @@ import ( "github.com/snapcore/snapd/httputil" "github.com/snapcore/snapd/kernel/fde" "github.com/snapcore/snapd/osutil" - "github.com/snapcore/snapd/osutil/disks" "github.com/snapcore/snapd/overlord/snapstate" "github.com/snapcore/snapd/overlord/state" "github.com/snapcore/snapd/overlord/storecontext" @@ -628,10 +627,10 @@ func MockSecbootDeleteKeys(f func(node string, matches map[string]bool) error) ( } } -func MockDisksPartitionUUIDFromMountPoint(f func(mountpoint string, opts *disks.Options) (string, error)) (restore func()) { - old := disksPartitionUUIDFromMountPoint - disksPartitionUUIDFromMountPoint = f +func MockDisksDmCryptUUIDFromMountPoint(f func(mountpoint string) (string, error)) (restore func()) { + old := disksDmCryptUUIDFromMountPoint + disksDmCryptUUIDFromMountPoint = f return func() { - disksPartitionUUIDFromMountPoint = old + disksDmCryptUUIDFromMountPoint = old } } diff --git a/overlord/devicestate/handlers_install.go b/overlord/devicestate/handlers_install.go index eb651c7ad3c..a2143b80407 100644 --- a/overlord/devicestate/handlers_install.go +++ b/overlord/devicestate/handlers_install.go @@ -65,6 +65,7 @@ var ( bootMakeRunnableStandalone = boot.MakeRunnableStandaloneSystem bootMakeRunnableAfterDataReset = boot.MakeRunnableSystemAfterDataReset bootEnsureNextBootToRunMode = boot.EnsureNextBootToRunMode + disksDmCryptUUIDFromMountPoint = disks.DmCryptUUIDFromMountPoint installRun = install.Run installFactoryReset = install.FactoryReset installMountVolumes = install.MountVolumes @@ -610,11 +611,11 @@ func (m *DeviceManager) doFactoryResetRunSystem(t *state.Task, _ *tomb.Tomb) err return fmt.Errorf("internal error: no system-save device") } - uuid, err := disks.PartitionUUID(saveNode) + uuid, err := disks.FilesystemUUID(saveNode) if err != nil { return fmt.Errorf("cannot find uuid for partition %s: %v", saveNode, err) } - saveNode = fmt.Sprintf("/dev/disk/by-partuuid/%s", uuid) + saveNode = fmt.Sprintf("/dev/disk/by-uuid/%s", uuid) saveBoostrapContainer, err := createSaveBootstrappedContainer(saveNode) if err != nil { @@ -1191,7 +1192,6 @@ var ( secbootRenameOrDeleteKeys = secboot.RenameOrDeleteKeys secbootCreateBootstrappedContainer = secboot.CreateBootstrappedContainer secbootDeleteKeys = secboot.DeleteKeys - disksPartitionUUIDFromMountPoint = disks.PartitionUUIDFromMountPoint ) func createSaveBootstrappedContainer(saveNode string) (secboot.BootstrappedContainer, error) { @@ -1242,14 +1242,12 @@ func deleteOldSaveKey(saveMntPnt string) error { // keys. // FIXME: maybe there is better if we had a function returning the devname instead. - partUUID, err := disksPartitionUUIDFromMountPoint(saveMntPnt, &disks.Options{ - IsDecryptedDevice: true, - }) + uuid, err := disksDmCryptUUIDFromMountPoint(saveMntPnt) if err != nil { - return fmt.Errorf("cannot partition save partition: %v", err) + return fmt.Errorf("cannot find save partition: %v", err) } - diskPath := filepath.Join("/dev/disk/by-partuuid", partUUID) + diskPath := filepath.Join("/dev/disk/by-uuid", uuid) toDelete := map[string]bool{ "factory-reset-old": true, diff --git a/secboot/encrypt_sb.go b/secboot/encrypt_sb.go index a5c3c9a170a..90695dd0e2f 100644 --- a/secboot/encrypt_sb.go +++ b/secboot/encrypt_sb.go @@ -26,7 +26,6 @@ import ( "fmt" "io" "os" - "path/filepath" sb "github.com/snapcore/secboot" @@ -107,7 +106,7 @@ func EnsureRecoveryKey(keyFile string, rkeyDevs []RecoveryKeyDevice) (keys.Recov keyFile string } for _, rkeyDev := range rkeyDevs { - dev, err := devByPartUUIDFromMount(rkeyDev.Mountpoint) + dev, err := devFromMount(rkeyDev.Mountpoint) if err != nil { return keys.RecoveryKey{}, fmt.Errorf("cannot find matching device for: %v", err) } @@ -219,15 +218,13 @@ func EnsureRecoveryKey(keyFile string, rkeyDevs []RecoveryKeyDevice) (keys.Recov } } -func devByPartUUIDFromMount(mp string) (string, error) { - partUUID, err := disks.PartitionUUIDFromMountPoint(mp, &disks.Options{ - IsDecryptedDevice: true, - }) +func devFromMount(mp string) (string, error) { + uuid, err := disks.DmCryptUUIDFromMountPoint(mp) if err != nil { return "", fmt.Errorf("cannot partition for mount %v: %v", mp, err) } - dev := filepath.Join("/dev/disk/by-partuuid", partUUID) - return dev, nil + // TODO: make secboot accept UUID= and use that + return fmt.Sprintf("/dev/disk/by-uuid/%s", uuid), nil } // RemoveRecoveryKeys removes any recovery key from all encrypted block devices. @@ -239,7 +236,7 @@ func RemoveRecoveryKeys(rkeyDevToKey map[RecoveryKeyDevice]string) error { var keyFiles []string for rkeyDev, keyFile := range rkeyDevToKey { - dev, err := devByPartUUIDFromMount(rkeyDev.Mountpoint) + dev, err := devFromMount(rkeyDev.Mountpoint) if err != nil { return fmt.Errorf("cannot find matching device for: %v", err) } @@ -300,12 +297,13 @@ func RemoveRecoveryKeys(rkeyDevToKey map[RecoveryKeyDevice]string) error { // encryption key change process, a call to TransitionEncryptionKeyChange is // needed. func StageEncryptionKeyChange(node string, key keys.EncryptionKey) error { - partitionUUID, err := disks.PartitionUUID(node) + uuid, err := disks.FilesystemUUID(node) if err != nil { - return fmt.Errorf("cannot get UUID of partition %v: %v", node, err) + return fmt.Errorf("cannot get UUID of %v: %v", node, err) } - dev := filepath.Join("/dev/disk/by-partuuid", partitionUUID) + // TODO: make secboot accept UUID= and use that + dev := fmt.Sprintf("/dev/disk/by-uuid/%s", uuid) logger.Debugf("stage encryption key change on device: %v", dev) var buf bytes.Buffer @@ -334,7 +332,7 @@ func StageEncryptionKeyChange(node string, key keys.EncryptionKey) error { // device corresponding to the given mount point. The change is authorized using // the new key, thus a prior call to StageEncryptionKeyChange must be done. func TransitionEncryptionKeyChange(mountpoint string, key keys.EncryptionKey) error { - dev, err := devByPartUUIDFromMount(mountpoint) + dev, err := devFromMount(mountpoint) if err != nil { return fmt.Errorf("cannot find matching device: %v", err) } diff --git a/secboot/encrypt_sb_test.go b/secboot/encrypt_sb_test.go index 3af6d0a3ffa..a90385dd4db 100644 --- a/secboot/encrypt_sb_test.go +++ b/secboot/encrypt_sb_test.go @@ -148,6 +148,7 @@ fi s.udevadmCmd = testutil.MockCommand(c, "udevadm", ` echo "ID_PART_ENTRY_UUID=something" + echo "ID_FS_UUID=someuuid" `) s.AddCleanup(s.udevadmCmd.Restore) @@ -172,12 +173,12 @@ func (s *keymgrSuite) TestStageEncryptionKeyHappy(c *C) { "systemd-run", "--wait", "--pipe", "--collect", "--service-type=exec", "--quiet", "--property=KeyringMode=inherit", "--", - s.keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-partuuid/something", + s.keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-uuid/someuuid", "--stage", }, }) c.Check(s.keymgrCmd.Calls(), DeepEquals, [][]string{ - {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-partuuid/something", "--stage"}, + {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-uuid/someuuid", "--stage"}, }) var b bytes.Buffer json.NewEncoder(&b).Encode(struct { @@ -194,7 +195,7 @@ func (s *keymgrSuite) TestStageEncryptionKeyBadUdev(c *C) { `) defer udevadmCmd.Restore() err := secboot.StageEncryptionKeyChange("/dev/foo/bar", key) - c.Assert(err, ErrorMatches, "cannot get UUID of partition /dev/foo/bar: cannot get required udev partition UUID property") + c.Assert(err, ErrorMatches, "cannot get UUID of /dev/foo/bar: cannot get required udev ID_FS_UUID property") c.Check(udevadmCmd.Calls(), DeepEquals, [][]string{ {"udevadm", "info", "--query", "property", "--name", "/dev/foo/bar"}, }) @@ -219,12 +220,12 @@ func (s *keymgrSuite) TestStageTransitionEncryptionKeyBadKeymgr(c *C) { "systemd-run", "--wait", "--pipe", "--collect", "--service-type=exec", "--quiet", "--property=KeyringMode=inherit", "--", - keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-partuuid/something", + keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-uuid/someuuid", "--stage", }, }) c.Check(keymgrCmd.Calls(), DeepEquals, [][]string{ - {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-partuuid/something", "--stage"}, + {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-uuid/someuuid", "--stage"}, }) s.systemdRunCmd.ForgetCalls() @@ -239,12 +240,12 @@ func (s *keymgrSuite) TestStageTransitionEncryptionKeyBadKeymgr(c *C) { "systemd-run", "--wait", "--pipe", "--collect", "--service-type=exec", "--quiet", "--property=KeyringMode=inherit", "--", - keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-partuuid/foo-uuid", + keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--transition", }, }) c.Check(keymgrCmd.Calls(), DeepEquals, [][]string{ - {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-partuuid/foo-uuid", "--transition"}, + {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--transition"}, }) } @@ -268,19 +269,18 @@ func (s *keymgrSuite) TestTransitionEncryptionKeyHappy(c *C) { c.Assert(err, IsNil) c.Check(udevadmCmd.Calls(), DeepEquals, [][]string{ {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/foo"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304"}, }) c.Check(s.systemdRunCmd.Calls(), DeepEquals, [][]string{ { "systemd-run", "--wait", "--pipe", "--collect", "--service-type=exec", "--quiet", "--property=KeyringMode=inherit", "--", - s.keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-partuuid/foo-uuid", + s.keymgrCmd.Exe(), "change-encryption-key", "--device", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--transition", }, }) c.Check(s.keymgrCmd.Calls(), DeepEquals, [][]string{ - {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-partuuid/foo-uuid", "--transition"}, + {"snap-fde-keymgr", "change-encryption-key", "--device", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--transition"}, }) var b bytes.Buffer json.NewEncoder(&b).Encode(struct { @@ -308,11 +308,13 @@ while [ "$#" -gt 1 ]; do echo "DEVTYPE=disk" echo "MAJOR=600" echo "MINOR=3" + echo "DM_UUID=CRYPT-LUKS2-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo" ;; /dev/mapper/bar) echo "DEVTYPE=disk" echo "MAJOR=600" echo "MINOR=4" + echo "DM_UUID=CRYPT-LUKS2-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb-bar" ;; /dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304) echo "ID_PART_ENTRY_UUID=foo-uuid" @@ -333,12 +335,6 @@ done s.AddCleanup(func() { dirs.SetRootDir(dirs.GlobalRootDir) }) dirs.SetRootDir(s.d) - snaptest.PopulateDir(s.d, [][]string{ - {"/sys/dev/block/600:3/dm/uuid", "CRYPT-LUKS2-5a522809c87e4dfa81a88dc5667d1304-foo"}, - {"/sys/dev/block/600:3/dm/name", "foo"}, - {"/sys/dev/block/600:4/dm/uuid", "CRYPT-LUKS2-5a522809c87e4dfa81a88dc5667d1305-bar"}, - {"/sys/dev/block/600:4/dm/name", "bar"}, - }) return udevadmCmd } @@ -368,9 +364,7 @@ func (s *keymgrSuite) TestEnsureRecoveryKey(c *C) { c.Assert(err, IsNil) c.Check(udevadmCmd.Calls(), DeepEquals, [][]string{ {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/foo"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304"}, {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/bar"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1305"}, }) // A second call should not do much @@ -419,9 +413,7 @@ func (s *keymgrSuite) TestEnsureRecoveryKeyLegacy(c *C) { c.Assert(err, IsNil) c.Check(udevadmCmd.Calls(), DeepEquals, [][]string{ {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/foo"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304"}, {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/bar"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1305"}, }) c.Check(s.systemdRunCmd.Calls(), DeepEquals, [][]string{ { @@ -430,9 +422,9 @@ func (s *keymgrSuite) TestEnsureRecoveryKeyLegacy(c *C) { "--property=KeyringMode=inherit", "--", s.keymgrCmd.Exe(), "add-recovery-key", "--key-file", filepath.Join(s.d, "recovery.key"), - "--devices", "/dev/disk/by-partuuid/foo-uuid", + "--devices", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--authorizations", "keyring", - "--devices", "/dev/disk/by-partuuid/bar-uuid", + "--devices", "/dev/disk/by-uuid/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "--authorizations", "file:/authz/key.file", }, }) @@ -440,8 +432,8 @@ func (s *keymgrSuite) TestEnsureRecoveryKeyLegacy(c *C) { { "snap-fde-keymgr", "add-recovery-key", "--key-file", filepath.Join(s.d, "recovery.key"), - "--devices", "/dev/disk/by-partuuid/foo-uuid", "--authorizations", "keyring", - "--devices", "/dev/disk/by-partuuid/bar-uuid", "--authorizations", "file:/authz/key.file", + "--devices", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--authorizations", "keyring", + "--devices", "/dev/disk/by-uuid/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "--authorizations", "file:/authz/key.file", }, }) c.Check(rkey, DeepEquals, keys.RecoveryKey{'r', 'e', 'c', 'o', 'v', 'e', 'r', 'y', '1', '1', '1', '1', '1', '1', '1', '1'}) @@ -471,9 +463,7 @@ func (s *keymgrSuite) TestRemoveRecoveryKey(c *C) { expectedUdevCalls := [][]string{ // order can change depending on map iteration {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/foo"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304"}, {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/bar"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1305"}, } udevCalls := udevadmCmd.Calls() @@ -506,9 +496,7 @@ func (s *keymgrSuite) TestRemoveRecoveryKeyLegacy(c *C) { expectedUdevCalls := [][]string{ // order can change depending on map iteration {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/foo"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1304"}, {"udevadm", "info", "--query", "property", "--name", "/dev/mapper/bar"}, - {"udevadm", "info", "--query", "property", "--name", "/dev/disk/by-uuid/5a522809-c87e-4dfa-81a8-8dc5667d1305"}, } expectedSystemdRunCalls := [][]string{ { @@ -517,9 +505,9 @@ func (s *keymgrSuite) TestRemoveRecoveryKeyLegacy(c *C) { "--property=KeyringMode=inherit", "--", s.keymgrCmd.Exe(), "remove-recovery-key", // order can change depending on map iteration - "--devices", "/dev/disk/by-partuuid/foo-uuid", "--authorizations", "keyring", + "--devices", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--authorizations", "keyring", "--key-files", filepath.Join(s.d, "recovery.key"), - "--devices", "/dev/disk/by-partuuid/bar-uuid", "--authorizations", "file:/authz/key.file", + "--devices", "/dev/disk/by-uuid/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "--authorizations", "file:/authz/key.file", "--key-files", filepath.Join(s.d, "missing-recovery.key"), }, } @@ -527,9 +515,9 @@ func (s *keymgrSuite) TestRemoveRecoveryKeyLegacy(c *C) { { "snap-fde-keymgr", "remove-recovery-key", // order can change depending on map iteration - "--devices", "/dev/disk/by-partuuid/foo-uuid", "--authorizations", "keyring", + "--devices", "/dev/disk/by-uuid/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "--authorizations", "keyring", "--key-files", filepath.Join(s.d, "recovery.key"), - "--devices", "/dev/disk/by-partuuid/bar-uuid", "--authorizations", "file:/authz/key.file", + "--devices", "/dev/disk/by-uuid/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "--authorizations", "file:/authz/key.file", "--key-files", filepath.Join(s.d, "missing-recovery.key"), }, } diff --git a/secboot/secboot_sb.go b/secboot/secboot_sb.go index 21641dab843..d09c4e56fdf 100644 --- a/secboot/secboot_sb.go +++ b/secboot/secboot_sb.go @@ -79,7 +79,7 @@ func UnlockVolumeUsingSealedKeyIfEncrypted(disk disks.Disk, name string, sealedE // looking for the encrypted device to unlock, later on in the boot // process we will look for the decrypted device to ensure it matches // what we expected - partUUID, err := disk.FindMatchingPartitionUUIDWithFsLabel(EncryptedPartitionName(name)) + part, err := disk.FindMatchingPartitionWithFsLabel(EncryptedPartitionName(name)) if err == nil { res.IsEncrypted = true } else { @@ -90,13 +90,13 @@ func UnlockVolumeUsingSealedKeyIfEncrypted(disk disks.Disk, name string, sealedE } // otherwise it is an error not found and we should search for the // unencrypted device - partUUID, err = disk.FindMatchingPartitionUUIDWithFsLabel(name) + part, err = disk.FindMatchingPartitionWithFsLabel(name) if err != nil { return res, fmt.Errorf("error enumerating partitions for disk to find unencrypted device %q: %v", name, err) } } - partDevice := filepath.Join("/dev/disk/by-partuuid", partUUID) + partDevice := filepath.Join("/dev/disk/by-partuuid", part.PartitionUUID) if !res.IsEncrypted { // if we didn't find an encrypted device just return, don't try to @@ -117,14 +117,16 @@ func UnlockVolumeUsingSealedKeyIfEncrypted(disk disks.Disk, name string, sealedE // make up a new name for the mapped device mapperName := name + "-" + uuid - sourceDevice := partDevice + sourceDevice := fmt.Sprintf("/dev/disk/by-uuid/%s", part.FilesystemUUID) targetDevice := filepath.Join("/dev/mapper", mapperName) if fdeHasRevealKey() { - return unlockVolumeUsingSealedKeyFDERevealKey(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) + res, err = unlockVolumeUsingSealedKeyFDERevealKey(sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) } else { - return unlockVolumeUsingSealedKeyTPM(name, sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) + res, err = unlockVolumeUsingSealedKeyTPM(name, sealedEncryptionKeyFile, sourceDevice, targetDevice, mapperName, opts) } + res.PartDevice = partDevice + return res, err } // UnlockEncryptedVolumeUsingKey unlocks an existing volume using the provided key. @@ -137,13 +139,13 @@ func UnlockEncryptedVolumeUsingKey(disk disks.Disk, name string, key []byte) (Un // looking for the encrypted device to unlock, later on in the boot // process we will look for the decrypted device to ensure it matches // what we expected - partUUID, err := disk.FindMatchingPartitionUUIDWithFsLabel(EncryptedPartitionName(name)) + part, err := disk.FindMatchingPartitionWithFsLabel(EncryptedPartitionName(name)) if err != nil { return unlockRes, err } unlockRes.IsEncrypted = true // we have a device - encdev := filepath.Join("/dev/disk/by-partuuid", partUUID) + encdev := filepath.Join("/dev/disk/by-uuid", part.FilesystemUUID) unlockRes.PartDevice = encdev uuid, err := randutilRandomKernelUUID() diff --git a/secboot/secboot_sb_test.go b/secboot/secboot_sb_test.go index cd977c0b1e8..7f555951d57 100644 --- a/secboot/secboot_sb_test.go +++ b/secboot/secboot_sb_test.go @@ -433,6 +433,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { { FilesystemLabel: "name-enc", PartitionUUID: "enc-dev-partuuid", + FilesystemUUID: "enc-dev-uuid", }, }, } @@ -444,6 +445,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { { FilesystemLabel: "name", PartitionUUID: "unenc-dev-partuuid", + FilesystemUUID: "unenc-dev-uuid", }, }, } @@ -526,7 +528,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { hasEncdev: true, rkErr: errors.New("cannot unlock with recovery key"), rkAllow: true, disk: mockDiskWithEncDev, - err: `cannot unlock encrypted device ".*/enc-dev-partuuid": cannot unlock with recovery key`, + err: `cannot unlock encrypted device "/dev/disk/by-uuid/enc-dev-uuid": cannot unlock with recovery key`, }, { // no tpm, has encrypted device, unlocked using the recovery key tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, @@ -537,14 +539,14 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { // no tpm, has encrypted device, unlocking with recovery key not allowed tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, disk: mockDiskWithEncDev, - err: `cannot activate encrypted device ".*/enc-dev-partuuid": activation error`, + err: `cannot activate encrypted device "/dev/disk/by-uuid/enc-dev-uuid": activation error`, }, { // no tpm, has encrypted device, recovery key unlocking fails rkErr: errors.New("cannot unlock with recovery key"), tpmErr: sb_tpm2.ErrNoTPM2Device, hasEncdev: true, rkAllow: true, disk: mockDiskWithEncDev, - err: `cannot unlock encrypted device ".*/enc-dev-partuuid": cannot unlock with recovery key`, + err: `cannot unlock encrypted device "/dev/disk/by-uuid/enc-dev-uuid": cannot unlock with recovery key`, }, { // no tpm, no encrypted device tpmErr: sb_tpm2.ErrNoTPM2Device, @@ -585,18 +587,22 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { fsLabel += "-enc" } - partuuid := "" + uuid := "" + partUUID := "" if !tc.skipDiskEnsureCheck { for _, p := range tc.disk.Structure { if p.FilesystemLabel == fsLabel { - partuuid = p.PartitionUUID + uuid = p.FilesystemUUID + partUUID = p.PartitionUUID break } } - c.Assert(partuuid, Not(Equals), "", Commentf("didn't find fs label %s in disk", fsLabel)) + c.Assert(uuid, Not(Equals), "", Commentf("didn't find fs label %s in disk", fsLabel)) + c.Assert(partUUID, Not(Equals), "", Commentf("didn't find fs label %s in disk", fsLabel)) } - devicePath := filepath.Join("/dev/disk/by-partuuid", partuuid) + devicePath := filepath.Join("/dev/disk/by-partuuid", partUUID) + devicePathUUID := fmt.Sprintf("/dev/disk/by-uuid/%s", uuid) var keyPath string if tc.oldKeyFormat { @@ -673,7 +679,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncrypted(c *C) { restore = secboot.MockSbActivateVolumeWithKeyData(func(volumeName, sourceDevicePath string, authRequestor sb.AuthRequestor, options *sb.ActivateVolumeOptions, keys ...*sb.KeyData) error { c.Assert(volumeName, Equals, "name-"+randomUUID) - c.Assert(sourceDevicePath, Equals, devicePath) + c.Assert(sourceDevicePath, Equals, devicePathUUID) c.Assert(keys, HasLen, 1) c.Assert(keys[0], Equals, expectedKeyData) @@ -1362,6 +1368,7 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyUUIDError(c *C) { Structure: []disks.Partition{ { FilesystemLabel: "ubuntu-save-enc", + FilesystemUUID: "321-321-321", PartitionUUID: "123-123-123", }, }, @@ -1374,7 +1381,7 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyUUIDError(c *C) { unlockRes, err := secboot.UnlockEncryptedVolumeUsingKey(disk, "ubuntu-save", []byte("fooo")) c.Assert(err, ErrorMatches, "mocked uuid error") c.Check(unlockRes, DeepEquals, secboot.UnlockResult{ - PartDevice: "/dev/disk/by-partuuid/123-123-123", + PartDevice: "/dev/disk/by-uuid/321-321-321", IsEncrypted: true, }) } @@ -1384,6 +1391,7 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyHappy(c *C) { Structure: []disks.Partition{ { FilesystemLabel: "ubuntu-save-enc", + FilesystemUUID: "321-321-321", PartitionUUID: "123-123-123", }, }, @@ -1400,14 +1408,14 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyHappy(c *C) { c.Check(options, DeepEquals, &sb.ActivateVolumeOptions{}) c.Check(key, DeepEquals, []byte("fooo")) c.Check(volumeName, Matches, "ubuntu-save-random-uuid-123-123") - c.Check(sourceDevicePath, Equals, "/dev/disk/by-partuuid/123-123-123") + c.Check(sourceDevicePath, Equals, "/dev/disk/by-uuid/321-321-321") return nil }) defer restore() unlockRes, err := secboot.UnlockEncryptedVolumeUsingKey(disk, "ubuntu-save", []byte("fooo")) c.Assert(err, IsNil) c.Check(unlockRes, DeepEquals, secboot.UnlockResult{ - PartDevice: "/dev/disk/by-partuuid/123-123-123", + PartDevice: "/dev/disk/by-uuid/321-321-321", FsDevice: "/dev/mapper/ubuntu-save-random-uuid-123-123", IsEncrypted: true, UnlockMethod: secboot.UnlockedWithKey, @@ -1419,6 +1427,7 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyErr(c *C) { Structure: []disks.Partition{ { FilesystemLabel: "ubuntu-save-enc", + FilesystemUUID: "321-321-321", PartitionUUID: "123-123-123", }, }, @@ -1440,7 +1449,7 @@ func (s *secbootSuite) TestUnlockEncryptedVolumeUsingKeyErr(c *C) { // we would have at least identified that the device is a decrypted one c.Check(unlockRes, DeepEquals, secboot.UnlockResult{ IsEncrypted: true, - PartDevice: "/dev/disk/by-partuuid/123-123-123", + PartDevice: "/dev/disk/by-uuid/321-321-321", FsDevice: "", }) } @@ -1460,6 +1469,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyErr( Structure: []disks.Partition{ { FilesystemLabel: "name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1516,6 +1526,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1An Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1702,6 +1713,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV2(c Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1765,6 +1777,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV2Ac Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1817,6 +1830,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV2Al Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1885,6 +1899,7 @@ func (s *secbootSuite) checkV2Key(c *C, keyFn string, prefixToDrop, expectedKey, Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -1955,6 +1970,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyV1(c Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, }, @@ -2012,6 +2028,7 @@ func (s *secbootSuite) TestUnlockVolumeUsingSealedKeyIfEncryptedFdeRevealKeyBadJ Structure: []disks.Partition{ { FilesystemLabel: "device-name-enc", + FilesystemUUID: "enc-dev-uuid", PartitionUUID: "enc-dev-partuuid", }, },