From 58eb637ba9bc345ce280f6ea2c9d382617ce07fe Mon Sep 17 00:00:00 2001 From: RebeccaMahany Date: Tue, 16 Jul 2024 16:37:06 -0400 Subject: [PATCH 1/2] Copy sqlite database to temp dir before querying --- ee/katc/sqlite.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/ee/katc/sqlite.go b/ee/katc/sqlite.go index fe8b3407c..e2dc993a6 100644 --- a/ee/katc/sqlite.go +++ b/ee/katc/sqlite.go @@ -4,10 +4,13 @@ import ( "context" "database/sql" "fmt" + "io" "log/slog" + "os" "path/filepath" "strings" + "github.com/kolide/launcher/ee/agent" "github.com/osquery/osquery-go/plugin/table" _ "modernc.org/sqlite" ) @@ -60,7 +63,18 @@ func sourcePatternToGlobbablePattern(sourcePattern string) string { // querySqliteDb queries the database at the given path, returning rows of results func querySqliteDb(ctx context.Context, slogger *slog.Logger, path string, query string) ([]map[string][]byte, error) { - dsn := fmt.Sprintf("file:%s?mode=ro", path) + // If the database is in use, we won't be able to query it. So, copy it to a temporary location first. + tempDbCopyLocation, err := copySqliteDb(path) + if err != nil { + if tempDbCopyLocation != "" { + _ = os.RemoveAll(tempDbCopyLocation) + } + return nil, fmt.Errorf("unable to copy db: %w", err) + } + // The copy was successful -- make sure we clean it up after we're done + defer os.RemoveAll(filepath.Base(tempDbCopyLocation)) + + dsn := fmt.Sprintf("file:%s?mode=ro", tempDbCopyLocation) conn, err := sql.Open("sqlite", dsn) if err != nil { return nil, fmt.Errorf("opening sqlite db: %w", err) @@ -118,3 +132,34 @@ func querySqliteDb(ctx context.Context, slogger *slog.Logger, path string, query return results, nil } + +// copySqliteDb makes a temporary directory and copies the given db into it. +func copySqliteDb(path string) (string, error) { + dbCopyDir, err := agent.MkdirTemp("sqlite-temp") + if err != nil { + return "", fmt.Errorf("making temporary directory: %w", err) + } + + srcFh, err := os.Open(path) + if err != nil { + return "", fmt.Errorf("opening %s: %w", path, err) + } + defer srcFh.Close() + + dbCopyDest := filepath.Join(dbCopyDir, filepath.Base(path)) + destFh, err := os.Create(dbCopyDest) + if err != nil { + return "", fmt.Errorf("opening %s: %w", dbCopyDest, err) + } + + if _, err := io.Copy(destFh, srcFh); err != nil { + _ = destFh.Close() + return "", fmt.Errorf("copying %s to %s: %w", path, dbCopyDest, err) + } + + if err := destFh.Close(); err != nil { + return "", fmt.Errorf("completing write from %s to %s: %w", path, dbCopyDest, err) + } + + return dbCopyDest, nil +} From 9c2b482a29b817f7740a23ddc77acb7d0d836d4d Mon Sep 17 00:00:00 2001 From: RebeccaMahany Date: Tue, 16 Jul 2024 17:04:31 -0400 Subject: [PATCH 2/2] Set immutable instead --- ee/katc/sqlite.go | 47 +---------------------------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/ee/katc/sqlite.go b/ee/katc/sqlite.go index e2dc993a6..467db4928 100644 --- a/ee/katc/sqlite.go +++ b/ee/katc/sqlite.go @@ -4,13 +4,10 @@ import ( "context" "database/sql" "fmt" - "io" "log/slog" - "os" "path/filepath" "strings" - "github.com/kolide/launcher/ee/agent" "github.com/osquery/osquery-go/plugin/table" _ "modernc.org/sqlite" ) @@ -63,18 +60,7 @@ func sourcePatternToGlobbablePattern(sourcePattern string) string { // querySqliteDb queries the database at the given path, returning rows of results func querySqliteDb(ctx context.Context, slogger *slog.Logger, path string, query string) ([]map[string][]byte, error) { - // If the database is in use, we won't be able to query it. So, copy it to a temporary location first. - tempDbCopyLocation, err := copySqliteDb(path) - if err != nil { - if tempDbCopyLocation != "" { - _ = os.RemoveAll(tempDbCopyLocation) - } - return nil, fmt.Errorf("unable to copy db: %w", err) - } - // The copy was successful -- make sure we clean it up after we're done - defer os.RemoveAll(filepath.Base(tempDbCopyLocation)) - - dsn := fmt.Sprintf("file:%s?mode=ro", tempDbCopyLocation) + dsn := fmt.Sprintf("file:%s?mode=ro&immutable=1", path) conn, err := sql.Open("sqlite", dsn) if err != nil { return nil, fmt.Errorf("opening sqlite db: %w", err) @@ -132,34 +118,3 @@ func querySqliteDb(ctx context.Context, slogger *slog.Logger, path string, query return results, nil } - -// copySqliteDb makes a temporary directory and copies the given db into it. -func copySqliteDb(path string) (string, error) { - dbCopyDir, err := agent.MkdirTemp("sqlite-temp") - if err != nil { - return "", fmt.Errorf("making temporary directory: %w", err) - } - - srcFh, err := os.Open(path) - if err != nil { - return "", fmt.Errorf("opening %s: %w", path, err) - } - defer srcFh.Close() - - dbCopyDest := filepath.Join(dbCopyDir, filepath.Base(path)) - destFh, err := os.Create(dbCopyDest) - if err != nil { - return "", fmt.Errorf("opening %s: %w", dbCopyDest, err) - } - - if _, err := io.Copy(destFh, srcFh); err != nil { - _ = destFh.Close() - return "", fmt.Errorf("copying %s to %s: %w", path, dbCopyDest, err) - } - - if err := destFh.Close(); err != nil { - return "", fmt.Errorf("completing write from %s to %s: %w", path, dbCopyDest, err) - } - - return dbCopyDest, nil -}