From 249259376da98d8e10e6876c80ff3905e9756bdc Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 29 Oct 2019 00:04:39 -0700 Subject: filesystem: rename Mount.Filesystem to Mount.FilesystemType Make it clear that this refers to a type of filesystem such as "ext4", rather than to a specific filesystem instance. --- filesystem/filesystem.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'filesystem/filesystem.go') diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index ee332c8..3884e6e 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -64,10 +64,10 @@ var ( ) // Mount contains information for a specific mounted filesystem. -// Path - Absolute path where the directory is mounted -// Filesystem - Name of the mounted filesystem -// Options - List of options used when mounting the filesystem -// Device - Device for filesystem (empty string if we cannot find one) +// Path - Absolute path where the directory is mounted +// FilesystemType - Type of the mounted filesystem, e.g. "ext4" +// Options - List of options used when mounting the filesystem +// Device - Device for filesystem (empty string if we cannot find one) // // In order to use a Mount to store fscrypt metadata, some directories must be // setup first. Specifically, the directories created look like: @@ -90,10 +90,10 @@ var ( // allows login protectors to be created when the root filesystem is read-only, // provided that "/.fscrypt" is a symlink pointing to a writable location. type Mount struct { - Path string - Filesystem string - Options []string - Device string + Path string + FilesystemType string + Options []string + Device string } // PathSorter allows mounts to be sorted by Path. @@ -123,9 +123,9 @@ const ( func (m *Mount) String() string { return fmt.Sprintf(`%s - Filsystem: %s - Options: %v - Device: %s`, m.Path, m.Filesystem, m.Options, m.Device) + FilesystemType: %s + Options: %v + Device: %s`, m.Path, m.FilesystemType, m.Options, m.Device) } // BaseDir returns the path to the base fscrypt directory for this filesystem. -- cgit v1.2.3 From 9d7a4bf93c0d20a7eb2f07ef2ef63834f2cbf6a9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 29 Oct 2019 00:04:39 -0700 Subject: filesystem: remove Mount.Options fscrypt doesn't currently do anything with the mount options, so remove them from the Mount structure for now. --- filesystem/filesystem.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'filesystem/filesystem.go') diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 3884e6e..2b3383c 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -66,7 +66,6 @@ var ( // Mount contains information for a specific mounted filesystem. // Path - Absolute path where the directory is mounted // FilesystemType - Type of the mounted filesystem, e.g. "ext4" -// Options - List of options used when mounting the filesystem // Device - Device for filesystem (empty string if we cannot find one) // // In order to use a Mount to store fscrypt metadata, some directories must be @@ -92,7 +91,6 @@ var ( type Mount struct { Path string FilesystemType string - Options []string Device string } @@ -124,8 +122,7 @@ const ( func (m *Mount) String() string { return fmt.Sprintf(`%s FilesystemType: %s - Options: %v - Device: %s`, m.Path, m.FilesystemType, m.Options, m.Device) + Device: %s`, m.Path, m.FilesystemType, m.Device) } // BaseDir returns the path to the base fscrypt directory for this filesystem. -- cgit v1.2.3 From c7da2443d6ffa51727db09f8ef1df6aea8c7612c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 29 Oct 2019 00:04:39 -0700 Subject: filesystem: get correct device for kernel-mounted rootfs A root filesystem mounted via the kernel command line always has a source of "/dev/root", which isn't a real device node. This makes fscrypt think this filesystem doesn't have a source device, which breaks creating login passphrase-protected directories on other filesystems: fscrypt encrypt: filesystem /: no device for mount "/": system error: cannot create filesystem link This also makes 'fscrypt status' show a blank source device: MOUNTPOINT DEVICE FILESYSTEM ENCRYPTION FSCRYPT / ext4 supported Yes To fix this case, update loadMountInfo() to map the device number to the device name via sysfs rather than use the mount source field. --- filesystem/filesystem.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'filesystem/filesystem.go') diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 2b3383c..c37962a 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -67,6 +67,9 @@ var ( // Path - Absolute path where the directory is mounted // FilesystemType - Type of the mounted filesystem, e.g. "ext4" // Device - Device for filesystem (empty string if we cannot find one) +// DeviceNumber - Device number of the filesystem. This is set even if +// Device isn't, since all filesystems have a device +// number assigned by the kernel, even pseudo-filesystems. // // In order to use a Mount to store fscrypt metadata, some directories must be // setup first. Specifically, the directories created look like: @@ -92,6 +95,7 @@ type Mount struct { Path string FilesystemType string Device string + DeviceNumber DeviceNumber } // PathSorter allows mounts to be sorted by Path. -- cgit v1.2.3 From dbafdbaa9b0767f71affaf15fb8c626f64e27122 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 29 Oct 2019 00:33:54 -0700 Subject: filesystem: handle bind mounts properly Currently, fscrypt treats bind mounts as separate filesystems. This is broken because fscrypt will look for a directory's encryption policy in different places depending on which mount it's accessed through. This forces users to create an fscrypt metadata directory at every bind mount, and to copy fscrypt metadata around between mounts. Fix this by storing fscrypt metadata only at the root of the filesystem. To accomplish this: - Make mountsByDevice store only a single Mount per filesystem, rather than multiple. For this Mount, choose a mount of the full filesystem if available, preferably a read-write mount. If the filesystem has only bind mounts, store a nil entry in mountsByDevice so we can show a proper error message later. - Change FindMount() and GetMount() to look up the Mount by device number rather than by path, so that they don't return different Mounts depending on which path is used. - Change AllFilesystems() to not return bind mounts. - Due to the above changes, the mountsByPath map is no longer needed outside of loadMountInfo(). So make it a local variable there. Resolves https://github.com/google/fscrypt/issues/59 --- filesystem/filesystem.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'filesystem/filesystem.go') diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index c37962a..9bae72b 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -70,6 +70,9 @@ var ( // DeviceNumber - Device number of the filesystem. This is set even if // Device isn't, since all filesystems have a device // number assigned by the kernel, even pseudo-filesystems. +// BindMnt - True if this mount is not for the full filesystem but +// rather is only for a subtree. +// ReadOnly - True if this is a read-only mount // // In order to use a Mount to store fscrypt metadata, some directories must be // setup first. Specifically, the directories created look like: @@ -96,6 +99,8 @@ type Mount struct { FilesystemType string Device string DeviceNumber DeviceNumber + BindMnt bool + ReadOnly bool } // PathSorter allows mounts to be sorted by Path. @@ -437,21 +442,16 @@ func (m *Mount) GetProtector(descriptor string) (*Mount, *metadata.ProtectorData return nil, nil, m.err(err) } - // As the link could refer to multiple filesystems, we check each one - // for valid metadata. - mnts, err := getMountsFromLink(string(link)) + linkedMnt, err := getMountFromLink(string(link)) if err != nil { return nil, nil, m.err(err) } - - for _, mnt := range mnts { - if data, err := mnt.GetRegularProtector(descriptor); err != nil { - log.Print(err) - } else { - return mnt, data, nil - } + data, err := linkedMnt.GetRegularProtector(descriptor) + if err != nil { + log.Print(err) + return nil, nil, m.err(errors.Wrapf(ErrLinkExpired, "protector %s", descriptor)) } - return nil, nil, m.err(errors.Wrapf(ErrLinkExpired, "protector %s", descriptor)) + return linkedMnt, data, nil } // RemoveProtector deletes the protector metadata (or a link to another -- cgit v1.2.3