lint: update golangci-lint to v2.12.2

Update golangci-lint and adjust code for new gosec diagnostics. Use
root-scoped filesystem operations where appropriate, preserve explicit
user path behavior for SSH keys, and avoid background contexts in
request-scoped cleanup paths.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi committed 2026-05-14 10:13:15 -07:00
1 parent 90b691ab45
commit bd3608ddc9
21 files changed
+122 -65

No files matched your search

+2 -2
View File
@@ -109,7 +109,7 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool
}
defer func() {
if err != nil {
l.Discard()
l.Discard(ctx)
}
}()
@@ -461,7 +461,7 @@ func ensureCompression(ctx context.Context, ref *immutableRef, comp compression.
}
defer func() {
if err != nil {
l.Discard()
l.Discard(ctx)
}
}()
+1 -1
View File
@@ -235,7 +235,7 @@ func (cm *cacheManager) GetByBlob(ctx context.Context, desc ocispecs.Descriptor,
snapshotID := chainID.String()
if link != nil {
snapshotID = link.getSnapshotID()
go link.Release(context.TODO())
go link.Release(context.WithoutCancel(ctx))
}
l, err := cm.LeaseManager.Create(ctx, func(l *leases.Lease) error {
+3 -2
View File
@@ -1519,8 +1519,9 @@ func (cr *cacheRecord) finalize(ctx context.Context) error {
go func() {
cr.cm.mu.Lock()
defer cr.cm.mu.Unlock()
if err := mutable.remove(context.TODO(), true); err != nil {
bklog.G(ctx).Error(err)
cleanupCtx := context.WithoutCancel(ctx)
if err := mutable.remove(cleanupCtx, true); err != nil {
bklog.G(cleanupCtx).Error(err)
}
}()
+6 -2
View File
@@ -13726,8 +13726,12 @@ func testGitBundleRoundTrip(t *testing.T, sb integration.Sandbox) {
localBare := t.TempDir()
err = runInDir(localBare, "git init --bare")
require.NoError(t, err)
bundlePath := filepath.Join(t.TempDir(), "bundle.pack")
require.NoError(t, os.WriteFile(bundlePath, bundleBytes, 0644))
bundleRoot := t.TempDir()
root, err := os.OpenRoot(bundleRoot)
require.NoError(t, err)
require.NoError(t, root.WriteFile("bundle.pack", bundleBytes, 0644))
require.NoError(t, root.Close())
bundlePath := filepath.Join(bundleRoot, "bundle.pack")
err = runInDir(localBare, fmt.Sprintf("git fetch %s +refs/*:refs/*", bundlePath))
require.NoError(t, err)
//nolint:gosec // Test-controlled temp dir and commit SHA are not attacker input.
+18 -5
View File
@@ -15,18 +15,24 @@ import (
func main() {
re := regexp.MustCompile("(?s)<!---GENERATE_START (.*?)-->(.*?)<!---GENERATE_END-->\n")
err := filepath.Walk("./docs", func(path string, stat fs.FileInfo, err error) error {
root, err := os.OpenRoot("./docs")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = fs.WalkDir(root.FS(), ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if stat.IsDir() {
if d.IsDir() {
return nil
}
if filepath.Ext(path) != ".md" {
return nil
}
data, err := os.ReadFile(path)
data, err := root.ReadFile(path)
if err != nil {
return err
}
@@ -61,14 +67,21 @@ func main() {
}
if !bytes.Equal(data, dataNew) {
fmt.Println(path)
if err := os.WriteFile(path, dataNew, stat.Mode()); err != nil {
info, err := d.Info()
if err != nil {
return err
}
fmt.Println(filepath.Join("docs", path))
if err := root.WriteFile(path, dataNew, info.Mode()); err != nil {
return err
}
}
return nil
})
if closeErr := root.Close(); closeErr != nil && err == nil {
err = closeErr
}
if err != nil {
fmt.Println(err)
os.Exit(1)
+1 -1
View File
@@ -646,7 +646,7 @@ func runcProcessHandle(ctx context.Context, killer procKiller) (*procHandle, con
for {
select {
case <-ctx.Done():
killCtx, timeout := context.WithCancelCause(context.Background()) //nolint:govet
killCtx, timeout := context.WithCancelCause(context.WithoutCancel(ctx)) //nolint:govet
killCtx, _ = context.WithTimeoutCause(killCtx, 7*time.Second, errors.WithStack(context.DeadlineExceeded)) //nolint:govet
if err := p.killer.Kill(killCtx); err != nil {
select {
+1 -4
View File
@@ -8,16 +8,13 @@ import (
)
func main() {
var f *os.File
var err error
if len(os.Args) < 2 {
fmt.Println("please supply filename(s)")
os.Exit(1)
}
for _, fn := range os.Args[1:] {
f, err = os.Open(fn)
f, err := os.Open(fn) //nolint:gosec // not using os.Root to support symlinks
if err != nil {
panic(err)
}
+2 -2
View File
@@ -4,7 +4,7 @@ ARG GO_VERSION=1.26
ARG ALPINE_VERSION=3.23
ARG XX_VERSION=1.9.0
ARG PROTOLINT_VERSION=0.50.5
ARG GOLANGCI_LINT_VERSION=v2.8.0
ARG GOLANGCI_LINT_VERSION=v2.12.2
ARG GOLANGCI_FROM_SOURCE=false
ARG GOPLS_VERSION=v0.38.0
# GOPLS_ANALYZERS defines gopls analyzers to be run. disabled by default: deprecated simplifyrange unusedfunc unusedvariable
@@ -34,7 +34,7 @@ RUN apk add --no-cache gcc musl-dev yamllint
ARG GOLANGCI_LINT_VERSION
ARG GOLANGCI_FROM_SOURCE
COPY --link --from=golangci-binary / /usr/bin/
RUN [ "${GOLANGCI_FROM_SOURCE}" = "true" ] && exit 0; wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s ${GOLANGCI_LINT_VERSION}
RUN [ "${GOLANGCI_FROM_SOURCE}" = "true" ] && exit 0; wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/${GOLANGCI_LINT_VERSION}/install.sh | sh -s ${GOLANGCI_LINT_VERSION}
COPY --link --from=protolint-base /usr/local/bin/protolint /usr/local/bin/protolint
COPY --link --from=xx / /
WORKDIR /go/src/github.com/moby/buildkit
@@ -130,7 +130,7 @@ func toDialer(paths []string, raw bool) (func(context.Context) (net.Conn, error)
continue
}
fi, err := os.Stat(p)
fi, err := os.Stat(p) //nolint:gosec // SSH agent paths are explicit user inputs and may intentionally be symlinks.
if err != nil {
return nil, errors.WithStack(err)
}
@@ -142,7 +142,7 @@ func toDialer(paths []string, raw bool) (func(context.Context) (net.Conn, error)
return nil, errors.Errorf("raw mode only supported with socket paths")
}
f, err := os.Open(p)
f, err := os.Open(p) //nolint:gosec // SSH key paths are explicit user inputs and may intentionally be symlinks.
if err != nil {
return nil, errors.Wrapf(err, "failed to open %s", p)
}
+1 -1
View File
@@ -20,7 +20,7 @@ func TestStream(handler Handler) Dialer {
s1, s2 := sockPair()
return func(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) {
go func() {
err := handler(context.TODO(), s1, meta)
err := handler(context.WithoutCancel(ctx), s1, meta)
if err != nil {
bklog.G(ctx).Error(err)
}
+1 -1
View File
@@ -972,7 +972,7 @@ func (e *edge) execOp(ctx context.Context) (any, error) {
for i := range results {
if i != int(index) {
go results[i].Release(context.TODO())
go results[i].Release(context.WithoutCancel(ctx))
}
}
+1 -1
View File
@@ -290,7 +290,7 @@ func (h *Queue) addResource(ctx context.Context, l leases.Lease, desc *controlap
if err != nil {
return err
}
defer lr.Discard()
defer lr.Discard(ctx)
ok, err := h.migrateBlobV2(ctx, desc.Digest, detectSkipLayers)
if err != nil {
return err
+26 -12
View File
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"fmt"
"io"
"io/fs"
"net/url"
"os"
"os/exec"
@@ -1326,8 +1327,14 @@ func (gs *gitSourceHandler) checkout(ctx context.Context, repo *gitRepo, g sessi
}
}
checkoutRoot, err := os.OpenRoot(checkoutDir)
if err != nil {
return nil, errors.Wrap(err, "failed to open git checkout root")
}
defer checkoutRoot.Close()
if compatibilityVersion == compat.CompatibilityVersion013 {
if err := resetCompatibility014FileModes(checkoutDir); err != nil {
if err := resetCompatibility014FileModes(checkoutRoot); err != nil {
return nil, errors.Wrapf(err, "failed to normalize compatibility file modes for %s", urlutil.RedactCredentials(gs.src.Remote))
}
}
@@ -1337,16 +1344,23 @@ func (gs *gitSourceHandler) checkout(ctx context.Context, repo *gitRepo, g sessi
if err != nil {
return nil, errors.Wrapf(err, "failed to get commit time for %s", urlutil.RedactCredentials(gs.src.Remote))
}
if err := resetSnapshotMtimes(checkoutDir, commitTime); err != nil {
if err := resetSnapshotMtimes(checkoutRoot, commitTime); err != nil {
return nil, errors.Wrapf(err, "failed to normalize mtimes for %s", urlutil.RedactCredentials(gs.src.Remote))
}
}
if idmap := mount.IdentityMapping(); idmap != nil {
uid, gid := idmap.RootPair()
err := filepath.WalkDir(gitDir, func(p string, _ os.DirEntry, _ error) error {
return os.Lchown(p, uid, gid)
root, err := os.OpenRoot(gitDir)
if err != nil {
return nil, errors.Wrap(err, "failed to open git checkout root")
}
err = fs.WalkDir(root.FS(), ".", func(p string, _ os.DirEntry, _ error) error {
return root.Lchown(p, uid, gid)
})
if closeErr := root.Close(); closeErr != nil && err == nil {
err = closeErr
}
if err != nil {
return nil, errors.Wrap(err, "failed to remap git checkout")
}
@@ -1388,9 +1402,9 @@ func getCommitTime(ctx context.Context, git *gitutil.GitCLI, ref string) (time.T
// resetSnapshotMtimes walks dir and sets the mtime of every file,
// symlink, and directory to t. Directories are set bottom-up so that
// a parent's mtime is not invalidated by a later child write.
func resetSnapshotMtimes(dir string, t time.Time) error {
func resetSnapshotMtimes(root *os.Root, t time.Time) error {
var dirs []string
err := filepath.WalkDir(dir, func(p string, d os.DirEntry, err error) error {
err := fs.WalkDir(root.FS(), ".", func(p string, d os.DirEntry, err error) error {
if err != nil {
return err
}
@@ -1399,15 +1413,15 @@ func resetSnapshotMtimes(dir string, t time.Time) error {
return nil
}
if d.Type()&os.ModeSymlink != 0 {
return lchtimes(p, t)
return lchtimes(filepath.Join(root.Name(), p), t)
}
return os.Chtimes(p, t, t)
return root.Chtimes(p, t, t)
})
if err != nil {
return err
}
for i := len(dirs) - 1; i >= 0; i-- {
if err := os.Chtimes(dirs[i], t, t); err != nil {
if err := root.Chtimes(dirs[i], t, t); err != nil {
return err
}
}
@@ -1420,8 +1434,8 @@ func resetSnapshotMtimes(dir string, t time.Time) error {
// left untouched: their pre-v0.15 behavior is not covered by the current
// compatibility matrix, and blindly adding write bits to 0o755 would be a
// guess.
func resetCompatibility014FileModes(dir string) error {
return filepath.WalkDir(dir, func(p string, d os.DirEntry, err error) error {
func resetCompatibility014FileModes(root *os.Root) error {
return fs.WalkDir(root.FS(), ".", func(p string, d os.DirEntry, err error) error {
if err != nil {
return err
}
@@ -1437,7 +1451,7 @@ func resetCompatibility014FileModes(dir string) error {
if !mode.IsRegular() || mode&0o111 != 0 {
return nil
}
return os.Chmod(p, mode|0o222)
return root.Chmod(p, mode|0o222)
})
}
+21 -10
View File
@@ -2016,13 +2016,17 @@ func testCheckSignatures(t *testing.T, keepGitDir bool, format string) {
fixturesBase := os.Getenv("BUILDKIT_TEST_SIGN_FIXTURES")
user1GPGPub, err := os.ReadFile(fixturesBase + "/user1.gpg.pub")
fixturesRoot, err := os.OpenRoot(fixturesBase)
require.NoError(t, err)
defer fixturesRoot.Close()
user1GPGPub, err := fixturesRoot.ReadFile("user1.gpg.pub")
require.NoError(t, err)
err = gitsign.VerifySignature(ob, user1GPGPub, nil)
require.NoError(t, err)
user2GPGPub, err := os.ReadFile(fixturesBase + "/user2.gpg.pub")
user2GPGPub, err := fixturesRoot.ReadFile("user2.gpg.pub")
require.NoError(t, err)
err = gitsign.VerifySignature(ob, user2GPGPub, nil)
@@ -2052,10 +2056,10 @@ func testCheckSignatures(t *testing.T, keepGitDir bool, format string) {
require.NoError(t, err)
require.Greater(t, len(ob.Signature), 50)
sshkey1, err := os.ReadFile(fixturesBase + "/user1.ssh.pub")
sshkey1, err := fixturesRoot.ReadFile("user1.ssh.pub")
require.NoError(t, err)
sshkey2, err := os.ReadFile(fixturesBase + "/user2.ssh.pub")
sshkey2, err := fixturesRoot.ReadFile("user2.ssh.pub")
require.NoError(t, err)
err = gitsign.VerifySignature(ob, sshkey2, nil)
@@ -2107,16 +2111,20 @@ func testVerifySignatures(t *testing.T, keepGitDir bool, format string) {
fixturesBase := os.Getenv("BUILDKIT_TEST_SIGN_FIXTURES")
user1GPGPub, err := os.ReadFile(fixturesBase + "/user1.gpg.pub")
fixturesRoot, err := os.OpenRoot(fixturesBase)
require.NoError(t, err)
defer fixturesRoot.Close()
user1GPGPub, err := fixturesRoot.ReadFile("user1.gpg.pub")
require.NoError(t, err)
user2GPGPub, err := os.ReadFile(fixturesBase + "/user2.gpg.pub")
user2GPGPub, err := fixturesRoot.ReadFile("user2.gpg.pub")
require.NoError(t, err)
user1SSHPub, err := os.ReadFile(fixturesBase + "/user1.ssh.pub")
user1SSHPub, err := fixturesRoot.ReadFile("user1.ssh.pub")
require.NoError(t, err)
user2SSHPub, err := os.ReadFile(fixturesBase + "/user2.ssh.pub")
user2SSHPub, err := fixturesRoot.ReadFile("user2.ssh.pub")
require.NoError(t, err)
// a/v1.2.3 commit is signed by user1 gpg
@@ -2672,7 +2680,7 @@ func logProgressStreams(ctx context.Context, t *testing.T) context.Context {
go func() {
defer close(done)
for {
prog, err := pr.Read(context.Background())
prog, err := pr.Read(ctx)
if err != nil {
return
}
@@ -2714,7 +2722,10 @@ func TestResetSnapshotMtimes(t *testing.T) {
require.NoError(t, os.Symlink("file.txt", filepath.Join(dir, "link")))
target := time.Date(2023, 6, 15, 12, 0, 0, 0, time.UTC)
require.NoError(t, resetSnapshotMtimes(dir, target))
root, err := os.OpenRoot(dir)
require.NoError(t, err)
require.NoError(t, resetSnapshotMtimes(root, target))
require.NoError(t, root.Close())
// Regular files should have mtime set
fi, err := os.Lstat(filepath.Join(dir, "file.txt"))
+7 -3
View File
@@ -37,11 +37,15 @@ func EnsureUserAddressDir() error {
xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR")
if xdgRuntimeDir != "" {
dirs := strings.Split(xdgRuntimeDir, ":")
dir := filepath.Join(dirs[0], "buildkit")
if err := os.MkdirAll(dir, 0700); err != nil {
root, err := os.OpenRoot(dirs[0])
if err != nil {
return err
}
return os.Chmod(dir, 0700|os.ModeSticky)
defer root.Close()
if err := root.MkdirAll("buildkit", 0700); err != nil {
return err
}
return root.Chmod("buildkit", 0700|os.ModeSticky)
}
return nil
}
+4 -4
View File
@@ -47,8 +47,8 @@ type LeaseRef struct {
err error
}
func (l *LeaseRef) Discard() error {
return l.lm.Delete(context.Background(), l.l)
func (l *LeaseRef) Discard(ctx context.Context) error {
return l.lm.Delete(context.WithoutCancel(ctx), l.l)
}
func (l *LeaseRef) Adopt(ctx context.Context) error {
@@ -73,10 +73,10 @@ func (l *LeaseRef) Adopt(ctx context.Context) error {
}
}
if len(l.resources) == 0 {
l.Discard()
l.Discard(ctx)
return nil
}
go l.Discard()
go l.Discard(ctx)
return nil
}
+9 -2
View File
@@ -83,8 +83,13 @@ func readFileAt(dirfd int, filename string, buf []byte) (int64, error) {
// https://github.com/containerd/nerdctl/pull/2723
func withDetachedNetNSIfAny(ctx context.Context, fn func(context.Context) error) error {
if stateDir := os.Getenv("ROOTLESSKIT_STATE_DIR"); stateDir != "" {
detachedNetNS := filepath.Join(stateDir, "netns")
if _, err := os.Lstat(detachedNetNS); !errors.Is(err, os.ErrNotExist) {
root, err := os.OpenRoot(stateDir)
if err != nil {
return err
}
defer root.Close()
if _, err := root.Lstat("netns"); !errors.Is(err, os.ErrNotExist) {
detachedNetNS := filepath.Join(stateDir, "netns")
return ns.WithNetNSPath(detachedNetNS, func(_ ns.NetNS) error {
ctx := context.WithValue(ctx, contextKeyDetachedNetNS, detachedNetNS)
bklog.G(ctx).Debugf("Entering RootlessKit's detached netns %q", detachedNetNS)
@@ -92,6 +97,8 @@ func withDetachedNetNSIfAny(ctx context.Context, fn func(context.Context) error)
bklog.G(ctx).WithError(err2).Debugf("Leaving RootlessKit's detached netns %q", detachedNetNS)
return err2
})
} else if err != nil {
return err
}
}
return fn(ctx)
+3 -3
View File
@@ -100,16 +100,16 @@ func (mr *MultiReader) Reader(ctx context.Context) Reader {
}()
if !mr.initialized {
go mr.handle()
go mr.handle(context.WithoutCancel(ctx))
mr.initialized = true
}
return pr
}
func (mr *MultiReader) handle() error {
func (mr *MultiReader) handle(ctx context.Context) error {
for {
p, err := mr.main.Read(context.TODO())
p, err := mr.main.Read(ctx)
if err != nil {
if errors.Is(err, io.EOF) {
mr.mu.Lock()
+4 -4
View File
@@ -31,9 +31,9 @@ func (p *ProviderWithProgress) ReaderAt(ctx context.Context, desc ocispecs.Descr
return nil, err
}
ctx, cancel := context.WithCancelCause(ctx)
progressCtx, cancel := context.WithCancelCause(context.WithoutCancel(ctx))
doneCh := make(chan struct{})
go trackProgress(ctx, desc, p.Manager, doneCh)
go trackProgress(progressCtx, desc, p.Manager, doneCh) //nolint:gosec // Progress tracking is tied to the reader lifetime and canceled by Close.
return readerAtWithCancel{ReaderAt: ra, cancel: cancel, doneCh: doneCh, logger: bklog.G(ctx)}, nil
}
@@ -65,9 +65,9 @@ func (f *FetcherWithProgress) Fetch(ctx context.Context, desc ocispecs.Descripto
return nil, err
}
ctx, cancel := context.WithCancelCause(ctx)
progressCtx, cancel := context.WithCancelCause(context.WithoutCancel(ctx))
doneCh := make(chan struct{})
go trackProgress(ctx, desc, f.Manager, doneCh)
go trackProgress(progressCtx, desc, f.Manager, doneCh) //nolint:gosec // Progress tracking is tied to the reader lifetime and canceled by Close.
return readerWithCancel{ReadCloser: rc, cancel: cancel, doneCh: doneCh, logger: bklog.G(ctx)}, nil
}
+8 -2
View File
@@ -38,7 +38,13 @@ func NewRegistry(dir string) (url string, cl func() error, err error) {
dir = tmpdir
}
if _, err := os.Stat(filepath.Join(dir, "config.yaml")); err != nil {
root, err := os.OpenRoot(dir)
if err != nil {
return "", nil, errors.WithStack(err)
}
defer root.Close()
if _, err := root.Stat("config.yaml"); err != nil {
if !errors.Is(err, os.ErrNotExist) {
return "", nil, err
}
@@ -51,7 +57,7 @@ http:
addr: 127.0.0.1:0
`, filepath.Join(dir, "data"))
if err := os.WriteFile(filepath.Join(dir, "config.yaml"), []byte(template), 0600); err != nil {
if err := root.WriteFile("config.yaml", []byte(template), 0600); err != nil {
return "", nil, err
}
}
+1 -1
View File
@@ -395,7 +395,7 @@ func (w *Worker) PruneCacheMounts(ctx context.Context, ids map[string]bool) erro
}
// if ref is unused try to clean it up right away by releasing it
if mref, err := w.CacheMgr.GetMutable(ctx, md.ID()); err == nil {
go mref.Release(context.TODO())
go mref.Release(context.WithoutCancel(ctx))
}
}
}