Skip to content

Commit

Permalink
Merge pull request #154 from ebiggers/bind-mounts
Browse files Browse the repository at this point in the history
Store fscrypt metadata in only one place per filesystem, so that bind
mounts don't get their own metadata directories (which was ambiguous,
as the same file may be accessible via multiple mounts).

Also correctly set the source device for root filesystems mounted via
the kernel command line, and fix creating linked protectors to such
filesystems.
  • Loading branch information
josephlr committed Oct 30, 2019
2 parents a3434e4 + e71c5e4 commit 9b2f1c3
Show file tree
Hide file tree
Showing 7 changed files with 544 additions and 149 deletions.
8 changes: 4 additions & 4 deletions actions/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func NewContextFromPath(path string, target *user.User) (*Context, error) {
}

log.Printf("%s is on %s filesystem %q (%s)", path,
ctx.Mount.Filesystem, ctx.Mount.Path, ctx.Mount.Device)
ctx.Mount.FilesystemType, ctx.Mount.Path, ctx.Mount.Device)
return ctx, nil
}

Expand All @@ -95,7 +95,7 @@ func NewContextFromMountpoint(mountpoint string, target *user.User) (*Context, e
return nil, err
}

log.Printf("found %s filesystem %q (%s)", ctx.Mount.Filesystem,
log.Printf("found %s filesystem %q (%s)", ctx.Mount.FilesystemType,
ctx.Mount.Path, ctx.Mount.Device)
return ctx, nil
}
Expand Down Expand Up @@ -137,9 +137,9 @@ func (ctx *Context) checkContext() error {
func (ctx *Context) getService() string {
// For legacy configurations, we may need non-standard services
if ctx.Config.HasCompatibilityOption(LegacyConfig) {
switch ctx.Mount.Filesystem {
switch ctx.Mount.FilesystemType {
case "ext4", "f2fs":
return ctx.Mount.Filesystem + ":"
return ctx.Mount.FilesystemType + ":"
}
}
return unix.FS_KEY_DESC_PREFIX
Expand Down
9 changes: 5 additions & 4 deletions cmd/fscrypt/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ func writeGlobalStatus(w io.Writer) error {
continue
}

fmt.Fprintf(t, "%s\t%s\t%s\t%s\t%s\n", mount.Path, mount.Device, mount.Filesystem,
supportString, yesNoString(usingFscrypt))
fmt.Fprintf(t, "%s\t%s\t%s\t%s\t%s\n", mount.Path, mount.Device,
mount.FilesystemType, supportString, yesNoString(usingFscrypt))

if supportErr == nil {
supportCount++
Expand Down Expand Up @@ -139,8 +139,9 @@ func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error {
return err
}

fmt.Fprintf(w, "%s filesystem %q has %s and %s\n\n", ctx.Mount.Filesystem, ctx.Mount.Path,
pluralize(len(options), "protector"), pluralize(len(policyDescriptors), "policy"))
fmt.Fprintf(w, "%s filesystem %q has %s and %s\n\n", ctx.Mount.FilesystemType,
ctx.Mount.Path, pluralize(len(options), "protector"),
pluralize(len(policyDescriptors), "policy"))

if len(options) > 0 {
writeOptions(w, options)
Expand Down
45 changes: 23 additions & 22 deletions filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,15 @@ 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"
// 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.
// 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:
Expand All @@ -90,10 +95,12 @@ 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
Device string
DeviceNumber DeviceNumber
BindMnt bool
ReadOnly bool
}

// PathSorter allows mounts to be sorted by Path.
Expand Down Expand Up @@ -123,9 +130,8 @@ 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
Device: %s`, m.Path, m.FilesystemType, m.Device)
}

// BaseDir returns the path to the base fscrypt directory for this filesystem.
Expand Down Expand Up @@ -436,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
Expand Down
Loading

0 comments on commit 9b2f1c3

Please sign in to comment.