From e9919b0bfd00c7d228531ebafa410cbfdafcb2e3 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 9 May 2020 14:52:06 -0700 Subject: actions/config: improve config file related errors ErrBadConfig: Fix backwards wrapping, include the bad config, and make it clear that this is an internal error. ErrBadConfigFile: Fix backwards wrapping, include the config file location, and adjust the suggestion slightly. ErrConfigFileExists: Include the config file location. ErrNoConfigFile: Include the config file location, and adjust the suggestion slightly. --- actions/config.go | 50 +++++++++++++++++++++++++++++++++++++++++++++----- actions/context.go | 12 +++--------- cli-tests/t_setup.out | 10 +++++----- cmd/fscrypt/errors.go | 10 ++++++---- 4 files changed, 59 insertions(+), 23 deletions(-) diff --git a/actions/config.go b/actions/config.go index 2463b95..b848d92 100644 --- a/actions/config.go +++ b/actions/config.go @@ -22,12 +22,12 @@ package actions import ( "bytes" + "fmt" "log" "os" "runtime" "time" - "github.com/pkg/errors" "golang.org/x/sys/unix" "github.com/google/fscrypt/crypto" @@ -40,6 +40,46 @@ import ( // overridden by the user of this package. var ConfigFileLocation = "/etc/fscrypt.conf" +// ErrBadConfig is an internal error that indicates that the config struct is invalid. +type ErrBadConfig struct { + Config *metadata.Config + UnderlyingError error +} + +func (err *ErrBadConfig) Error() string { + return fmt.Sprintf(`internal error: config is invalid: %s + + The invalid config is %s`, err.UnderlyingError, err.Config) +} + +// ErrBadConfigFile indicates that the config file is invalid. +type ErrBadConfigFile struct { + Path string + UnderlyingError error +} + +func (err *ErrBadConfigFile) Error() string { + return fmt.Sprintf("%q is invalid: %s", err.Path, err.UnderlyingError) +} + +// ErrConfigFileExists indicates that the config file already exists. +type ErrConfigFileExists struct { + Path string +} + +func (err *ErrConfigFileExists) Error() string { + return fmt.Sprintf("%q already exists", err.Path) +} + +// ErrNoConfigFile indicates that the config file doesn't exist. +type ErrNoConfigFile struct { + Path string +} + +func (err *ErrNoConfigFile) Error() string { + return fmt.Sprintf("%q doesn't exist", err.Path) +} + const ( // Permissions of the config file (global readable) configPermissions = 0644 @@ -67,7 +107,7 @@ func CreateConfigFile(target time.Duration, policyVersion int64) error { createFlags, configPermissions) switch { case os.IsExist(err): - return ErrConfigFileExists + return &ErrConfigFileExists{ConfigFileLocation} case err != nil: return err } @@ -98,7 +138,7 @@ func getConfig() (*metadata.Config, error) { configFile, err := os.Open(ConfigFileLocation) switch { case os.IsNotExist(err): - return nil, ErrNoConfigFile + return nil, &ErrNoConfigFile{ConfigFileLocation} case err != nil: return nil, err } @@ -107,7 +147,7 @@ func getConfig() (*metadata.Config, error) { log.Printf("Reading config from %q\n", ConfigFileLocation) config, err := metadata.ReadConfig(configFile) if err != nil { - return nil, errors.Wrap(ErrBadConfigFile, err.Error()) + return nil, &ErrBadConfigFile{ConfigFileLocation, err} } // Use system defaults if not specified @@ -133,7 +173,7 @@ func getConfig() (*metadata.Config, error) { } if err := config.CheckValidity(); err != nil { - return nil, errors.Wrap(ErrBadConfigFile, err.Error()) + return nil, &ErrBadConfigFile{ConfigFileLocation, err} } return config, nil diff --git a/actions/context.go b/actions/context.go index 0db0671..26295ec 100644 --- a/actions/context.go +++ b/actions/context.go @@ -40,14 +40,8 @@ import ( "github.com/google/fscrypt/util" ) -// Errors relating to Config files or Config structures. -var ( - ErrNoConfigFile = errors.New("global config file does not exist") - ErrBadConfigFile = errors.New("global config file has invalid data") - ErrConfigFileExists = errors.New("global config file already exists") - ErrBadConfig = errors.New("invalid Config structure provided") - ErrLocked = errors.New("key needs to be unlocked first") -) +// ErrLocked indicates that the key hasn't been unwrapped yet. +var ErrLocked = errors.New("key needs to be unlocked first") // Context contains the necessary global state to perform most of fscrypt's // actions. @@ -126,7 +120,7 @@ func newContextFromUser(targetUser *user.User) (*Context, error) { // which is being used with fscrypt. func (ctx *Context) checkContext() error { if err := ctx.Config.CheckValidity(); err != nil { - return errors.Wrap(ErrBadConfig, err.Error()) + return &ErrBadConfig{ctx.Config, err} } return ctx.Mount.CheckSetup() } diff --git a/cli-tests/t_setup.out b/cli-tests/t_setup.out index e1606ba..7d597bd 100644 --- a/cli-tests/t_setup.out +++ b/cli-tests/t_setup.out @@ -38,12 +38,12 @@ Metadata directories created at "MNT/.fscrypt". with fscrypt # no config file -[ERROR] fscrypt setup: global config file does not exist +[ERROR] fscrypt setup: "FSCRYPT_CONF" doesn't exist -Run "sudo fscrypt setup" to create the file. +Run "sudo fscrypt setup" to create this file. # bad config file -[ERROR] fscrypt setup: invalid character 'b' looking for beginning of value: - global config file has invalid data +[ERROR] fscrypt setup: "FSCRYPT_CONF" is invalid: invalid + character 'b' looking for beginning of value -Run "sudo fscrypt setup" to recreate the file. +Either fix this file manually, or run "sudo fscrypt setup" to recreate it. diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go index 8bda921..e7c025f 100644 --- a/cmd/fscrypt/errors.go +++ b/cmd/fscrypt/errors.go @@ -79,6 +79,12 @@ func getFullName(c *cli.Context) string { // getErrorSuggestions returns a string containing suggestions about how to fix // an error. If no suggestion is necessary or available, return empty string. func getErrorSuggestions(err error) string { + switch err.(type) { + case *actions.ErrBadConfigFile: + return `Either fix this file manually, or run "sudo fscrypt setup" to recreate it.` + case *actions.ErrNoConfigFile: + return `Run "sudo fscrypt setup" to create this file.` + } switch errors.Cause(err) { case filesystem.ErrNotSetup: return fmt.Sprintf(`Run "fscrypt setup %s" to use fscrypt on this filesystem.`, mountpointArg) @@ -117,10 +123,6 @@ func getErrorSuggestions(err error) string { return fmt.Sprintf(`v2 encryption policies are only supported by kernel version 5.4 and later. Either use a newer kernel, or change policy_version to 1 in %s.`, actions.ConfigFileLocation) - case actions.ErrBadConfigFile: - return `Run "sudo fscrypt setup" to recreate the file.` - case actions.ErrNoConfigFile: - return `Run "sudo fscrypt setup" to create the file.` case actions.ErrMissingPolicyMetadata: return `This file or directory has either been encrypted with another tool (such as e4crypt) or the corresponding -- cgit v1.2.3