diff options
Diffstat (limited to 'filesystem/mountpoint.go')
| -rw-r--r-- | filesystem/mountpoint.go | 96 |
1 files changed, 54 insertions, 42 deletions
diff --git a/filesystem/mountpoint.go b/filesystem/mountpoint.go index ddcc243..1a4b10f 100644 --- a/filesystem/mountpoint.go +++ b/filesystem/mountpoint.go @@ -33,6 +33,8 @@ const char* read_mode = "r"; // Helper function for freeing strings void string_free(char* str) { free(str); } + +// Helper function to lookup tokens */ import "C" @@ -42,16 +44,11 @@ import ( "path/filepath" "strings" "sync" + + "fscrypt/metadata" ) var ( - // SupportedFilesystems is a map of the filesystems which support - // filesystem-level encryption. - SupportedFilesystems = map[string]bool{ - "ext4": true, - "f2fs": true, - "ubifs": true, - } // These maps hold data about the state of the system's mountpoints. mountsByPath map[string]*Mount mountsByDevice map[string][]*Mount @@ -121,12 +118,7 @@ func getMountInfo() error { // filesystems are listed in mount order. mountsByPath[mnt.Path] = &mnt - // Use libblkid to get the device name - cDeviceName := C.blkid_evaluate_spec(entry.mnt_fsname, &cache) - defer C.string_free(cDeviceName) - - deviceName, err := cannonicalizePath(C.GoString(cDeviceName)) - + deviceName, err := cannonicalizePath(C.GoString(entry.mnt_fsname)) // Only use real valid devices (unlike cgroups, tmpfs, ...) if err == nil && isDevice(deviceName) { mnt.Device = deviceName @@ -138,30 +130,38 @@ func getMountInfo() error { // checkSupport returns an error if the specified mount does not support // filesystem-level encryption. func checkSupport(mount *Mount) error { - if SupportedFilesystems[mount.Filesystem] { + // Getting a policy on a filesystem which supports encryption should + // either return the policy or say there isn't one. Anything else + // indicates a problem with support. + _, err := metadata.GetPolicy(mount.Path) + if err == nil || err == metadata.ErrNotEncrypted { + log.Printf("%s filesystem at %q supports encryption (got %v)", + mount.Filesystem, mount.Path, err) return nil } - log.Printf("filesystem %s does not support filesystem encryption", mount.Filesystem) - return ErrNoSupport + + log.Printf("%s filesystem at %q probably doesn't support encryption (got %v)", + mount.Filesystem, mount.Path, err) + return err } // AllSupportedFilesystems lists all the Mounts which could support filesystem // encryption. This doesn't mean they necessarily do or that they are being used // with fscrypt. -func AllSupportedFilesystems() (mounts []*Mount) { +func AllSupportedFilesystems() ([]*Mount, error) { mountMutex.Lock() defer mountMutex.Unlock() if err := getMountInfo(); err != nil { - log.Print(err) - return + return nil, err } + var supportedMounts []*Mount for _, mount := range mountsByPath { if checkSupport(mount) == nil { - mounts = append(mounts, mount) + supportedMounts = append(supportedMounts, mount) } } - return + return supportedMounts, nil } // UpdateMountInfo updates the filesystem mountpoint maps with the current state @@ -240,28 +240,34 @@ func GetMount(mountpoint string) (*Mount, error) { // filesystem has been updated since the last call to one of the mount // functions, run UpdateMountInfo to see the change. func getMountsFromLink(link string) ([]*Mount, error) { - mountMutex.Lock() - defer mountMutex.Unlock() - if err := getMountInfo(); err != nil { - return nil, err - } - - // Use blkid to get the device + // Use blkid_evaluate_spec to get the device name. cLink := C.CString(link) defer C.string_free(cLink) + cDeviceName := C.blkid_evaluate_spec(cLink, &cache) defer C.string_free(cDeviceName) + deviceName := C.GoString(cDeviceName) + + log.Printf("blkid_evaluate_spec(%q, <cache>) = %q", link, deviceName) - deviceName, err := cannonicalizePath(C.GoString(cDeviceName)) + if deviceName == "" { + return nil, ErrNoLink + } + deviceName, err := cannonicalizePath(deviceName) if err != nil { return nil, err } + mountMutex.Lock() + defer mountMutex.Unlock() + if err := getMountInfo(); err != nil { + return nil, err + } + if mnts, ok := mountsByDevice[deviceName]; ok { return mnts, nil } - log.Printf("link %q does not refer to a device", link) return nil, ErrNoLink } @@ -269,23 +275,29 @@ func getMountsFromLink(link string) ([]*Mount, error) { // value for the Mount's device according to libblkid. An error is returned if // the device/token pair has no value. func makeLink(mnt *Mount, token string) (string, error) { - mountMutex.Lock() - defer mountMutex.Unlock() - if err := getMountInfo(); err != nil { - return "", err - } + // The blkid cache may not always hold the canonical device path. To + // solve this we first use blkid_evaluate_spec to find the right entry + // in the cache. Then that name is used to get the token value. + cDevice := C.CString(mnt.Device) + defer C.string_free(cDevice) + + cDeviceEntry := C.blkid_evaluate_spec(cDevice, &cache) + defer C.string_free(cDeviceEntry) + deviceEntry := C.GoString(cDeviceEntry) + + log.Printf("blkid_evaluate_spec(%q, <cache>) = %q", mnt.Device, deviceEntry) cToken := C.CString(token) defer C.string_free(cToken) - cDevice := C.CString(mnt.Device) - defer C.string_free(cDevice) - cValue := C.blkid_get_tag_value(cache, cToken, cDevice) - if cValue == nil { - log.Printf("filesystem at %q has no %s", mnt.Path, token) - return "", ErrCannotLink - } + cValue := C.blkid_get_tag_value(cache, cToken, cDeviceEntry) defer C.string_free(cValue) + value := C.GoString(cValue) + + log.Printf("blkid_get_tag_value(<cache>, %s, %s) = %s", token, deviceEntry, value) + if value == "" { + return "", ErrCannotLink + } return fmt.Sprintf("%s=%s", token, C.GoString(cValue)), nil } |