aboutsummaryrefslogtreecommitdiff
path: root/filesystem/mountpoint.go
diff options
context:
space:
mode:
authorJoe Richey joerichey@google.com <joerichey@google.com>2017-05-31 17:52:15 -0700
committerJoe Richey joerichey@google.com <joerichey@google.com>2017-06-15 22:32:35 -0700
commit67879f7a69e2040f2266d81ba239324534e24405 (patch)
tree7b2a6725daec02f4868fa8c835ba18acd913a160 /filesystem/mountpoint.go
parentd4160e07cfc1942844160fdb8e6c9525da0bd2c8 (diff)
filesystem: change support detection and bug-fixes
Instead of checking if the filesystem type is correct, we now detect if a filesystem supports encryption by trying to read a policy on its root directory. The error returned tells us if there is support or not. This commit also fixes a bug in the use libblkid. Throughout all of fscrypt, cannonicalizePath() is used before any path comparison or lookup. However, the canonical device path in the blkid cache may differ from our idea of a canonical path. Additional blkid functions are needed to perform the necessary translation. This is noted in the documentation of makeLink(). Finally, this commit makes a few API changes. AllSupporedFilesystems() now returns an error, and a GetProtector() method now replaces the GetLinkedProtector() and GetEitherProtector() methods. A PathSorter has also been added so Mounts can be sorted in a reliable order. Change-Id: I664f46fafd1483ebecb743c061b03d708b3233a4
Diffstat (limited to 'filesystem/mountpoint.go')
-rw-r--r--filesystem/mountpoint.go96
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
}