aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2022-02-23 12:35:04 -0800
committerEric Biggers <ebiggers@google.com>2022-02-23 12:35:04 -0800
commit6e355131670ad014e45f879475ddf800f0080d41 (patch)
treeb323dd02a668b36a4b07f9f8275d6555acb00dbb /cmd
parent45599bdfad300f1a034c70dd70b4bd180d66f52c (diff)
Make 'fscrypt setup' offer a choice of directory modes
World-writable directories are not appropriate for some systems, so offer a choice of single-user-writable and world-writable modes, with single-user-writable being the default. Add a new documentation section to help users decide which one to use.
Diffstat (limited to 'cmd')
-rw-r--r--cmd/fscrypt/commands.go6
-rw-r--r--cmd/fscrypt/errors.go4
-rw-r--r--cmd/fscrypt/flags.go14
-rw-r--r--cmd/fscrypt/setup.go41
-rw-r--r--cmd/fscrypt/status.go11
5 files changed, 68 insertions, 8 deletions
diff --git a/cmd/fscrypt/commands.go b/cmd/fscrypt/commands.go
index 023c0fa..30aa3a7 100644
--- a/cmd/fscrypt/commands.go
+++ b/cmd/fscrypt/commands.go
@@ -63,7 +63,7 @@ var Setup = cli.Command{
the README). This may require root privileges.`,
mountpointArg, actions.ConfigFileLocation,
shortDisplay(timeTargetFlag)),
- Flags: []cli.Flag{timeTargetFlag, forceFlag},
+ Flags: []cli.Flag{timeTargetFlag, forceFlag, allUsersSetupFlag},
Action: setupAction,
}
@@ -468,7 +468,7 @@ var Lock = cli.Command{
recoverable by an attacker who compromises system memory. To be
fully safe, you must reboot with a power cycle.`,
directoryArg, shortDisplay(dropCachesFlag)),
- Flags: []cli.Flag{dropCachesFlag, userFlag, allUsersFlag},
+ Flags: []cli.Flag{dropCachesFlag, userFlag, allUsersLockFlag},
Action: lockAction,
}
@@ -502,7 +502,7 @@ func lockAction(c *cli.Context) error {
return newExitError(c, ErrDropCachesPerm)
}
- if err = policy.Deprovision(allUsersFlag.Value); err != nil {
+ if err = policy.Deprovision(allUsersLockFlag.Value); err != nil {
switch err {
case keyring.ErrKeyNotPresent:
break
diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go
index bcf5b59..2d76792 100644
--- a/cmd/fscrypt/errors.go
+++ b/cmd/fscrypt/errors.go
@@ -232,6 +232,10 @@ func getErrorSuggestions(err error) string {
}
}
return ""
+ case *filesystem.ErrNoCreatePermission:
+ return `For how to allow users to create fscrypt metadata on a
+ filesystem, refer to
+ https://github.com/google/fscrypt#setting-up-fscrypt-on-a-filesystem`
case *filesystem.ErrNotSetup:
return fmt.Sprintf(`Run "sudo fscrypt setup %s" to use fscrypt
on this filesystem.`, e.Mount.Path)
diff --git a/cmd/fscrypt/flags.go b/cmd/fscrypt/flags.go
index 044b71e..1b41839 100644
--- a/cmd/fscrypt/flags.go
+++ b/cmd/fscrypt/flags.go
@@ -116,7 +116,8 @@ var (
allFlags = []prettyFlag{helpFlag, versionFlag, verboseFlag, quietFlag,
forceFlag, skipUnlockFlag, timeTargetFlag,
sourceFlag, nameFlag, keyFileFlag, protectorFlag,
- unlockWithFlag, policyFlag, allUsersFlag, noRecoveryFlag}
+ unlockWithFlag, policyFlag, allUsersLockFlag, allUsersSetupFlag,
+ noRecoveryFlag}
// universalFlags contains flags that should be on every command
universalFlags = []cli.Flag{verboseFlag, quietFlag, helpFlag}
)
@@ -164,7 +165,7 @@ var (
privileges.`,
Default: true,
}
- allUsersFlag = &boolFlag{
+ allUsersLockFlag = &boolFlag{
Name: "all-users",
Usage: `Lock the directory no matter which user(s) have unlocked
it. Requires root privileges. This flag is only
@@ -172,6 +173,15 @@ var (
different from the one you're locking it as. This flag
is only implemented for v2 encryption policies.`,
}
+ allUsersSetupFlag = &boolFlag{
+ Name: "all-users",
+ Usage: `When setting up a filesystem for fscrypt, allow users
+ other than the calling user (typically root) to create
+ fscrypt policies and protectors on the filesystem. Note
+ that this will create a world-writable directory, which
+ users could use to fill up the entire filesystem. Hence,
+ this option may not be appropriate for some systems.`,
+ }
noRecoveryFlag = &boolFlag{
Name: "no-recovery",
Usage: `Don't generate a recovery passphrase.`,
diff --git a/cmd/fscrypt/setup.go b/cmd/fscrypt/setup.go
index 7b9bebb..1da0d16 100644
--- a/cmd/fscrypt/setup.go
+++ b/cmd/fscrypt/setup.go
@@ -26,6 +26,7 @@ import (
"os"
"github.com/google/fscrypt/actions"
+ "github.com/google/fscrypt/filesystem"
"github.com/google/fscrypt/util"
)
@@ -80,11 +81,47 @@ func setupFilesystem(w io.Writer, path string) error {
if err != nil {
return err
}
+ username := ctx.TargetUser.Username
- if err = ctx.Mount.Setup(); err != nil {
+ err = ctx.Mount.CheckSetup()
+ if err == nil {
+ return &filesystem.ErrAlreadySetup{Mount: ctx.Mount}
+ }
+ if _, ok := err.(*filesystem.ErrNotSetup); !ok {
return err
}
- fmt.Fprintf(w, "Metadata directories created at %q.\n", ctx.Mount.BaseDir())
+ allUsers := allUsersSetupFlag.Value
+ if !allUsers {
+ thisFilesystem := "this filesystem"
+ if ctx.Mount.Path == "/" {
+ thisFilesystem = "the root filesystem"
+ }
+ prompt := fmt.Sprintf(`Allow users other than %s to create
+fscrypt metadata on %s? (See
+https://github.com/google/fscrypt#setting-up-fscrypt-on-a-filesystem)`,
+ username, thisFilesystem)
+ allUsers, err = askQuestion(wrapText(prompt, 0), false)
+ if err != nil {
+ return err
+ }
+ }
+ var setupMode filesystem.SetupMode
+ if allUsers {
+ setupMode = filesystem.WorldWritable
+ } else {
+ setupMode = filesystem.SingleUserWritable
+ }
+ if err = ctx.Mount.Setup(setupMode); err != nil {
+ return err
+ }
+
+ if allUsers {
+ fmt.Fprintf(w, "Metadata directories created at %q, writable by everyone.\n",
+ ctx.Mount.BaseDir())
+ } else {
+ fmt.Fprintf(w, "Metadata directories created at %q, writable by %s only.\n",
+ ctx.Mount.BaseDir(), username)
+ }
return nil
}
diff --git a/cmd/fscrypt/status.go b/cmd/fscrypt/status.go
index d10dfd8..54c6f1f 100644
--- a/cmd/fscrypt/status.go
+++ b/cmd/fscrypt/status.go
@@ -165,9 +165,18 @@ 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.FilesystemType,
+ fmt.Fprintf(w, "%s filesystem %q has %s and %s.\n", ctx.Mount.FilesystemType,
ctx.Mount.Path, pluralize(len(options), "protector"),
pluralize(len(policyDescriptors), "policy"))
+ if setupMode, user, err := ctx.Mount.GetSetupMode(); err == nil {
+ switch setupMode {
+ case filesystem.WorldWritable:
+ fmt.Fprintf(w, "All users can create fscrypt metadata on this filesystem.\n")
+ case filesystem.SingleUserWritable:
+ fmt.Fprintf(w, "Only %s can create fscrypt metadata on this filesystem.\n", user.Username)
+ }
+ }
+ fmt.Fprintf(w, "\n")
if len(options) > 0 {
writeOptions(w, options)