diff --git a/pkg/build/linter.go b/pkg/build/linter.go index b97ed0b8e..1e46a7c4a 100644 --- a/pkg/build/linter.go +++ b/pkg/build/linter.go @@ -36,36 +36,34 @@ type linter struct { } var linterMap = map[string]linter{ + "dev": linter{devLinter, "If this package is creating /dev nodes, it should use udev instead; otherwise, remove any files in /dev"}, + "opt": linter{optLinter, "This package should be a -compat package"}, "setuidgid": linter{isSetUidOrGidLinter, "Unset the setuid/setgid bit on the relevant files, or remove this linter"}, + "srv": linter{srvLinter, "This package should be a -compat package"}, "tempdir": linter{tempDirLinter, "Remove any offending files in temporary dirs in the pipeline"}, "usrlocal": linter{usrLocalLinter, "This package should be a -compat package"}, "varempty": linter{varEmptyLinter, "Remove any offending files in /var/empty in the pipeline"}, } +var isDevRegex = regexp.MustCompile("^dev/") +var isOptRegex = regexp.MustCompile("^opt/") +var isSrvRegex = regexp.MustCompile("^srv/") +var isTempDirRegex = regexp.MustCompile("^(var/)?(tmp|run)/") var isUsrLocalRegex = regexp.MustCompile("^usr/local/") var isVarEmptyRegex = regexp.MustCompile("^var/empty/") -var isTempDirRegex = regexp.MustCompile("^(var/)?(tmp|run)/") var isCompatPackage = regexp.MustCompile("-compat$") -func usrLocalLinter(_ LinterContext, path string, _ fs.DirEntry) error { - if isUsrLocalRegex.MatchString(path) { - return fmt.Errorf("/usr/local path found in non-compat package") +func devLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isDevRegex.MatchString(path) { + return fmt.Errorf("Package writes to /dev") } return nil } -func varEmptyLinter(_ LinterContext, path string, _ fs.DirEntry) error { - if isVarEmptyRegex.MatchString(path) { - return fmt.Errorf("Package writes to /var/empty") - } - - return nil -} - -func tempDirLinter(_ LinterContext, path string, _ fs.DirEntry) error { - if isTempDirRegex.MatchString(path) { - return fmt.Errorf("Package writes to a temp dir") +func optLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isOptRegex.MatchString(path) { + return fmt.Errorf("Package writes to /opt") } return nil @@ -87,6 +85,38 @@ func isSetUidOrGidLinter(_ LinterContext, _ string, d fs.DirEntry) error { return nil } +func srvLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isSrvRegex.MatchString(path) { + return fmt.Errorf("Package writes to /srv") + } + + return nil +} + +func tempDirLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isTempDirRegex.MatchString(path) { + return fmt.Errorf("Package writes to a temp dir") + } + + return nil +} + +func usrLocalLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isUsrLocalRegex.MatchString(path) { + return fmt.Errorf("/usr/local path found in non-compat package") + } + + return nil +} + +func varEmptyLinter(_ LinterContext, path string, _ fs.DirEntry) error { + if isVarEmptyRegex.MatchString(path) { + return fmt.Errorf("Package writes to /var/empty") + } + + return nil +} + func lintPackageFs(lctx LinterContext, fsys fs.FS, linters []string) error { // If this is a compat package, do nothing. if isCompatPackage.MatchString(lctx.pkgname) { diff --git a/pkg/build/linter_test.go b/pkg/build/linter_test.go index 77f7572f8..8116f22f2 100644 --- a/pkg/build/linter_test.go +++ b/pkg/build/linter_test.go @@ -37,7 +37,7 @@ func Test_usrLocalLinter(t *testing.T) { Epoch: 0, Checks: config.Checks{ Enabled: []string{"usrlocal"}, - Disabled: []string{"setuidgid", "tempdir", "varempty"}, + Disabled: []string{"dev", "opt", "setuidgid", "srv", "tempdir", "varempty"}, }, }, } @@ -66,7 +66,7 @@ func Test_varEmptyLinter(t *testing.T) { Epoch: 0, Checks: config.Checks{ Enabled: []string{"varempty"}, - Disabled: []string{"setuidgid", "tempdir", "usrlocal"}, + Disabled: []string{"dev", "opt", "setuidgid", "srv", "tempdir", "usrlocal"}, }, }, } @@ -84,6 +84,96 @@ func Test_varEmptyLinter(t *testing.T) { assert.Error(t, lintPackageFs(lctx, fsys, linters)) } +func Test_devLinter(t *testing.T) { + dir, err := os.MkdirTemp("", "melange.XXXXX") + defer os.RemoveAll(dir) + assert.NoError(t, err) + + cfg := config.Configuration{ + Package: config.Package{ + Name: "test", + Version: "4.2.0", + Epoch: 0, + Checks: config.Checks{ + Enabled: []string{"dev"}, + Disabled: []string{"opt", "setuidgid", "srv", "tempdir", "usrlocal", "varempty"}, + }, + }, + } + + pathdir := filepath.Join(dir, "dev") + err = os.MkdirAll(pathdir, 0700) + assert.NoError(t, err) + _, err = os.Create(filepath.Join(pathdir, "test.txt")) + assert.NoError(t, err) + + linters := cfg.Package.Checks.GetLinters() + assert.Equal(t, linters, []string{"dev"}) + fsys := os.DirFS(dir) + lctx := LinterContext{cfg.Package.Name, &cfg, &cfg.Package.Checks} + assert.Error(t, lintPackageFs(lctx, fsys, linters)) +} + +func Test_optLinter(t *testing.T) { + dir, err := os.MkdirTemp("", "melange.XXXXX") + defer os.RemoveAll(dir) + assert.NoError(t, err) + + cfg := config.Configuration{ + Package: config.Package{ + Name: "test", + Version: "4.2.0", + Epoch: 0, + Checks: config.Checks{ + Enabled: []string{"opt"}, + Disabled: []string{"dev", "setuidgid", "srv", "tempdir", "usrlocal", "varempty"}, + }, + }, + } + + pathdir := filepath.Join(dir, "opt") + err = os.MkdirAll(pathdir, 0700) + assert.NoError(t, err) + _, err = os.Create(filepath.Join(pathdir, "test.txt")) + assert.NoError(t, err) + + linters := cfg.Package.Checks.GetLinters() + assert.Equal(t, linters, []string{"opt"}) + fsys := os.DirFS(dir) + lctx := LinterContext{cfg.Package.Name, &cfg, &cfg.Package.Checks} + assert.Error(t, lintPackageFs(lctx, fsys, linters)) +} + +func Test_srvLinter(t *testing.T) { + dir, err := os.MkdirTemp("", "melange.XXXXX") + defer os.RemoveAll(dir) + assert.NoError(t, err) + + cfg := config.Configuration{ + Package: config.Package{ + Name: "test", + Version: "4.2.0", + Epoch: 0, + Checks: config.Checks{ + Enabled: []string{"srv"}, + Disabled: []string{"dev", "opt", "setuidgid", "tempdir", "usrlocal", "varempty"}, + }, + }, + } + + pathdir := filepath.Join(dir, "srv") + err = os.MkdirAll(pathdir, 0700) + assert.NoError(t, err) + _, err = os.Create(filepath.Join(pathdir, "test.txt")) + assert.NoError(t, err) + + linters := cfg.Package.Checks.GetLinters() + assert.Equal(t, linters, []string{"srv"}) + fsys := os.DirFS(dir) + lctx := LinterContext{cfg.Package.Name, &cfg, &cfg.Package.Checks} + assert.Error(t, lintPackageFs(lctx, fsys, linters)) +} + func Test_tempDirLinter(t *testing.T) { dir, err := os.MkdirTemp("", "melange.XXXXX") defer os.RemoveAll(dir) @@ -96,7 +186,7 @@ func Test_tempDirLinter(t *testing.T) { Epoch: 0, Checks: config.Checks{ Enabled: []string{"tempdir"}, - Disabled: []string{"setuidgid", "usrlocal", "varempty"}, + Disabled: []string{"dev", "opt", "setuidgid", "srv", "usrlocal", "varempty"}, }, }, } @@ -157,7 +247,7 @@ func Test_setUidGidLinter(t *testing.T) { Epoch: 0, Checks: config.Checks{ Enabled: []string{"setuidgid"}, - Disabled: []string{"tempdir", "usrlocal", "varempty"}, + Disabled: []string{"dev", "opt", "srv", "tempdir", "usrlocal", "varempty"}, }, }, } diff --git a/pkg/config/config.go b/pkg/config/config.go index a0e3d54c9..554bfd989 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -338,6 +338,9 @@ func (cfg Configuration) Name() string { } var defaultLinters = []string{ + "dev", + "opt", + "srv", "setuidgid", "tempdir", "usrlocal",