[op] Replace syscall package usage with golang.org/x/sys/unix in runsc/.

The syscall package has been deprecated in favor of golang.org/x/sys.

Note that syscall is still used in some places because the following don't seem
to have an equivalent in unix package:
- syscall.SysProcIDMap
- syscall.Credential

Updates #214

PiperOrigin-RevId: 361381490
This commit is contained in:
Ayush Ranjan
2021-03-06 22:07:07 -08:00
committed by gVisor bot
parent 0a909ba75a
commit e668288faf
48 changed files with 614 additions and 627 deletions
+6 -6
View File
@@ -17,8 +17,8 @@ package boot
import (
"fmt"
"os"
"syscall"
"golang.org/x/sys/unix"
"google.golang.org/protobuf/proto"
"gvisor.dev/gvisor/pkg/eventchannel"
"gvisor.dev/gvisor/pkg/log"
@@ -93,19 +93,19 @@ func (c *compatEmitter) emitUnimplementedSyscall(us *spb.UnimplementedSyscall) {
tr := c.trackers[sysnr]
if tr == nil {
switch sysnr {
case syscall.SYS_PRCTL:
case unix.SYS_PRCTL:
// args: cmd, ...
tr = newArgsTracker(0)
case syscall.SYS_IOCTL, syscall.SYS_EPOLL_CTL, syscall.SYS_SHMCTL, syscall.SYS_FUTEX, syscall.SYS_FALLOCATE:
case unix.SYS_IOCTL, unix.SYS_EPOLL_CTL, unix.SYS_SHMCTL, unix.SYS_FUTEX, unix.SYS_FALLOCATE:
// args: fd/addr, cmd, ...
tr = newArgsTracker(1)
case syscall.SYS_GETSOCKOPT, syscall.SYS_SETSOCKOPT:
case unix.SYS_GETSOCKOPT, unix.SYS_SETSOCKOPT:
// args: fd, level, name, ...
tr = newArgsTracker(1, 2)
case syscall.SYS_SEMCTL:
case unix.SYS_SEMCTL:
// args: semid, semnum, cmd, ...
tr = newArgsTracker(2)
@@ -131,7 +131,7 @@ func (c *compatEmitter) emitUnimplementedSyscall(us *spb.UnimplementedSyscall) {
}
func (c *compatEmitter) emitUncaughtSignal(msg *ucspb.UncaughtSignal) {
sig := syscall.Signal(msg.SignalNumber)
sig := unix.Signal(msg.SignalNumber)
c.sink.Infof(
"Uncaught signal: %q (%d), PID: %d, TID: %d, fault addr: %#x",
sig, msg.SignalNumber, msg.Pid, msg.Tid, msg.FaultAddr)
+2 -2
View File
@@ -16,8 +16,8 @@ package boot
import (
"fmt"
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/sentry/arch"
rpb "gvisor.dev/gvisor/pkg/sentry/arch/registers_go_proto"
@@ -92,7 +92,7 @@ func syscallNum(regs *rpb.Registers) uint64 {
func newArchArgsTracker(sysnr uint64) syscallTracker {
switch sysnr {
case syscall.SYS_ARCH_PRCTL:
case unix.SYS_ARCH_PRCTL:
// args: cmd, ...
return newArgsTracker(0)
}
+2 -2
View File
@@ -18,9 +18,9 @@ import (
"errors"
"fmt"
"os"
"syscall"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/control/server"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/log"
@@ -366,7 +366,7 @@ func (cm *containerManager) Restore(o *RestoreOpts, _ *struct{}) error {
case 2:
// The device file is donated to the platform.
// Can't take ownership away from os.File. dup them to get a new FD.
fd, err := syscall.Dup(int(o.Files[1].Fd()))
fd, err := unix.Dup(int(o.Files[1].Fd()))
if err != nil {
return fmt.Errorf("failed to dup file: %v", err)
}
File diff suppressed because it is too large Load Diff
+16 -17
View File
@@ -17,30 +17,29 @@
package filter
import (
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/seccomp"
)
func init() {
allowedSyscalls[syscall.SYS_ARCH_PRCTL] = []seccomp.Rule{
allowedSyscalls[unix.SYS_ARCH_PRCTL] = []seccomp.Rule{
// TODO(b/168828518): No longer used in Go 1.16+.
{seccomp.EqualTo(linux.ARCH_SET_FS)},
}
allowedSyscalls[syscall.SYS_CLONE] = []seccomp.Rule{
allowedSyscalls[unix.SYS_CLONE] = []seccomp.Rule{
// parent_tidptr and child_tidptr are always 0 because neither
// CLONE_PARENT_SETTID nor CLONE_CHILD_SETTID are used.
{
seccomp.EqualTo(
syscall.CLONE_VM |
syscall.CLONE_FS |
syscall.CLONE_FILES |
syscall.CLONE_SETTLS |
syscall.CLONE_SIGHAND |
syscall.CLONE_SYSVSEM |
syscall.CLONE_THREAD),
unix.CLONE_VM |
unix.CLONE_FS |
unix.CLONE_FILES |
unix.CLONE_SETTLS |
unix.CLONE_SIGHAND |
unix.CLONE_SYSVSEM |
unix.CLONE_THREAD),
seccomp.MatchAny{}, // newsp
seccomp.EqualTo(0), // parent_tidptr
seccomp.EqualTo(0), // child_tidptr
@@ -49,12 +48,12 @@ func init() {
{
// TODO(b/168828518): No longer used in Go 1.16+ (on amd64).
seccomp.EqualTo(
syscall.CLONE_VM |
syscall.CLONE_FS |
syscall.CLONE_FILES |
syscall.CLONE_SIGHAND |
syscall.CLONE_SYSVSEM |
syscall.CLONE_THREAD),
unix.CLONE_VM |
unix.CLONE_FS |
unix.CLONE_FILES |
unix.CLONE_SIGHAND |
unix.CLONE_SYSVSEM |
unix.CLONE_THREAD),
seccomp.MatchAny{}, // newsp
seccomp.EqualTo(0), // parent_tidptr
seccomp.EqualTo(0), // child_tidptr
+8 -9
View File
@@ -17,21 +17,20 @@
package filter
import (
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
)
func init() {
allowedSyscalls[syscall.SYS_CLONE] = []seccomp.Rule{
allowedSyscalls[unix.SYS_CLONE] = []seccomp.Rule{
{
seccomp.EqualTo(
syscall.CLONE_VM |
syscall.CLONE_FS |
syscall.CLONE_FILES |
syscall.CLONE_SIGHAND |
syscall.CLONE_SYSVSEM |
syscall.CLONE_THREAD),
unix.CLONE_VM |
unix.CLONE_FS |
unix.CLONE_FILES |
unix.CLONE_SIGHAND |
unix.CLONE_SYSVSEM |
unix.CLONE_THREAD),
seccomp.MatchAny{}, // newsp
// These arguments are left uninitialized by the Go
// runtime, so they may be anything (and are unused by
+3 -4
View File
@@ -15,19 +15,18 @@
package filter
import (
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
)
// profileFilters returns extra syscalls made by runtime/pprof package.
func profileFilters() seccomp.SyscallRules {
return seccomp.SyscallRules{
syscall.SYS_OPENAT: []seccomp.Rule{
unix.SYS_OPENAT: []seccomp.Rule{
{
seccomp.MatchAny{},
seccomp.MatchAny{},
seccomp.EqualTo(syscall.O_RDONLY | syscall.O_LARGEFILE | syscall.O_CLOEXEC),
seccomp.EqualTo(unix.O_RDONLY | unix.O_LARGEFILE | unix.O_CLOEXEC),
},
},
}
+5 -6
View File
@@ -17,8 +17,7 @@
package filter
import (
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
)
@@ -26,9 +25,9 @@ import (
func instrumentationFilters() seccomp.SyscallRules {
Report("MSAN is enabled: syscall filters less restrictive!")
return seccomp.SyscallRules{
syscall.SYS_CLONE: {},
syscall.SYS_MMAP: {},
syscall.SYS_SCHED_GETAFFINITY: {},
syscall.SYS_SET_ROBUST_LIST: {},
unix.SYS_CLONE: {},
unix.SYS_MMAP: {},
unix.SYS_SCHED_GETAFFINITY: {},
unix.SYS_SET_ROBUST_LIST: {},
}
}
+12 -13
View File
@@ -17,8 +17,7 @@
package filter
import (
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/seccomp"
)
@@ -26,17 +25,17 @@ import (
func instrumentationFilters() seccomp.SyscallRules {
Report("TSAN is enabled: syscall filters less restrictive!")
return seccomp.SyscallRules{
syscall.SYS_BRK: {},
syscall.SYS_CLOCK_NANOSLEEP: {},
syscall.SYS_CLONE: {},
syscall.SYS_FUTEX: {},
syscall.SYS_MMAP: {},
syscall.SYS_MUNLOCK: {},
syscall.SYS_NANOSLEEP: {},
syscall.SYS_OPEN: {},
syscall.SYS_OPENAT: {},
syscall.SYS_SET_ROBUST_LIST: {},
unix.SYS_BRK: {},
unix.SYS_CLOCK_NANOSLEEP: {},
unix.SYS_CLONE: {},
unix.SYS_FUTEX: {},
unix.SYS_MMAP: {},
unix.SYS_MUNLOCK: {},
unix.SYS_NANOSLEEP: {},
unix.SYS_OPEN: {},
unix.SYS_OPENAT: {},
unix.SYS_SET_ROBUST_LIST: {},
// Used within glibc's malloc.
syscall.SYS_TIME: {},
unix.SYS_TIME: {},
}
}
+6 -6
View File
@@ -20,9 +20,9 @@ import (
"sort"
"strconv"
"strings"
"syscall"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/fd"
@@ -312,11 +312,11 @@ func setupContainerFS(ctx context.Context, conf *config.Config, mntr *containerM
}
func adjustDirentCache(k *kernel.Kernel) error {
var hl syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &hl); err != nil {
var hl unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &hl); err != nil {
return fmt.Errorf("getting RLIMIT_NOFILE: %v", err)
}
if int64(hl.Cur) != syscall.RLIM_INFINITY {
if hl.Cur != unix.RLIM_INFINITY {
newSize := hl.Cur / 2
if newSize < gofer.DefaultDirentCacheSize {
log.Infof("Setting gofer dirent cache size to %d", newSize)
@@ -844,10 +844,10 @@ func (c *containerMounter) mountSubmount(ctx context.Context, conf *config.Confi
// than simply printed to the logs for the 'runsc boot' command.
//
// We check the error message string rather than type because the
// actual error types (syscall.EIO, syscall.EPIPE) are lost by file system
// actual error types (unix.EIO, unix.EPIPE) are lost by file system
// implementation (e.g. p9).
// TODO(gvisor.dev/issue/1765): Remove message when bug is resolved.
if strings.Contains(err.Error(), syscall.EIO.Error()) || strings.Contains(err.Error(), syscall.EPIPE.Error()) {
if strings.Contains(err.Error(), unix.EIO.Error()) || strings.Contains(err.Error(), unix.EPIPE.Error()) {
return fmt.Errorf("%v: %s", err, specutils.FaqErrorMsg("memlock", "you may be encountering a Linux kernel bug"))
}
return err
+4 -4
View File
@@ -16,9 +16,9 @@ package boot
import (
"fmt"
"syscall"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sync"
@@ -104,9 +104,9 @@ func (d *defs) initDefaults() error {
// Read host limits that directly affect the sandbox and adjust the defaults
// based on them.
for _, res := range []int{syscall.RLIMIT_FSIZE, syscall.RLIMIT_NOFILE} {
var hl syscall.Rlimit
if err := syscall.Getrlimit(res, &hl); err != nil {
for _, res := range []int{unix.RLIMIT_FSIZE, unix.RLIMIT_NOFILE} {
var hl unix.Rlimit
if err := unix.Getrlimit(res, &hl); err != nil {
return err
}
+3 -4
View File
@@ -19,7 +19,6 @@ import (
"math/rand"
"os"
"reflect"
"syscall"
"testing"
"time"
@@ -78,7 +77,7 @@ func testSpec() *specs.Spec {
// sandbox side of the connection, and a function that when called will stop the
// gofer.
func startGofer(root string) (int, func(), error) {
fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0)
fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0)
if err != nil {
return 0, nil, err
}
@@ -86,8 +85,8 @@ func startGofer(root string) (int, func(), error) {
socket, err := unet.NewSocket(goferEnd)
if err != nil {
syscall.Close(sandboxEnd)
syscall.Close(goferEnd)
unix.Close(sandboxEnd)
unix.Close(goferEnd)
return 0, nil, fmt.Errorf("error creating server on FD %d: %v", goferEnd, err)
}
at, err := fsgofer.NewAttachPoint(root, fsgofer.Config{ROMount: true})
+2 -2
View File
@@ -19,8 +19,8 @@ import (
"net"
"runtime"
"strings"
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
@@ -195,7 +195,7 @@ func (n *Network) CreateLinksAndRoutes(args *CreateLinksAndRoutesArgs, _ *struct
for j := 0; j < link.NumChannels; j++ {
// Copy the underlying FD.
oldFD := args.FilePayload.Files[fdOffset].Fd()
newFD, err := syscall.Dup(int(oldFD))
newFD, err := unix.Dup(int(oldFD))
if err != nil {
return fmt.Errorf("failed to dup FD %v: %v", oldFD, err)
}
+4 -5
View File
@@ -27,7 +27,6 @@ import (
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
"github.com/cenkalti/backoff"
@@ -111,7 +110,7 @@ func setValue(path, name, data string) error {
err := ioutil.WriteFile(fullpath, []byte(data), 0700)
if err == nil {
return nil
} else if !errors.Is(err, syscall.EINTR) {
} else if !errors.Is(err, unix.EINTR) {
return err
}
}
@@ -161,7 +160,7 @@ func fillFromAncestor(path string) (string, error) {
err := ioutil.WriteFile(path, []byte(val), 0700)
if err == nil {
break
} else if !errors.Is(err, syscall.EINTR) {
} else if !errors.Is(err, unix.EINTR) {
return "", err
}
}
@@ -337,7 +336,7 @@ func (c *Cgroup) Install(res *specs.LinuxResources) error {
c.Own[key] = true
if err := os.MkdirAll(path, 0755); err != nil {
if cfg.optional && errors.Is(err, syscall.EROFS) {
if cfg.optional && errors.Is(err, unix.EROFS) {
log.Infof("Skipping cgroup %q", key)
continue
}
@@ -370,7 +369,7 @@ func (c *Cgroup) Uninstall() error {
defer cancel()
b := backoff.WithContext(backoff.NewConstantBackOff(100*time.Millisecond), ctx)
fn := func() error {
err := syscall.Rmdir(path)
err := unix.Rmdir(path)
if os.IsNotExist(err) {
return nil
}
+1
View File
@@ -18,5 +18,6 @@ go_library(
"//runsc/flag",
"//runsc/specutils",
"@com_github_google_subcommands//:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
+4 -4
View File
@@ -23,10 +23,10 @@ import (
"os"
"os/signal"
"runtime"
"syscall"
"time"
"github.com/google/subcommands"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/platform"
@@ -198,7 +198,7 @@ func Main(version string) {
// want with them. Since Docker and Containerd both eat boot's stderr, we
// dup our stderr to the provided log FD so that panics will appear in the
// logs, rather than just disappear.
if err := syscall.Dup3(fd, int(os.Stderr.Fd()), 0); err != nil {
if err := unix.Dup3(fd, int(os.Stderr.Fd()), 0); err != nil {
cmd.Fatalf("error dup'ing fd %d to stderr: %v", fd, err)
}
} else if conf.AlsoLogToStderr {
@@ -227,11 +227,11 @@ func Main(version string) {
// SIGTERM is sent to all processes if a test exceeds its
// timeout and this case is handled by syscall_test_runner.
log.Warningf("Block the TERM signal. This is only safe in tests!")
signal.Ignore(syscall.SIGTERM)
signal.Ignore(unix.SIGTERM)
}
// Call the subcommand and pass in the configuration.
var ws syscall.WaitStatus
var ws unix.WaitStatus
subcmdCode := subcommands.Execute(context.Background(), conf, &ws)
if subcmdCode == subcommands.ExitSuccess {
log.Infof("Exiting with status: %v", ws)
+2 -3
View File
@@ -19,7 +19,6 @@ import (
"os"
"runtime/debug"
"strings"
"syscall"
"github.com/google/subcommands"
specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -259,8 +258,8 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
ws := l.WaitExit()
log.Infof("application exiting with %+v", ws)
waitStatus := args[1].(*syscall.WaitStatus)
*waitStatus = syscall.WaitStatus(ws.Status())
waitStatus := args[1].(*unix.WaitStatus)
*waitStatus = unix.WaitStatus(ws.Status())
l.Destroy()
return subcommands.ExitSuccess
}
+2 -2
View File
@@ -18,9 +18,9 @@ import (
"context"
"os"
"path/filepath"
"syscall"
"github.com/google/subcommands"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/runsc/config"
"gvisor.dev/gvisor/runsc/container"
@@ -73,7 +73,7 @@ func (c *Checkpoint) Execute(_ context.Context, f *flag.FlagSet, args ...interfa
id := f.Arg(0)
conf := args[0].(*config.Config)
waitStatus := args[1].(*syscall.WaitStatus)
waitStatus := args[1].(*unix.WaitStatus)
cont, err := container.Load(conf.RootDir, container.FullID{ContainerID: id}, container.LoadOpts{})
if err != nil {
+8 -8
View File
@@ -18,8 +18,8 @@ import (
"fmt"
"os"
"path/filepath"
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/runsc/specutils"
)
@@ -49,11 +49,11 @@ func pivotRoot(root string) error {
// will be moved to "/" too. The parent mount of the old_root will be
// new_root, so after umounting the old_root, we will see only
// the new_root in "/".
if err := syscall.PivotRoot(".", "."); err != nil {
if err := unix.PivotRoot(".", "."); err != nil {
return fmt.Errorf("pivot_root failed, make sure that the root mount has a parent: %v", err)
}
if err := syscall.Unmount(".", syscall.MNT_DETACH); err != nil {
if err := unix.Unmount(".", unix.MNT_DETACH); err != nil {
return fmt.Errorf("error umounting the old root file system: %v", err)
}
return nil
@@ -70,26 +70,26 @@ func setUpChroot(pidns bool) error {
// Convert all shared mounts into slave to be sure that nothing will be
// propagated outside of our namespace.
if err := syscall.Mount("", "/", "", syscall.MS_SLAVE|syscall.MS_REC, ""); err != nil {
if err := unix.Mount("", "/", "", unix.MS_SLAVE|unix.MS_REC, ""); err != nil {
return fmt.Errorf("error converting mounts: %v", err)
}
if err := syscall.Mount("runsc-root", chroot, "tmpfs", syscall.MS_NOSUID|syscall.MS_NODEV|syscall.MS_NOEXEC, ""); err != nil {
if err := unix.Mount("runsc-root", chroot, "tmpfs", unix.MS_NOSUID|unix.MS_NODEV|unix.MS_NOEXEC, ""); err != nil {
return fmt.Errorf("error mounting tmpfs in choot: %v", err)
}
if pidns {
flags := uint32(syscall.MS_NOSUID | syscall.MS_NODEV | syscall.MS_NOEXEC | syscall.MS_RDONLY)
flags := uint32(unix.MS_NOSUID | unix.MS_NODEV | unix.MS_NOEXEC | unix.MS_RDONLY)
if err := mountInChroot(chroot, "proc", "/proc", "proc", flags); err != nil {
return fmt.Errorf("error mounting proc in chroot: %v", err)
}
} else {
if err := mountInChroot(chroot, "/proc", "/proc", "bind", syscall.MS_BIND|syscall.MS_RDONLY|syscall.MS_REC); err != nil {
if err := mountInChroot(chroot, "/proc", "/proc", "bind", unix.MS_BIND|unix.MS_RDONLY|unix.MS_REC); err != nil {
return fmt.Errorf("error mounting proc in chroot: %v", err)
}
}
if err := syscall.Mount("", chroot, "", syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_BIND, ""); err != nil {
if err := unix.Mount("", chroot, "", unix.MS_REMOUNT|unix.MS_RDONLY|unix.MS_BIND, ""); err != nil {
return fmt.Errorf("error remounting chroot in read-only: %v", err)
}
+5 -5
View File
@@ -19,9 +19,9 @@ import (
"fmt"
"runtime"
"strconv"
"syscall"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/runsc/specutils"
)
@@ -71,7 +71,7 @@ func setCapsAndCallSelf(args []string, caps *specs.LinuxCapabilities) error {
binPath := specutils.ExePath
log.Infof("Execve %q again, bye!", binPath)
err := syscall.Exec(binPath, args, []string{})
err := unix.Exec(binPath, args, []string{})
return fmt.Errorf("error executing %s: %v", binPath, err)
}
@@ -83,16 +83,16 @@ func callSelfAsNobody(args []string) error {
const nobody = 65534
if _, _, err := syscall.RawSyscall(syscall.SYS_SETGID, uintptr(nobody), 0, 0); err != 0 {
if _, _, err := unix.RawSyscall(unix.SYS_SETGID, uintptr(nobody), 0, 0); err != 0 {
return fmt.Errorf("error setting uid: %v", err)
}
if _, _, err := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(nobody), 0, 0); err != 0 {
if _, _, err := unix.RawSyscall(unix.SYS_SETUID, uintptr(nobody), 0, 0); err != 0 {
return fmt.Errorf("error setting gid: %v", err)
}
binPath := specutils.ExePath
log.Infof("Execve %q again, bye!", binPath)
err := syscall.Exec(binPath, args, []string{})
err := unix.Exec(binPath, args, []string{})
return fmt.Errorf("error executing %s: %v", binPath, err)
}

Some files were not shown because too many files have changed in this diff Show More