Skip to content

Commit

Permalink
archive: disable looking up usernames and groupnames on the host
Browse files Browse the repository at this point in the history
These strings were resolved using the user information on the host
filesystem and were decreasing reproducibility.

For moby/buildkit issue 3688

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
(cherry picked from commit d26587c)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
AkihiroSuda authored and thaJeztah committed Mar 8, 2023
1 parent 0f72de8 commit 063ad2f
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ issues:
max-issues-per-linter: 0
max-same-issues: 0

# Only using / doesn't work due to https://github.com/golangci/golangci-lint/issues/1398.
exclude-rules:
- path: 'archive[\\/]tarheader[\\/]'
# conversion is necessary on Linux, unnecessary on macOS
text: "unnecessary conversion"

linters-settings:
gosec:
# The following issues surfaced when `gosec` linter
Expand Down
4 changes: 3 additions & 1 deletion archive/tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"syscall"
"time"

"github.com/containerd/containerd/archive/tarheader"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/pkg/userns"
"github.com/containerd/continuity/fs"
Expand Down Expand Up @@ -554,7 +555,8 @@ func (cw *ChangeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e
}
}

hdr, err := tar.FileInfoHeader(f, link)
// Use FileInfoHeaderNoLookups to avoid propagating user names and group names from the host
hdr, err := tarheader.FileInfoHeaderNoLookups(f, link)
if err != nil {
return err
}
Expand Down
82 changes: 82 additions & 0 deletions archive/tarheader/tarheader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
Portions from https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive.go#L419-L464
Copyright (C) Docker/Moby authors.
Licensed under the Apache License, Version 2.0
NOTICE: https://github.com/moby/moby/blob/v23.0.1/NOTICE
*/

package tarheader

import (
"archive/tar"
"os"
)

// nosysFileInfo hides the system-dependent info of the wrapped FileInfo to
// prevent tar.FileInfoHeader from introspecting it and potentially calling into
// glibc.
//
// From https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive.go#L419-L434 .
type nosysFileInfo struct {
os.FileInfo
}

func (fi nosysFileInfo) Sys() interface{} {
// A Sys value of type *tar.Header is safe as it is system-independent.
// The tar.FileInfoHeader function copies the fields into the returned
// header without performing any OS lookups.
if sys, ok := fi.FileInfo.Sys().(*tar.Header); ok {
return sys
}
return nil
}

// sysStat, if non-nil, populates hdr from system-dependent fields of fi.
//
// From https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive.go#L436-L437 .
var sysStat func(fi os.FileInfo, hdr *tar.Header) error

// FileInfoHeaderNoLookups creates a partially-populated tar.Header from fi.
//
// Compared to the archive/tar.FileInfoHeader function, this function is safe to
// call from a chrooted process as it does not populate fields which would
// require operating system lookups. It behaves identically to
// tar.FileInfoHeader when fi is a FileInfo value returned from
// tar.Header.FileInfo().
//
// When fi is a FileInfo for a native file, such as returned from os.Stat() and
// os.Lstat(), the returned Header value differs from one returned from
// tar.FileInfoHeader in the following ways. The Uname and Gname fields are not
// set as OS lookups would be required to populate them. The AccessTime and
// ChangeTime fields are not currently set (not yet implemented) although that
// is subject to change. Callers which require the AccessTime or ChangeTime
// fields to be zeroed should explicitly zero them out in the returned Header
// value to avoid any compatibility issues in the future.
//
// From https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive.go#L439-L464 .
func FileInfoHeaderNoLookups(fi os.FileInfo, link string) (*tar.Header, error) {
hdr, err := tar.FileInfoHeader(nosysFileInfo{fi}, link)
if err != nil {
return nil, err
}
if sysStat != nil {
return hdr, sysStat(fi, hdr)
}
return hdr, nil
}
59 changes: 59 additions & 0 deletions archive/tarheader/tarheader_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//go:build !windows

/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
Portions from https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive_unix.go#L52-L70
Copyright (C) Docker/Moby authors.
Licensed under the Apache License, Version 2.0
NOTICE: https://github.com/moby/moby/blob/v23.0.1/NOTICE
*/

package tarheader

import (
"archive/tar"
"os"
"syscall"

"golang.org/x/sys/unix"
)

func init() {
sysStat = statUnix
}

// statUnix populates hdr from system-dependent fields of fi without performing
// any OS lookups.
// From https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive_unix.go#L52-L70
func statUnix(fi os.FileInfo, hdr *tar.Header) error {
s, ok := fi.Sys().(*syscall.Stat_t)
if !ok {
return nil
}

hdr.Uid = int(s.Uid)
hdr.Gid = int(s.Gid)

if s.Mode&unix.S_IFBLK != 0 ||
s.Mode&unix.S_IFCHR != 0 {
hdr.Devmajor = int64(unix.Major(uint64(s.Rdev)))
hdr.Devminor = int64(unix.Minor(uint64(s.Rdev)))
}

return nil
}

0 comments on commit 063ad2f

Please sign in to comment.