diff --git a/cmd/root.go b/cmd/root.go index 06ce17ad..dfc6a2cb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -248,26 +248,33 @@ func initializeApplication(cmd *cobra.Command, args []string) error { return nil } +// terminateApplication cleans up the application context and closes the log file +// and removes the local temp directory if it was created func terminateApplication(cmd *cobra.Command, args []string) error { - var appContext common.AppContext + var ctx context.Context if cmd.Parent() == nil { - appContext = cmd.Context().Value(common.AppContext{}).(common.AppContext) + ctx = cmd.Context() } else { - appContext = cmd.Parent().Context().Value(common.AppContext{}).(common.AppContext) + ctx = cmd.Parent().Context() } - - // clean up temp directory - if appContext.LocalTempDir != "" && !flagDebug { - err := os.RemoveAll(appContext.LocalTempDir) - if err != nil { - slog.Error("error cleaning up temp directory", slog.String("tempDir", appContext.LocalTempDir), slog.String("error", err.Error())) + if ctx != nil { + ctxValue := ctx.Value(common.AppContext{}) + if ctxValue != nil { + if appContext, ok := ctxValue.(common.AppContext); ok { + // clean up temp directory if debug flag is not set + if appContext.LocalTempDir != "" && !flagDebug { + err := os.RemoveAll(appContext.LocalTempDir) + if err != nil { + slog.Error("error cleaning up temp directory", slog.String("tempDir", appContext.LocalTempDir), slog.String("error", err.Error())) + } + } + slog.Info("Shutting down", slog.String("app", common.AppName), slog.String("version", gVersion), slog.Int("PID", os.Getpid()), slog.String("arguments", strings.Join(os.Args, " "))) + if gLogFile != nil { + gLogFile.Close() + } + } } } - - slog.Info("Shutting down", slog.String("app", common.AppName), slog.String("version", gVersion), slog.Int("PID", os.Getpid()), slog.String("arguments", strings.Join(os.Args, " "))) - if gLogFile != nil { - gLogFile.Close() - } return nil } diff --git a/internal/common/targets.go b/internal/common/targets.go index 767f62f7..f9a74a0e 100644 --- a/internal/common/targets.go +++ b/internal/common/targets.go @@ -144,8 +144,9 @@ func GetTargets(cmd *cobra.Command, needsElevatedPrivileges bool, failIfCantElev // confirm that the temp directory was not created on a file system mounted with noexec noExec, err := isNoExec(myTarget, myTarget.GetTempDirectory()) if err != nil { - targetErrs[targetIdx] = fmt.Errorf("failed to check if temp directory is noexec") - slog.Error(targetErrs[targetIdx].Error(), slog.String("target", myTarget.GetName()), slog.String("error", err.Error())) + // log the error but don't reject the target just in case our check is wrong + slog.Error("failed to check if temp directory is mounted on 'noexec' file system", slog.String("target", myTarget.GetName()), slog.String("error", err.Error())) + continue } if noExec { targetErrs[targetIdx] = fmt.Errorf("target's temp directory must not be on a file system mounted with the 'noexec' option, override the default with --tempdir") @@ -161,29 +162,48 @@ func isNoExec(t target.Target, tempDir string) (bool, error) { dfCmd := exec.Command("df", "-P", tempDir) dfOutput, _, _, err := t.RunCommand(dfCmd, 0, true) if err != nil { + err = fmt.Errorf("failed to run df command: %w", err) return false, err } mountCmd := exec.Command("mount") mountOutput, _, _, err := t.RunCommand(mountCmd, 0, true) if err != nil { + err = fmt.Errorf("failed to run mount command: %w", err) return false, err } // Parse the output of `df` to extract the device name - lines := strings.Split(string(dfOutput), "\n") + lines := strings.Split(dfOutput, "\n") if len(lines) < 2 { - return false, fmt.Errorf("unexpected output from df command") + return false, fmt.Errorf("unexpected output from df command: %s", dfOutput) } - fields := strings.Fields(lines[1]) // Second line contains the device info - if len(fields) < 1 { - return false, fmt.Errorf("unexpected output format from df command") + dfFields := strings.Fields(lines[1]) // Second line contains the device info + if len(dfFields) < 6 { + return false, fmt.Errorf("unexpected output format from df command: %s", dfOutput) } - device := fields[0] + filesystem := dfFields[0] + mountedOn := dfFields[5] // Search for the device in the mount output and check for "noexec" - for line := range strings.SplitSeq(string(mountOutput), "\n") { - if strings.Contains(line, device) && strings.Contains(line, "noexec") { - return true, nil // Found "noexec" for the device + var found bool + for line := range strings.SplitSeq(mountOutput, "\n") { + mountFields := strings.Fields(line) + if len(mountFields) < 6 { + continue // Skip lines that don't have enough fields + } + device := mountFields[0] + mountPoint := mountFields[2] + mountOptions := strings.Join(mountFields[5:], " ") + if device == filesystem && mountPoint == mountedOn { + found = true + if strings.Contains(mountOptions, "noexec") { + return true, nil // Found "noexec" for the device + } else { + break + } } } + if !found { + return false, fmt.Errorf("device %s not found in mount output", filesystem) + } return false, nil // "noexec" not found } diff --git a/version.txt b/version.txt index 1545d966..87ce4929 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.5.0 +3.5.2