From 3d7cb4293c15173711dc74fdc308f6ccf81d0318 Mon Sep 17 00:00:00 2001 From: Christy Perez Date: Tue, 9 May 2017 17:38:27 -0400 Subject: [PATCH] Move libcontainer to x/sys/unix Since syscall is outdated and broken for some architectures, use x/sys/unix instead. There are still some dependencies on the syscall package that will remain in syscall for the forseeable future: Errno Signal SysProcAttr Additionally: - os still uses syscall, so it needs to be kept for anything returning *os.ProcessState, such as process.Wait. Signed-off-by: Christy Perez --- libcontainer/cgroups/fs/memory.go | 6 +- libcontainer/configs/namespaces_syscall.go | 14 +-- libcontainer/container_linux.go | 22 ++-- libcontainer/devices/devices_linux.go | 8 +- libcontainer/factory_linux.go | 5 +- libcontainer/factory_linux_test.go | 5 +- libcontainer/init_linux.go | 32 +++--- libcontainer/integration/checkpoint_test.go | 5 +- libcontainer/integration/exec_test.go | 29 +++--- libcontainer/integration/execin_test.go | 5 +- libcontainer/integration/template_test.go | 14 +-- libcontainer/keys/keyctl.go | 11 +- libcontainer/notify_linux.go | 5 +- libcontainer/notify_linux_test.go | 19 ++-- libcontainer/nsenter/nsenter_test.go | 11 +- libcontainer/process_linux.go | 18 ++-- libcontainer/rootfs_linux.go | 109 ++++++++++---------- libcontainer/seccomp/seccomp_linux.go | 11 +- libcontainer/specconv/spec_linux.go | 81 ++++++++------- libcontainer/standard_init_linux.go | 16 +-- libcontainer/state_linux.go | 7 +- libcontainer/system/linux.go | 20 ++-- libcontainer/system/setns_linux.go | 40 ------- libcontainer/system/syscall_linux_386.go | 6 +- libcontainer/system/syscall_linux_64.go | 6 +- libcontainer/system/syscall_linux_arm.go | 6 +- libcontainer/system/xattrs_linux.go | 29 +++--- libcontainer/user/lookup.go | 7 +- libcontainer/utils/utils.go | 5 +- libcontainer/utils/utils_test.go | 7 +- libcontainer/utils/utils_unix.go | 9 +- libcontainer/xattr/xattr_linux.go | 6 +- signals.go | 18 ++-- 33 files changed, 292 insertions(+), 300 deletions(-) delete mode 100644 libcontainer/system/setns_linux.go diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go index 0981cfb0..da2cc9f8 100644 --- a/libcontainer/cgroups/fs/memory.go +++ b/libcontainer/cgroups/fs/memory.go @@ -10,10 +10,12 @@ import ( "path/filepath" "strconv" "strings" - "syscall" + "syscall" // only for Errno "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" + + "golang.org/x/sys/unix" ) const ( @@ -93,7 +95,7 @@ func setKernelMemory(path string, kernelMemoryLimit uint64) error { // once tasks have been attached to the cgroup if pathErr, ok := err.(*os.PathError); ok { if errNo, ok := pathErr.Err.(syscall.Errno); ok { - if errNo == syscall.EBUSY { + if errNo == unix.EBUSY { return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit) } } diff --git a/libcontainer/configs/namespaces_syscall.go b/libcontainer/configs/namespaces_syscall.go index fb4b8522..4ce6813d 100644 --- a/libcontainer/configs/namespaces_syscall.go +++ b/libcontainer/configs/namespaces_syscall.go @@ -2,19 +2,19 @@ package configs -import "syscall" +import "golang.org/x/sys/unix" func (n *Namespace) Syscall() int { return namespaceInfo[n.Type] } var namespaceInfo = map[NamespaceType]int{ - NEWNET: syscall.CLONE_NEWNET, - NEWNS: syscall.CLONE_NEWNS, - NEWUSER: syscall.CLONE_NEWUSER, - NEWIPC: syscall.CLONE_NEWIPC, - NEWUTS: syscall.CLONE_NEWUTS, - NEWPID: syscall.CLONE_NEWPID, + NEWNET: unix.CLONE_NEWNET, + NEWNS: unix.CLONE_NEWNS, + NEWUSER: unix.CLONE_NEWUSER, + NEWIPC: unix.CLONE_NEWIPC, + NEWUTS: unix.CLONE_NEWUTS, + NEWPID: unix.CLONE_NEWPID, } // CloneFlags parses the container's Namespaces options to set the correct diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 7089cb5f..79771e41 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -15,7 +15,7 @@ import ( "reflect" "strings" "sync" - "syscall" + "syscall" // only for SysProcAttr and Signal "time" "golang.org/x/sys/unix" @@ -324,12 +324,12 @@ func (c *linuxContainer) createExecFifo() error { if _, err := os.Stat(fifoName); err == nil { return fmt.Errorf("exec fifo %s already exists", fifoName) } - oldMask := syscall.Umask(0000) - if err := syscall.Mkfifo(fifoName, 0622); err != nil { - syscall.Umask(oldMask) + oldMask := unix.Umask(0000) + if err := unix.Mkfifo(fifoName, 0622); err != nil { + unix.Umask(oldMask) return err } - syscall.Umask(oldMask) + unix.Umask(oldMask) if err := os.Chown(fifoName, rootuid, rootgid); err != nil { return err } @@ -923,11 +923,11 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { if err != nil { return err } - err = syscall.Mount(c.config.Rootfs, root, "", syscall.MS_BIND|syscall.MS_REC, "") + err = unix.Mount(c.config.Rootfs, root, "", unix.MS_BIND|unix.MS_REC, "") if err != nil { return err } - defer syscall.Unmount(root, syscall.MNT_DETACH) + defer unix.Unmount(root, unix.MNT_DETACH) t := criurpc.CriuReqType_RESTORE req := &criurpc.CriuReq{ Type: &t, @@ -977,7 +977,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error { c.addCriuRestoreMount(req, m) } - if criuOpts.EmptyNs&syscall.CLONE_NEWNET == 0 { + if criuOpts.EmptyNs&unix.CLONE_NEWNET == 0 { c.restoreNetwork(req, criuOpts) } @@ -1040,7 +1040,7 @@ func (c *linuxContainer) criuApplyCgroups(pid int, req *criurpc.CriuReq) error { } func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuOpts, applyCgroups bool) error { - fds, err := unix.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET|syscall.SOCK_CLOEXEC, 0) + fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_SEQPACKET|unix.SOCK_CLOEXEC, 0) if err != nil { return err } @@ -1386,8 +1386,8 @@ func (c *linuxContainer) runType() (Status, error) { } pid := c.initProcess.pid() // return Running if the init process is alive - if err := syscall.Kill(pid, 0); err != nil { - if err == syscall.ESRCH { + if err := unix.Kill(pid, 0); err != nil { + if err == unix.ESRCH { // It means the process does not exist anymore, could happen when the // process exited just when we call the function, we should not return // error in this case. diff --git a/libcontainer/devices/devices_linux.go b/libcontainer/devices/devices_linux.go index 364dc583..4fd35da8 100644 --- a/libcontainer/devices/devices_linux.go +++ b/libcontainer/devices/devices_linux.go @@ -6,9 +6,11 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" + "syscall" //only for Stat_t "github.com/opencontainers/runc/libcontainer/configs" + + "golang.org/x/sys/unix" ) var ( @@ -36,10 +38,10 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) { case mode&os.ModeDevice == 0: return nil, ErrNotADevice case mode&os.ModeCharDevice != 0: - fileModePermissionBits |= syscall.S_IFCHR + fileModePermissionBits |= unix.S_IFCHR devType = 'c' default: - fileModePermissionBits |= syscall.S_IFBLK + fileModePermissionBits |= unix.S_IFBLK devType = 'b' } stat_t, ok := fileInfo.Sys().(*syscall.Stat_t) diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index a68d471d..72af513f 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -10,7 +10,6 @@ import ( "regexp" "runtime/debug" "strconv" - "syscall" "github.com/docker/docker/pkg/mount" "github.com/opencontainers/runc/libcontainer/cgroups" @@ -20,6 +19,8 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs/validate" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) const ( @@ -92,7 +93,7 @@ func TmpfsRoot(l *LinuxFactory) error { return err } if !mounted { - if err := syscall.Mount("tmpfs", l.Root, "tmpfs", 0, ""); err != nil { + if err := unix.Mount("tmpfs", l.Root, "tmpfs", 0, ""); err != nil { return err } } diff --git a/libcontainer/factory_linux_test.go b/libcontainer/factory_linux_test.go index ea3b5132..055e1bfb 100644 --- a/libcontainer/factory_linux_test.go +++ b/libcontainer/factory_linux_test.go @@ -7,12 +7,13 @@ import ( "os" "path/filepath" "reflect" - "syscall" "testing" "github.com/docker/docker/pkg/mount" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) func newTestRoot() (string, error) { @@ -99,7 +100,7 @@ func TestFactoryNewTmpfs(t *testing.T) { if !found { t.Fatalf("Factory Root is not listed in mounts list") } - defer syscall.Unmount(root, syscall.MNT_DETACH) + defer unix.Unmount(root, unix.MNT_DETACH) } func TestFactoryLoadNotExists(t *testing.T) { diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 99cc02cb..65bee0be 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -9,7 +9,7 @@ import ( "net" "os" "strings" - "syscall" + "syscall" // only for Errno "unsafe" "github.com/Sirupsen/logrus" @@ -19,6 +19,8 @@ import ( "github.com/opencontainers/runc/libcontainer/user" "github.com/opencontainers/runc/libcontainer/utils" "github.com/vishvananda/netlink" + + "golang.org/x/sys/unix" ) type initType string @@ -84,7 +86,7 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket *os.File, stateDi return &linuxStandardInit{ pipe: pipe, consoleSocket: consoleSocket, - parentPid: syscall.Getppid(), + parentPid: unix.Getppid(), config: config, stateDirFD: stateDirFD, }, nil @@ -146,7 +148,7 @@ func finalizeNamespace(config *initConfig) error { return err } if config.Cwd != "" { - if err := syscall.Chdir(config.Cwd); err != nil { + if err := unix.Chdir(config.Cwd); err != nil { return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err) } } @@ -287,7 +289,7 @@ func setupUser(config *initConfig) error { // set the group). if !config.Rootless { suppGroups := append(execUser.Sgids, addGroups...) - if err := syscall.Setgroups(suppGroups); err != nil { + if err := unix.Setgroups(suppGroups); err != nil { return err } } @@ -313,8 +315,8 @@ func setupUser(config *initConfig) error { // The ownership needs to match because it is created outside of the container and needs to be // localized. func fixStdioPermissions(config *initConfig, u *user.ExecUser) error { - var null syscall.Stat_t - if err := syscall.Stat("/dev/null", &null); err != nil { + var null unix.Stat_t + if err := unix.Stat("/dev/null", &null); err != nil { return err } for _, fd := range []uintptr{ @@ -322,8 +324,8 @@ func fixStdioPermissions(config *initConfig, u *user.ExecUser) error { os.Stderr.Fd(), os.Stdout.Fd(), } { - var s syscall.Stat_t - if err := syscall.Fstat(int(fd), &s); err != nil { + var s unix.Stat_t + if err := unix.Fstat(int(fd), &s); err != nil { return err } @@ -346,7 +348,7 @@ func fixStdioPermissions(config *initConfig, u *user.ExecUser) error { // that users expect to be able to actually use their console. Without // this code, you couldn't effectively run as a non-root user inside a // container and also have a console set up. - if err := syscall.Fchown(int(fd), u.Uid, int(s.Gid)); err != nil { + if err := unix.Fchown(int(fd), u.Uid, int(s.Gid)); err != nil { return err } } @@ -401,7 +403,7 @@ func setupRoute(config *configs.Config) error { func setupRlimits(limits []configs.Rlimit, pid int) error { for _, rlimit := range limits { - if err := system.Prlimit(pid, rlimit.Type, syscall.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}); err != nil { + if err := system.Prlimit(pid, rlimit.Type, unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}); err != nil { return fmt.Errorf("error setting rlimit type %v: %v", rlimit.Type, err) } } @@ -424,7 +426,7 @@ type siginfo struct { // Its based off blockUntilWaitable in src/os/wait_waitid.go func isWaitable(pid int) (bool, error) { si := &siginfo{} - _, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(pid), uintptr(unsafe.Pointer(si)), syscall.WEXITED|syscall.WNOWAIT|syscall.WNOHANG, 0, 0) + _, _, e := unix.Syscall6(unix.SYS_WAITID, _P_PID, uintptr(pid), uintptr(unsafe.Pointer(si)), unix.WEXITED|unix.WNOWAIT|unix.WNOHANG, 0, 0) if e != 0 { return false, os.NewSyscallError("waitid", e) } @@ -432,15 +434,15 @@ func isWaitable(pid int) (bool, error) { return si.si_pid != 0, nil } -// isNoChildren returns true if err represents a syscall.ECHILD false otherwise +// isNoChildren returns true if err represents a unix.ECHILD (formerly syscall.ECHILD) false otherwise func isNoChildren(err error) bool { switch err := err.(type) { case syscall.Errno: - if err == syscall.ECHILD { + if err == unix.ECHILD { return true } case *os.SyscallError: - if err.Err == syscall.ECHILD { + if err.Err == unix.ECHILD { return true } } @@ -478,7 +480,7 @@ func signalAllProcesses(m cgroups.Manager, s os.Signal) error { } for _, p := range procs { - if s != syscall.SIGKILL { + if s != unix.SIGKILL { if ok, err := isWaitable(p.Pid); err != nil { if !isNoChildren(err) { logrus.Warn("signalAllProcesses: ", p.Pid, err) diff --git a/libcontainer/integration/checkpoint_test.go b/libcontainer/integration/checkpoint_test.go index d252cd40..a8c786c1 100644 --- a/libcontainer/integration/checkpoint_test.go +++ b/libcontainer/integration/checkpoint_test.go @@ -8,11 +8,12 @@ import ( "os/exec" "path/filepath" "strings" - "syscall" "testing" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/configs" + + "golang.org/x/sys/unix" ) func showFile(t *testing.T, fname string) error { @@ -75,7 +76,7 @@ func testCheckpoint(t *testing.T, userns bool) { config.Mounts = append(config.Mounts, &configs.Mount{ Destination: "/sys/fs/cgroup", Device: "cgroup", - Flags: defaultMountFlags | syscall.MS_RDONLY, + Flags: defaultMountFlags | unix.MS_RDONLY, }) if userns { diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index f3dd72a3..49db94ac 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -11,12 +11,13 @@ import ( "reflect" "strconv" "strings" - "syscall" "testing" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" + + "golang.org/x/sys/unix" ) func TestExecPS(t *testing.T) { @@ -188,7 +189,7 @@ func testRlimit(t *testing.T, userns bool) { // ensure limit is lower than what the config requests to test that in a user namespace // the Setrlimit call happens early enough that we still have permissions to raise the limit. - ok(t, syscall.Setrlimit(syscall.RLIMIT_NOFILE, &syscall.Rlimit{ + ok(t, unix.Setrlimit(unix.RLIMIT_NOFILE, &unix.Rlimit{ Max: 1024, Cur: 1024, })) @@ -874,7 +875,7 @@ func TestMountCmds(t *testing.T) { Source: tmpDir, Destination: "/tmp", Device: "bind", - Flags: syscall.MS_BIND | syscall.MS_REC, + Flags: unix.MS_BIND | unix.MS_REC, PremountCmds: []configs.Command{ {Path: "touch", Args: []string{filepath.Join(tmpDir, "hello")}}, {Path: "touch", Args: []string{filepath.Join(tmpDir, "world")}}, @@ -969,7 +970,7 @@ func TestMountCgroupRO(t *testing.T) { config.Mounts = append(config.Mounts, &configs.Mount{ Destination: "/sys/fs/cgroup", Device: "cgroup", - Flags: defaultMountFlags | syscall.MS_RDONLY, + Flags: defaultMountFlags | unix.MS_RDONLY, }) buffers, exitCode, err := runContainer(config, "", "mount") @@ -1244,7 +1245,7 @@ func TestSTDIOPermissions(t *testing.T) { } func unmountOp(path string) error { - if err := syscall.Unmount(path, syscall.MNT_DETACH); err != nil { + if err := unix.Unmount(path, unix.MNT_DETACH); err != nil { return err } return nil @@ -1269,7 +1270,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) { defer remove(rootfs) config := newTemplateConfig(rootfs) - config.RootPropagation = syscall.MS_SLAVE | syscall.MS_REC + config.RootPropagation = unix.MS_SLAVE | unix.MS_REC // Bind mount a volume dir1host, err := ioutil.TempDir("", "mnt1host") @@ -1278,9 +1279,9 @@ func TestRootfsPropagationSlaveMount(t *testing.T) { // Make this dir a "shared" mount point. This will make sure a // slave relationship can be established in container. - err = syscall.Mount(dir1host, dir1host, "bind", syscall.MS_BIND|syscall.MS_REC, "") + err = unix.Mount(dir1host, dir1host, "bind", unix.MS_BIND|unix.MS_REC, "") ok(t, err) - err = syscall.Mount("", dir1host, "", syscall.MS_SHARED|syscall.MS_REC, "") + err = unix.Mount("", dir1host, "", unix.MS_SHARED|unix.MS_REC, "") ok(t, err) defer unmountOp(dir1host) @@ -1288,7 +1289,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) { Source: dir1host, Destination: dir1cont, Device: "bind", - Flags: syscall.MS_BIND | syscall.MS_REC}) + Flags: unix.MS_BIND | unix.MS_REC}) // TODO: systemd specific processing f := factory @@ -1318,7 +1319,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) { ok(t, err) defer os.RemoveAll(dir2host) - err = syscall.Mount(dir2host, dir2host, "bind", syscall.MS_BIND, "") + err = unix.Mount(dir2host, dir2host, "bind", unix.MS_BIND, "") defer unmountOp(dir2host) ok(t, err) @@ -1386,7 +1387,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) { ok(t, err) defer remove(rootfs) config := newTemplateConfig(rootfs) - config.RootPropagation = syscall.MS_PRIVATE + config.RootPropagation = unix.MS_PRIVATE // Bind mount a volume dir1host, err := ioutil.TempDir("", "mnt1host") @@ -1395,9 +1396,9 @@ func TestRootfsPropagationSharedMount(t *testing.T) { // Make this dir a "shared" mount point. This will make sure a // shared relationship can be established in container. - err = syscall.Mount(dir1host, dir1host, "bind", syscall.MS_BIND|syscall.MS_REC, "") + err = unix.Mount(dir1host, dir1host, "bind", unix.MS_BIND|unix.MS_REC, "") ok(t, err) - err = syscall.Mount("", dir1host, "", syscall.MS_SHARED|syscall.MS_REC, "") + err = unix.Mount("", dir1host, "", unix.MS_SHARED|unix.MS_REC, "") ok(t, err) defer unmountOp(dir1host) @@ -1405,7 +1406,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) { Source: dir1host, Destination: dir1cont, Device: "bind", - Flags: syscall.MS_BIND | syscall.MS_REC}) + Flags: unix.MS_BIND | unix.MS_REC}) // TODO: systemd specific processing f := factory diff --git a/libcontainer/integration/execin_test.go b/libcontainer/integration/execin_test.go index 019757f6..2922eaad 100644 --- a/libcontainer/integration/execin_test.go +++ b/libcontainer/integration/execin_test.go @@ -7,13 +7,14 @@ import ( "os" "strconv" "strings" - "syscall" "testing" "time" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) func TestExecIn(t *testing.T) { @@ -122,7 +123,7 @@ func testExecInRlimit(t *testing.T, userns bool) { Stderr: buffers.Stderr, Rlimits: []configs.Rlimit{ // increase process rlimit higher than container rlimit to test per-process limit - {Type: syscall.RLIMIT_NOFILE, Hard: 1026, Soft: 1026}, + {Type: unix.RLIMIT_NOFILE, Hard: 1026, Soft: 1026}, }, } err = container.Run(ps) diff --git a/libcontainer/integration/template_test.go b/libcontainer/integration/template_test.go index 3f1dd3fc..5f7cab53 100644 --- a/libcontainer/integration/template_test.go +++ b/libcontainer/integration/template_test.go @@ -1,9 +1,9 @@ package integration import ( - "syscall" - "github.com/opencontainers/runc/libcontainer/configs" + + "golang.org/x/sys/unix" ) var standardEnvironment = []string{ @@ -13,7 +13,7 @@ var standardEnvironment = []string{ "TERM=xterm", } -const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV +const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV // newTemplateConfig returns a base template for running a container // @@ -140,14 +140,14 @@ func newTemplateConfig(rootfs string) *configs.Config { Source: "tmpfs", Destination: "/dev", Device: "tmpfs", - Flags: syscall.MS_NOSUID | syscall.MS_STRICTATIME, + Flags: unix.MS_NOSUID | unix.MS_STRICTATIME, Data: "mode=755", }, { Source: "devpts", Destination: "/dev/pts", Device: "devpts", - Flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, + Flags: unix.MS_NOSUID | unix.MS_NOEXEC, Data: "newinstance,ptmxmode=0666,mode=0620,gid=5", }, { @@ -170,7 +170,7 @@ func newTemplateConfig(rootfs string) *configs.Config { Source: "sysfs", Destination: "/sys", Device: "sysfs", - Flags: defaultMountFlags | syscall.MS_RDONLY, + Flags: defaultMountFlags | unix.MS_RDONLY, }, }, Networks: []*configs.Network{ @@ -182,7 +182,7 @@ func newTemplateConfig(rootfs string) *configs.Config { }, Rlimits: []configs.Rlimit{ { - Type: syscall.RLIMIT_NOFILE, + Type: unix.RLIMIT_NOFILE, Hard: uint64(1025), Soft: uint64(1025), }, diff --git a/libcontainer/keys/keyctl.go b/libcontainer/keys/keyctl.go index 8c90e56a..7cf8055f 100644 --- a/libcontainer/keys/keyctl.go +++ b/libcontainer/keys/keyctl.go @@ -6,8 +6,9 @@ import ( "fmt" "strconv" "strings" - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) const KEYCTL_JOIN_SESSION_KEYRING = 1 @@ -21,13 +22,13 @@ func JoinSessionKeyring(name string) (KeySerial, error) { var err error if len(name) > 0 { - _name, err = syscall.BytePtrFromString(name) + _name, err = unix.BytePtrFromString(name) if err != nil { return KeySerial(0), err } } - sessKeyId, _, errn := syscall.Syscall(syscall.SYS_KEYCTL, KEYCTL_JOIN_SESSION_KEYRING, uintptr(unsafe.Pointer(_name)), 0) + sessKeyId, _, errn := unix.Syscall(unix.SYS_KEYCTL, KEYCTL_JOIN_SESSION_KEYRING, uintptr(unsafe.Pointer(_name)), 0) if errn != 0 { return 0, fmt.Errorf("could not create session key: %v", errn) } @@ -41,7 +42,7 @@ func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error { dest := make([]byte, 1024) destBytes := unsafe.Pointer(&dest[0]) - if _, _, err := syscall.Syscall6(syscall.SYS_KEYCTL, uintptr(KEYCTL_DESCRIBE), uintptr(ringId), uintptr(destBytes), uintptr(len(dest)), 0, 0); err != 0 { + if _, _, err := unix.Syscall6(unix.SYS_KEYCTL, uintptr(KEYCTL_DESCRIBE), uintptr(ringId), uintptr(destBytes), uintptr(len(dest)), 0, 0); err != 0 { return err } @@ -58,7 +59,7 @@ func ModKeyringPerm(ringId KeySerial, mask, setbits uint32) error { perm := (uint32(perm64) & mask) | setbits - if _, _, err := syscall.Syscall(syscall.SYS_KEYCTL, uintptr(KEYCTL_SETPERM), uintptr(ringId), uintptr(perm)); err != 0 { + if _, _, err := unix.Syscall(unix.SYS_KEYCTL, uintptr(KEYCTL_SETPERM), uintptr(ringId), uintptr(perm)); err != 0 { return err } diff --git a/libcontainer/notify_linux.go b/libcontainer/notify_linux.go index 839a50c5..6da315d3 100644 --- a/libcontainer/notify_linux.go +++ b/libcontainer/notify_linux.go @@ -7,7 +7,8 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" + + "golang.org/x/sys/unix" ) const oomCgroupName = "memory" @@ -25,7 +26,7 @@ func registerMemoryEvent(cgDir string, evName string, arg string) (<-chan struct if err != nil { return nil, err } - fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0) + fd, _, syserr := unix.RawSyscall(unix.SYS_EVENTFD2, 0, unix.FD_CLOEXEC, 0) if syserr != 0 { evFile.Close() return nil, syserr diff --git a/libcontainer/notify_linux_test.go b/libcontainer/notify_linux_test.go index 9aa4f3b3..5e9f6a78 100644 --- a/libcontainer/notify_linux_test.go +++ b/libcontainer/notify_linux_test.go @@ -8,9 +8,10 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" "testing" "time" + + "golang.org/x/sys/unix" ) type notifyFunc func(paths map[string]string) (<-chan struct{}, error) @@ -53,11 +54,11 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ } // re-open the eventfd - efd, err := syscall.Dup(eventFd) + efd, err := unix.Dup(eventFd) if err != nil { t.Fatal("unable to reopen eventfd:", err) } - defer syscall.Close(efd) + defer unix.Close(efd) if err != nil { t.Fatal("unable to dup event fd:", err) @@ -66,7 +67,7 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ buf := make([]byte, 8) binary.LittleEndian.PutUint64(buf, 1) - if _, err := syscall.Write(efd, buf); err != nil { + if _, err := unix.Write(efd, buf); err != nil { t.Fatal("unable to write to eventfd:", err) } @@ -81,7 +82,7 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ if err := os.RemoveAll(memoryPath); err != nil { t.Fatal(err) } - if _, err := syscall.Write(efd, buf); err != nil { + if _, err := unix.Write(efd, buf); err != nil { t.Fatal("unable to write to eventfd:", err) } @@ -94,12 +95,12 @@ func testMemoryNotification(t *testing.T, evName string, notify notifyFunc, targ case <-time.After(100 * time.Millisecond): } - if _, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(evFd), syscall.F_GETFD, 0); err != syscall.EBADF { - t.Error("expected event control to be closed") + if _, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(evFd), unix.F_GETFD, 0); err != unix.EBADF { + t.Errorf("expected event control to be closed, but received error %s", err.Error()) } - if _, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(eventFd), syscall.F_GETFD, 0); err != syscall.EBADF { - t.Error("expected event fd to be closed") + if _, _, err := unix.Syscall(unix.SYS_FCNTL, uintptr(eventFd), unix.F_GETFD, 0); err != unix.EBADF { + t.Errorf("expected event fd to be closed, but received error %s", err.Error()) } } diff --git a/libcontainer/nsenter/nsenter_test.go b/libcontainer/nsenter/nsenter_test.go index 98b026f7..53215553 100644 --- a/libcontainer/nsenter/nsenter_test.go +++ b/libcontainer/nsenter/nsenter_test.go @@ -9,11 +9,12 @@ import ( "os" "os/exec" "strings" - "syscall" "testing" "github.com/opencontainers/runc/libcontainer" "github.com/vishvananda/netlink/nl" + + "golang.org/x/sys/unix" ) type pid struct { @@ -47,7 +48,7 @@ func TestNsenterValidPaths(t *testing.T) { r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0) r.AddData(&libcontainer.Int32msg{ Type: libcontainer.CloneFlagsAttr, - Value: uint32(syscall.CLONE_NEWNET), + Value: uint32(unix.CLONE_NEWNET), }) r.AddData(&libcontainer.Bytemsg{ Type: libcontainer.NsPathsAttr, @@ -103,7 +104,7 @@ func TestNsenterInvalidPaths(t *testing.T) { r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0) r.AddData(&libcontainer.Int32msg{ Type: libcontainer.CloneFlagsAttr, - Value: uint32(syscall.CLONE_NEWNET), + Value: uint32(unix.CLONE_NEWNET), }) r.AddData(&libcontainer.Bytemsg{ Type: libcontainer.NsPathsAttr, @@ -143,7 +144,7 @@ func TestNsenterIncorrectPathType(t *testing.T) { r := nl.NewNetlinkRequest(int(libcontainer.InitMsg), 0) r.AddData(&libcontainer.Int32msg{ Type: libcontainer.CloneFlagsAttr, - Value: uint32(syscall.CLONE_NEWNET), + Value: uint32(unix.CLONE_NEWNET), }) r.AddData(&libcontainer.Bytemsg{ Type: libcontainer.NsPathsAttr, @@ -166,7 +167,7 @@ func init() { } func newPipe() (parent *os.File, child *os.File, err error) { - fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) + fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0) if err != nil { return nil, nil, err } diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index bfe99551..0fdc3376 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -11,12 +11,14 @@ import ( "os/exec" "path/filepath" "strconv" - "syscall" + "syscall" // only for Signal "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) type parentProcess interface { @@ -62,7 +64,7 @@ func (p *setnsProcess) signal(sig os.Signal) error { if !ok { return errors.New("os: unsupported signal type") } - return syscall.Kill(p.pid(), s) + return unix.Kill(p.pid(), s) } func (p *setnsProcess) start() (err error) { @@ -108,7 +110,7 @@ func (p *setnsProcess) start() (err error) { } }) - if err := syscall.Shutdown(int(p.parentPipe.Fd()), syscall.SHUT_WR); err != nil { + if err := unix.Shutdown(int(p.parentPipe.Fd()), unix.SHUT_WR); err != nil { return newSystemErrorWithCause(err, "calling shutdown on init pipe") } // Must be done after Shutdown so the child will exit and we can wait for it. @@ -341,7 +343,7 @@ func (p *initProcess) start() error { if p.config.Config.Namespaces.Contains(configs.NEWNS) && !sentResume { return newSystemError(fmt.Errorf("could not synchronise after executing prestart hooks with container process")) } - if err := syscall.Shutdown(int(p.parentPipe.Fd()), syscall.SHUT_WR); err != nil { + if err := unix.Shutdown(int(p.parentPipe.Fd()), unix.SHUT_WR); err != nil { return newSystemErrorWithCause(err, "shutting down init pipe") } @@ -360,7 +362,7 @@ func (p *initProcess) wait() (*os.ProcessState, error) { } // we should kill all processes in cgroup when init is died if we use host PID namespace if p.sharePidns { - signalAllProcesses(p.manager, syscall.SIGKILL) + signalAllProcesses(p.manager, unix.SIGKILL) } return p.cmd.ProcessState, nil } @@ -409,7 +411,7 @@ func (p *initProcess) signal(sig os.Signal) error { if !ok { return errors.New("os: unsupported signal type") } - return syscall.Kill(p.pid(), s) + return unix.Kill(p.pid(), s) } func (p *initProcess) setExternalDescriptors(newFds []string) { @@ -450,7 +452,7 @@ func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) { defer func() { if err != nil { for _, fd := range fds { - syscall.Close(int(fd)) + unix.Close(int(fd)) } } }() @@ -475,7 +477,7 @@ func (p *Process) InitializeIO(rootuid, rootgid int) (i *IO, err error) { p.Stderr, i.Stderr = w, r // change ownership of the pipes incase we are in a user namespace for _, fd := range fds { - if err := syscall.Fchown(int(fd), rootuid, rootgid); err != nil { + if err := unix.Fchown(int(fd), rootuid, rootgid); err != nil { return nil, err } } diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 0ec5864f..e2e734a8 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -11,7 +11,6 @@ import ( "path" "path/filepath" "strings" - "syscall" "time" "github.com/docker/docker/pkg/mount" @@ -22,9 +21,11 @@ import ( "github.com/opencontainers/runc/libcontainer/system" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/selinux/go-selinux/label" + + "golang.org/x/sys/unix" ) -const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV +const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV // needsSetupDev returns true if /dev needs to be set up. func needsSetupDev(config *configs.Config) bool { @@ -91,7 +92,7 @@ func prepareRootfs(pipe io.ReadWriter, config *configs.Config) (err error) { // container. It's just cleaner to do this here (at the expense of the // operation not being perfectly split). - if err := syscall.Chdir(config.Rootfs); err != nil { + if err := unix.Chdir(config.Rootfs); err != nil { return newSystemErrorWithCausef(err, "changing dir to %q", config.Rootfs) } @@ -119,7 +120,7 @@ func finalizeRootfs(config *configs.Config) (err error) { // remount dev as ro if specified for _, m := range config.Mounts { if libcontainerUtils.CleanPath(m.Destination) == "/dev" { - if m.Flags&syscall.MS_RDONLY == syscall.MS_RDONLY { + if m.Flags&unix.MS_RDONLY == unix.MS_RDONLY { if err := remountReadonly(m); err != nil { return newSystemErrorWithCausef(err, "remounting %q as readonly", m.Destination) } @@ -135,7 +136,7 @@ func finalizeRootfs(config *configs.Config) (err error) { } } - syscall.Umask(0022) + unix.Umask(0022) return nil } @@ -199,14 +200,14 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { if copyUp { if err := fileutils.CopyDirectory(dest, tmpDir); err != nil { errMsg := fmt.Errorf("tmpcopyup: failed to copy %s to %s: %v", dest, tmpDir, err) - if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil { + if err1 := unix.Unmount(tmpDir, unix.MNT_DETACH); err1 != nil { return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg) } return errMsg } - if err := syscall.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil { + if err := unix.Mount(tmpDir, dest, "", unix.MS_MOVE, ""); err != nil { errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err) - if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil { + if err1 := unix.Unmount(tmpDir, unix.MNT_DETACH); err1 != nil { return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg) } return errMsg @@ -245,7 +246,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { } // bind mount won't change mount options, we need remount to make mount options effective. // first check that we have non-default options required before attempting a remount - if m.Flags&^(syscall.MS_REC|syscall.MS_REMOUNT|syscall.MS_BIND) != 0 { + if m.Flags&^(unix.MS_REC|unix.MS_REMOUNT|unix.MS_BIND) != 0 { // only remount if unique mount options are set if err := remount(m, rootfs); err != nil { return err @@ -299,13 +300,13 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { } } } - if m.Flags&syscall.MS_RDONLY != 0 { + if m.Flags&unix.MS_RDONLY != 0 { // remount cgroup root as readonly mcgrouproot := &configs.Mount{ Source: m.Destination, Device: "bind", Destination: m.Destination, - Flags: defaultMountFlags | syscall.MS_RDONLY | syscall.MS_BIND, + Flags: defaultMountFlags | unix.MS_RDONLY | unix.MS_BIND, } if err := remount(mcgrouproot, rootfs); err != nil { return err @@ -359,7 +360,7 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) { Device: "bind", Source: filepath.Join(mm.Mountpoint, relDir), Destination: filepath.Join(m.Destination, filepath.Base(mm.Mountpoint)), - Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags, + Flags: unix.MS_BIND | unix.MS_REC | m.Flags, PropagationFlags: m.PropagationFlags, }) } @@ -435,22 +436,22 @@ func setupDevSymlinks(rootfs string) error { // needs to be called after we chroot/pivot into the container's rootfs so that any // symlinks are resolved locally. func reOpenDevNull() error { - var stat, devNullStat syscall.Stat_t + var stat, devNullStat unix.Stat_t file, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err != nil { return fmt.Errorf("Failed to open /dev/null - %s", err) } defer file.Close() - if err := syscall.Fstat(int(file.Fd()), &devNullStat); err != nil { + if err := unix.Fstat(int(file.Fd()), &devNullStat); err != nil { return err } for fd := 0; fd < 3; fd++ { - if err := syscall.Fstat(fd, &stat); err != nil { + if err := unix.Fstat(fd, &stat); err != nil { return err } if stat.Rdev == devNullStat.Rdev { // Close and re-open the fd. - if err := syscall.Dup3(int(file.Fd()), fd, 0); err != nil { + if err := unix.Dup3(int(file.Fd()), fd, 0); err != nil { return err } } @@ -461,16 +462,16 @@ func reOpenDevNull() error { // Create the device nodes in the container. func createDevices(config *configs.Config) error { useBindMount := system.RunningInUserNS() || config.Namespaces.Contains(configs.NEWUSER) - oldMask := syscall.Umask(0000) + oldMask := unix.Umask(0000) for _, node := range config.Devices { // containers running in a user namespace are not allowed to mknod // devices so we can just bind mount it from the host. if err := createDeviceNode(config.Rootfs, node, useBindMount); err != nil { - syscall.Umask(oldMask) + unix.Umask(oldMask) return err } } - syscall.Umask(oldMask) + unix.Umask(oldMask) return nil } @@ -482,7 +483,7 @@ func bindMountDeviceNode(dest string, node *configs.Device) error { if f != nil { f.Close() } - return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "") + return unix.Mount(node.Path, dest, "bind", unix.MS_BIND, "") } // Creates the device node in the rootfs of the container. @@ -510,18 +511,18 @@ func mknodDevice(dest string, node *configs.Device) error { fileMode := node.FileMode switch node.Type { case 'c', 'u': - fileMode |= syscall.S_IFCHR + fileMode |= unix.S_IFCHR case 'b': - fileMode |= syscall.S_IFBLK + fileMode |= unix.S_IFBLK case 'p': - fileMode |= syscall.S_IFIFO + fileMode |= unix.S_IFIFO default: return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path) } - if err := syscall.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil { + if err := unix.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil { return err } - return syscall.Chown(dest, int(node.Uid), int(node.Gid)) + return unix.Chown(dest, int(node.Uid), int(node.Gid)) } func getMountInfo(mountinfo []*mount.Info, dir string) *mount.Info { @@ -588,18 +589,18 @@ func rootfsParentMountPrivate(rootfs string) error { // shared. Secondly when we bind mount rootfs it will propagate to // parent namespace and we don't want that to happen. if sharedMount { - return syscall.Mount("", parentMount, "", syscall.MS_PRIVATE, "") + return unix.Mount("", parentMount, "", unix.MS_PRIVATE, "") } return nil } func prepareRoot(config *configs.Config) error { - flag := syscall.MS_SLAVE | syscall.MS_REC + flag := unix.MS_SLAVE | unix.MS_REC if config.RootPropagation != 0 { flag = config.RootPropagation } - if err := syscall.Mount("", "/", "", uintptr(flag), ""); err != nil { + if err := unix.Mount("", "/", "", uintptr(flag), ""); err != nil { return err } @@ -610,11 +611,11 @@ func prepareRoot(config *configs.Config) error { return err } - return syscall.Mount(config.Rootfs, config.Rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, "") + return unix.Mount(config.Rootfs, config.Rootfs, "bind", unix.MS_BIND|unix.MS_REC, "") } func setReadonly() error { - return syscall.Mount("/", "/", "bind", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "") + return unix.Mount("/", "/", "bind", unix.MS_BIND|unix.MS_REMOUNT|unix.MS_RDONLY|unix.MS_REC, "") } func setupPtmx(config *configs.Config) error { @@ -637,24 +638,24 @@ func pivotRoot(rootfs string) error { // with pivot_root this allows us to pivot without creating directories in // the rootfs. Shout-outs to the LXC developers for giving us this idea. - oldroot, err := syscall.Open("/", syscall.O_DIRECTORY|syscall.O_RDONLY, 0) + oldroot, err := unix.Open("/", unix.O_DIRECTORY|unix.O_RDONLY, 0) if err != nil { return err } - defer syscall.Close(oldroot) + defer unix.Close(oldroot) - newroot, err := syscall.Open(rootfs, syscall.O_DIRECTORY|syscall.O_RDONLY, 0) + newroot, err := unix.Open(rootfs, unix.O_DIRECTORY|unix.O_RDONLY, 0) if err != nil { return err } - defer syscall.Close(newroot) + defer unix.Close(newroot) // Change to the new root so that the pivot_root actually acts on it. - if err := syscall.Fchdir(newroot); err != nil { + if err := unix.Fchdir(newroot); err != nil { return err } - if err := syscall.PivotRoot(".", "."); err != nil { + if err := unix.PivotRoot(".", "."); err != nil { return fmt.Errorf("pivot_root %s", err) } @@ -663,35 +664,35 @@ func pivotRoot(rootfs string) error { // really any guarantee from the kernel what /proc/self/cwd will be after a // pivot_root(2). - if err := syscall.Fchdir(oldroot); err != nil { + if err := unix.Fchdir(oldroot); err != nil { return err } // Make oldroot rprivate to make sure our unmounts don't propagate to the // host (and thus bork the machine). - if err := syscall.Mount("", ".", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil { + if err := unix.Mount("", ".", "", unix.MS_PRIVATE|unix.MS_REC, ""); err != nil { return err } // Preform the unmount. MNT_DETACH allows us to unmount /proc/self/cwd. - if err := syscall.Unmount(".", syscall.MNT_DETACH); err != nil { + if err := unix.Unmount(".", unix.MNT_DETACH); err != nil { return err } // Switch back to our shiny new root. - if err := syscall.Chdir("/"); err != nil { + if err := unix.Chdir("/"); err != nil { return fmt.Errorf("chdir / %s", err) } return nil } func msMoveRoot(rootfs string) error { - if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil { + if err := unix.Mount(rootfs, "/", "", unix.MS_MOVE, ""); err != nil { return err } - if err := syscall.Chroot("."); err != nil { + if err := unix.Chroot("."); err != nil { return err } - return syscall.Chdir("/") + return unix.Chdir("/") } // createIfNotExists creates a file or a directory only if it does not already exist. @@ -716,13 +717,13 @@ func createIfNotExists(path string, isDir bool) error { // readonlyPath will make a path read only. func readonlyPath(path string) error { - if err := syscall.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { + if err := unix.Mount(path, path, "", unix.MS_BIND|unix.MS_REC, ""); err != nil { if os.IsNotExist(err) { return nil } return err } - return syscall.Mount(path, path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY|syscall.MS_REC, "") + return unix.Mount(path, path, "", unix.MS_BIND|unix.MS_REMOUNT|unix.MS_RDONLY|unix.MS_REC, "") } // remountReadonly will remount an existing mount point and ensure that it is read-only. @@ -732,9 +733,9 @@ func remountReadonly(m *configs.Mount) error { flags = m.Flags ) for i := 0; i < 5; i++ { - if err := syscall.Mount("", dest, "", uintptr(flags|syscall.MS_REMOUNT|syscall.MS_RDONLY), ""); err != nil { + if err := unix.Mount("", dest, "", uintptr(flags|unix.MS_REMOUNT|unix.MS_RDONLY), ""); err != nil { switch err { - case syscall.EBUSY: + case unix.EBUSY: time.Sleep(100 * time.Millisecond) continue default: @@ -752,9 +753,9 @@ func remountReadonly(m *configs.Mount) error { // For files, maskPath bind mounts /dev/null over the top of the specified path. // For directories, maskPath mounts read-only tmpfs over the top of the specified path. func maskPath(path string) error { - if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { - if err == syscall.ENOTDIR { - return syscall.Mount("tmpfs", path, "tmpfs", syscall.MS_RDONLY, "") + if err := unix.Mount("/dev/null", path, "", unix.MS_BIND, ""); err != nil && !os.IsNotExist(err) { + if err == unix.ENOTDIR { + return unix.Mount("tmpfs", path, "tmpfs", unix.MS_RDONLY, "") } return err } @@ -775,7 +776,7 @@ func remount(m *configs.Mount, rootfs string) error { if !strings.HasPrefix(dest, rootfs) { dest = filepath.Join(rootfs, dest) } - if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil { + if err := unix.Mount(m.Source, dest, m.Device, uintptr(m.Flags|unix.MS_REMOUNT), ""); err != nil { return err } return nil @@ -790,7 +791,7 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { flags = m.Flags ) if libcontainerUtils.CleanPath(dest) == "/dev" { - flags &= ^syscall.MS_RDONLY + flags &= ^unix.MS_RDONLY } copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP @@ -798,12 +799,12 @@ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { dest = filepath.Join(rootfs, dest) } - if err := syscall.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil { + if err := unix.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil { return err } for _, pflag := range m.PropagationFlags { - if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil { + if err := unix.Mount("", dest, "", uintptr(pflag), ""); err != nil { return err } } diff --git a/libcontainer/seccomp/seccomp_linux.go b/libcontainer/seccomp/seccomp_linux.go index 518d2c38..135c1d71 100644 --- a/libcontainer/seccomp/seccomp_linux.go +++ b/libcontainer/seccomp/seccomp_linux.go @@ -7,18 +7,19 @@ import ( "fmt" "os" "strings" - "syscall" "github.com/opencontainers/runc/libcontainer/configs" libseccomp "github.com/seccomp/libseccomp-golang" + + "golang.org/x/sys/unix" ) var ( actAllow = libseccomp.ActAllow actTrap = libseccomp.ActTrap actKill = libseccomp.ActKill - actTrace = libseccomp.ActTrace.SetReturnCode(int16(syscall.EPERM)) - actErrno = libseccomp.ActErrno.SetReturnCode(int16(syscall.EPERM)) + actTrace = libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM)) + actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM)) // SeccompModeFilter refers to the syscall argument SECCOMP_MODE_FILTER. SeccompModeFilter = uintptr(2) @@ -84,9 +85,9 @@ func IsEnabled() bool { s, err := parseStatusFile("/proc/self/status") if err != nil { // Check if Seccomp is supported, via CONFIG_SECCOMP. - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_SECCOMP, 0, 0); err != syscall.EINVAL { + if _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_GET_SECCOMP, 0, 0); err != unix.EINVAL { // Make sure the kernel has CONFIG_SECCOMP_FILTER. - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_SECCOMP, SeccompModeFilter, 0); err != syscall.EINVAL { + if _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_SET_SECCOMP, SeccompModeFilter, 0); err != unix.EINVAL { return true } } diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index 1575ae03..41af6997 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -9,13 +9,14 @@ import ( "os" "path/filepath" "strings" - "syscall" "time" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/seccomp" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" "github.com/opencontainers/runtime-spec/specs-go" + + "golang.org/x/sys/unix" ) const wildcard = -1 @@ -30,13 +31,13 @@ var namespaceMapping = map[specs.LinuxNamespaceType]configs.NamespaceType{ } var mountPropagationMapping = map[string]int{ - "rprivate": syscall.MS_PRIVATE | syscall.MS_REC, - "private": syscall.MS_PRIVATE, - "rslave": syscall.MS_SLAVE | syscall.MS_REC, - "slave": syscall.MS_SLAVE, - "rshared": syscall.MS_SHARED | syscall.MS_REC, - "shared": syscall.MS_SHARED, - "": syscall.MS_PRIVATE | syscall.MS_REC, + "rprivate": unix.MS_PRIVATE | unix.MS_REC, + "private": unix.MS_PRIVATE, + "rslave": unix.MS_SLAVE | unix.MS_REC, + "slave": unix.MS_SLAVE, + "rshared": unix.MS_SHARED | unix.MS_REC, + "shared": unix.MS_SHARED, + "": unix.MS_PRIVATE | unix.MS_REC, } var allowedDevices = []*configs.Device{ @@ -638,41 +639,41 @@ func parseMountOptions(options []string) (int, []int, string, int) { clear bool flag int }{ - "async": {true, syscall.MS_SYNCHRONOUS}, - "atime": {true, syscall.MS_NOATIME}, - "bind": {false, syscall.MS_BIND}, + "async": {true, unix.MS_SYNCHRONOUS}, + "atime": {true, unix.MS_NOATIME}, + "bind": {false, unix.MS_BIND}, "defaults": {false, 0}, - "dev": {true, syscall.MS_NODEV}, - "diratime": {true, syscall.MS_NODIRATIME}, - "dirsync": {false, syscall.MS_DIRSYNC}, - "exec": {true, syscall.MS_NOEXEC}, - "mand": {false, syscall.MS_MANDLOCK}, - "noatime": {false, syscall.MS_NOATIME}, - "nodev": {false, syscall.MS_NODEV}, - "nodiratime": {false, syscall.MS_NODIRATIME}, - "noexec": {false, syscall.MS_NOEXEC}, - "nomand": {true, syscall.MS_MANDLOCK}, - "norelatime": {true, syscall.MS_RELATIME}, - "nostrictatime": {true, syscall.MS_STRICTATIME}, - "nosuid": {false, syscall.MS_NOSUID}, - "rbind": {false, syscall.MS_BIND | syscall.MS_REC}, - "relatime": {false, syscall.MS_RELATIME}, - "remount": {false, syscall.MS_REMOUNT}, - "ro": {false, syscall.MS_RDONLY}, - "rw": {true, syscall.MS_RDONLY}, - "strictatime": {false, syscall.MS_STRICTATIME}, - "suid": {true, syscall.MS_NOSUID}, - "sync": {false, syscall.MS_SYNCHRONOUS}, + "dev": {true, unix.MS_NODEV}, + "diratime": {true, unix.MS_NODIRATIME}, + "dirsync": {false, unix.MS_DIRSYNC}, + "exec": {true, unix.MS_NOEXEC}, + "mand": {false, unix.MS_MANDLOCK}, + "noatime": {false, unix.MS_NOATIME}, + "nodev": {false, unix.MS_NODEV}, + "nodiratime": {false, unix.MS_NODIRATIME}, + "noexec": {false, unix.MS_NOEXEC}, + "nomand": {true, unix.MS_MANDLOCK}, + "norelatime": {true, unix.MS_RELATIME}, + "nostrictatime": {true, unix.MS_STRICTATIME}, + "nosuid": {false, unix.MS_NOSUID}, + "rbind": {false, unix.MS_BIND | unix.MS_REC}, + "relatime": {false, unix.MS_RELATIME}, + "remount": {false, unix.MS_REMOUNT}, + "ro": {false, unix.MS_RDONLY}, + "rw": {true, unix.MS_RDONLY}, + "strictatime": {false, unix.MS_STRICTATIME}, + "suid": {true, unix.MS_NOSUID}, + "sync": {false, unix.MS_SYNCHRONOUS}, } propagationFlags := map[string]int{ - "private": syscall.MS_PRIVATE, - "shared": syscall.MS_SHARED, - "slave": syscall.MS_SLAVE, - "unbindable": syscall.MS_UNBINDABLE, - "rprivate": syscall.MS_PRIVATE | syscall.MS_REC, - "rshared": syscall.MS_SHARED | syscall.MS_REC, - "rslave": syscall.MS_SLAVE | syscall.MS_REC, - "runbindable": syscall.MS_UNBINDABLE | syscall.MS_REC, + "private": unix.MS_PRIVATE, + "shared": unix.MS_SHARED, + "slave": unix.MS_SLAVE, + "unbindable": unix.MS_UNBINDABLE, + "rprivate": unix.MS_PRIVATE | unix.MS_REC, + "rshared": unix.MS_SHARED | unix.MS_REC, + "rslave": unix.MS_SLAVE | unix.MS_REC, + "runbindable": unix.MS_UNBINDABLE | unix.MS_REC, } extensionFlags := map[string]struct { clear bool diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index ee6f19a7..98c7ae6d 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -6,7 +6,7 @@ import ( "fmt" "os" "os/exec" - "syscall" + "syscall" //only for Exec "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/configs" @@ -14,6 +14,8 @@ import ( "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/selinux/go-selinux/label" + + "golang.org/x/sys/unix" ) type linuxStandardInit struct { @@ -95,7 +97,7 @@ func (l *linuxStandardInit) Init() error { } if hostname := l.config.Config.Hostname; hostname != "" { - if err := syscall.Sethostname([]byte(hostname)); err != nil { + if err := unix.Sethostname([]byte(hostname)); err != nil { return err } } @@ -155,8 +157,8 @@ func (l *linuxStandardInit) Init() error { // compare the parent from the initial start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparented to something else so we should // just kill ourself and not cause problems for someone else. - if syscall.Getppid() != l.parentPid { - return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) + if unix.Getppid() != l.parentPid { + return unix.Kill(unix.Getpid(), unix.SIGKILL) } // check for the arg before waiting to make sure it exists and it is returned // as a create time error. @@ -168,11 +170,11 @@ func (l *linuxStandardInit) Init() error { l.pipe.Close() // wait for the fifo to be opened on the other side before // exec'ing the users process. - fd, err := syscall.Openat(l.stateDirFD, execFifoFilename, os.O_WRONLY|syscall.O_CLOEXEC, 0) + fd, err := unix.Openat(l.stateDirFD, execFifoFilename, os.O_WRONLY|unix.O_CLOEXEC, 0) if err != nil { return newSystemErrorWithCause(err, "openat exec fifo") } - if _, err := syscall.Write(fd, []byte("0")); err != nil { + if _, err := unix.Write(fd, []byte("0")); err != nil { return newSystemErrorWithCause(err, "write 0 exec fifo") } if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { @@ -182,7 +184,7 @@ func (l *linuxStandardInit) Init() error { } // close the statedir fd before exec because the kernel resets dumpable in the wrong order // https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318 - syscall.Close(l.stateDirFD) + unix.Close(l.stateDirFD) if err := syscall.Exec(name, l.config.Args[0:], os.Environ()); err != nil { return newSystemErrorWithCause(err, "exec user process") } diff --git a/libcontainer/state_linux.go b/libcontainer/state_linux.go index 62878acf..07055695 100644 --- a/libcontainer/state_linux.go +++ b/libcontainer/state_linux.go @@ -6,11 +6,12 @@ import ( "fmt" "os" "path/filepath" - "syscall" "github.com/Sirupsen/logrus" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) func newStateTransitionError(from, to containerState) error { @@ -39,7 +40,7 @@ type containerState interface { func destroy(c *linuxContainer) error { if !c.config.Namespaces.Contains(configs.NEWPID) { - if err := signalAllProcesses(c.cgroupManager, syscall.SIGKILL); err != nil { + if err := signalAllProcesses(c.cgroupManager, unix.SIGKILL); err != nil { logrus.Warn(err) } } @@ -156,7 +157,7 @@ func (i *createdState) transition(s containerState) error { } func (i *createdState) destroy() error { - i.c.initProcess.signal(syscall.SIGKILL) + i.c.initProcess.signal(unix.SIGKILL) return destroy(i.c) } diff --git a/libcontainer/system/linux.go b/libcontainer/system/linux.go index 1afc52b4..2ef7915a 100644 --- a/libcontainer/system/linux.go +++ b/libcontainer/system/linux.go @@ -7,8 +7,10 @@ import ( "fmt" "os" "os/exec" - "syscall" + "syscall" // only for exec "unsafe" + + "golang.org/x/sys/unix" ) // If arg2 is nonzero, set the "child subreaper" attribute of the @@ -53,8 +55,8 @@ func Execv(cmd string, args []string, env []string) error { return syscall.Exec(name, args, env) } -func Prlimit(pid, resource int, limit syscall.Rlimit) error { - _, _, err := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0) +func Prlimit(pid, resource int, limit unix.Rlimit) error { + _, _, err := unix.RawSyscall6(unix.SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(&limit)), uintptr(unsafe.Pointer(&limit)), 0, 0) if err != 0 { return err } @@ -62,7 +64,7 @@ func Prlimit(pid, resource int, limit syscall.Rlimit) error { } func SetParentDeathSignal(sig uintptr) error { - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 { + if _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_SET_PDEATHSIG, sig, 0); err != 0 { return err } return nil @@ -70,7 +72,7 @@ func SetParentDeathSignal(sig uintptr) error { func GetParentDeathSignal() (ParentDeathSignal, error) { var sig int - _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) + _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) if err != 0 { return -1, err } @@ -78,7 +80,7 @@ func GetParentDeathSignal() (ParentDeathSignal, error) { } func SetKeepCaps() error { - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 { + if _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_SET_KEEPCAPS, 1, 0); err != 0 { return err } @@ -86,7 +88,7 @@ func SetKeepCaps() error { } func ClearKeepCaps() error { - if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 { + if _, _, err := unix.RawSyscall(unix.SYS_PRCTL, unix.PR_SET_KEEPCAPS, 0, 0); err != 0 { return err } @@ -94,7 +96,7 @@ func ClearKeepCaps() error { } func Setctty() error { - if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 { + if _, _, err := unix.RawSyscall(unix.SYS_IOCTL, 0, uintptr(unix.TIOCSCTTY), 0); err != 0 { return err } return nil @@ -135,7 +137,7 @@ func SetSubreaper(i int) error { } func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { - _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) + _, _, e1 := unix.Syscall6(unix.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) if e1 != 0 { err = e1 } diff --git a/libcontainer/system/setns_linux.go b/libcontainer/system/setns_linux.go deleted file mode 100644 index 615ff4c8..00000000 --- a/libcontainer/system/setns_linux.go +++ /dev/null @@ -1,40 +0,0 @@ -package system - -import ( - "fmt" - "runtime" - "syscall" -) - -// Via http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7b21fddd087678a70ad64afc0f632e0f1071b092 -// -// We need different setns values for the different platforms and arch -// We are declaring the macro here because the SETNS syscall does not exist in th stdlib -var setNsMap = map[string]uintptr{ - "linux/386": 346, - "linux/arm64": 268, - "linux/amd64": 308, - "linux/arm": 375, - "linux/ppc": 350, - "linux/ppc64": 350, - "linux/ppc64le": 350, - "linux/s390x": 339, -} - -var sysSetns = setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)] - -func SysSetns() uint32 { - return uint32(sysSetns) -} - -func Setns(fd uintptr, flags uintptr) error { - ns, exists := setNsMap[fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)] - if !exists { - return fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime.GOARCH) - } - _, _, err := syscall.RawSyscall(ns, fd, flags, 0) - if err != 0 { - return err - } - return nil -} diff --git a/libcontainer/system/syscall_linux_386.go b/libcontainer/system/syscall_linux_386.go index bb44d895..3f7235ed 100644 --- a/libcontainer/system/syscall_linux_386.go +++ b/libcontainer/system/syscall_linux_386.go @@ -3,12 +3,12 @@ package system import ( - "syscall" + "golang.org/x/sys/unix" ) // Setuid sets the uid of the calling thread to the specified uid. func Setuid(uid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID32, uintptr(uid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0) if e1 != 0 { err = e1 } @@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { // Setgid sets the gid of the calling thread to the specified gid. func Setgid(gid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID32, uintptr(gid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0) if e1 != 0 { err = e1 } diff --git a/libcontainer/system/syscall_linux_64.go b/libcontainer/system/syscall_linux_64.go index 0816bf82..d7891a2f 100644 --- a/libcontainer/system/syscall_linux_64.go +++ b/libcontainer/system/syscall_linux_64.go @@ -3,12 +3,12 @@ package system import ( - "syscall" + "golang.org/x/sys/unix" ) // Setuid sets the uid of the calling thread to the specified uid. func Setuid(uid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(uid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETUID, uintptr(uid), 0, 0) if e1 != 0 { err = e1 } @@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { // Setgid sets the gid of the calling thread to the specified gid. func Setgid(gid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID, uintptr(gid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETGID, uintptr(gid), 0, 0) if e1 != 0 { err = e1 } diff --git a/libcontainer/system/syscall_linux_arm.go b/libcontainer/system/syscall_linux_arm.go index 3f780f31..31ff3deb 100644 --- a/libcontainer/system/syscall_linux_arm.go +++ b/libcontainer/system/syscall_linux_arm.go @@ -3,12 +3,12 @@ package system import ( - "syscall" + "golang.org/x/sys/unix" ) // Setuid sets the uid of the calling thread to the specified uid. func Setuid(uid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID32, uintptr(uid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETUID32, uintptr(uid), 0, 0) if e1 != 0 { err = e1 } @@ -17,7 +17,7 @@ func Setuid(uid int) (err error) { // Setgid sets the gid of the calling thread to the specified gid. func Setgid(gid int) (err error) { - _, _, e1 := syscall.RawSyscall(syscall.SYS_SETGID32, uintptr(gid), 0, 0) + _, _, e1 := unix.RawSyscall(unix.SYS_SETGID32, uintptr(gid), 0, 0) if e1 != 0 { err = e1 } diff --git a/libcontainer/system/xattrs_linux.go b/libcontainer/system/xattrs_linux.go index 30f74dfb..6628d4ae 100644 --- a/libcontainer/system/xattrs_linux.go +++ b/libcontainer/system/xattrs_linux.go @@ -1,8 +1,9 @@ package system import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) var _zero uintptr @@ -10,7 +11,7 @@ var _zero uintptr // Returns the size of xattrs and nil error // Requires path, takes allocated []byte or nil as last argument func Llistxattr(path string, dest []byte) (size int, err error) { - pathBytes, err := syscall.BytePtrFromString(path) + pathBytes, err := unix.BytePtrFromString(path) if err != nil { return -1, err } @@ -21,7 +22,7 @@ func Llistxattr(path string, dest []byte) (size int, err error) { newpathBytes = unsafe.Pointer(&_zero) } - _size, _, errno := syscall.Syscall6(syscall.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(newpathBytes), uintptr(len(dest)), 0, 0, 0) + _size, _, errno := unix.Syscall6(unix.SYS_LLISTXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(newpathBytes), uintptr(len(dest)), 0, 0, 0) size = int(_size) if errno != 0 { return -1, errno @@ -34,11 +35,11 @@ func Llistxattr(path string, dest []byte) (size int, err error) { // Requires path and its attribute as arguments func Lgetxattr(path string, attr string) ([]byte, error) { var sz int - pathBytes, err := syscall.BytePtrFromString(path) + pathBytes, err := unix.BytePtrFromString(path) if err != nil { return nil, err } - attrBytes, err := syscall.BytePtrFromString(attr) + attrBytes, err := unix.BytePtrFromString(attr) if err != nil { return nil, err } @@ -47,25 +48,25 @@ func Lgetxattr(path string, attr string) ([]byte, error) { sz = 128 dest := make([]byte, sz) destBytes := unsafe.Pointer(&dest[0]) - _sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + _sz, _, errno := unix.Syscall6(unix.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) switch { - case errno == syscall.ENODATA: + case errno == unix.ENODATA: return nil, errno - case errno == syscall.ENOTSUP: + case errno == unix.ENOTSUP: return nil, errno - case errno == syscall.ERANGE: + case errno == unix.ERANGE: // 128 byte array might just not be good enough, // A dummy buffer is used ``uintptr(0)`` to get real size // of the xattrs on disk - _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0) + _sz, _, errno = unix.Syscall6(unix.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0) sz = int(_sz) if sz < 0 { return nil, errno } dest = make([]byte, sz) destBytes := unsafe.Pointer(&dest[0]) - _sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) + _sz, _, errno = unix.Syscall6(unix.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) if errno != 0 { return nil, errno } @@ -77,11 +78,11 @@ func Lgetxattr(path string, attr string) ([]byte, error) { } func Lsetxattr(path string, attr string, data []byte, flags int) error { - pathBytes, err := syscall.BytePtrFromString(path) + pathBytes, err := unix.BytePtrFromString(path) if err != nil { return err } - attrBytes, err := syscall.BytePtrFromString(attr) + attrBytes, err := unix.BytePtrFromString(attr) if err != nil { return err } @@ -91,7 +92,7 @@ func Lsetxattr(path string, attr string, data []byte, flags int) error { } else { dataBytes = unsafe.Pointer(&_zero) } - _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) + _, _, errno := unix.Syscall6(unix.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0) if errno != 0 { return errno } diff --git a/libcontainer/user/lookup.go b/libcontainer/user/lookup.go index ab1439f3..bf491c89 100644 --- a/libcontainer/user/lookup.go +++ b/libcontainer/user/lookup.go @@ -2,7 +2,8 @@ package user import ( "errors" - "syscall" + + "golang.org/x/sys/unix" ) var ( @@ -40,7 +41,7 @@ func lookupUser(filter func(u User) bool) (User, error) { // user cannot be found (or there is no /etc/passwd file on the filesystem), // then CurrentUser returns an error. func CurrentUser() (User, error) { - return LookupUid(syscall.Getuid()) + return LookupUid(unix.Getuid()) } // LookupUser looks up a user by their username in /etc/passwd. If the user @@ -88,7 +89,7 @@ func lookupGroup(filter func(g Group) bool) (Group, error) { // entry in /etc/passwd. If the group cannot be found (or there is no // /etc/group file on the filesystem), then CurrentGroup returns an error. func CurrentGroup() (Group, error) { - return LookupGid(syscall.Getgid()) + return LookupGid(unix.Getgid()) } // LookupGroup looks up a group by its name in /etc/group. If the group cannot diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go index 2b35b9a7..baa54c9b 100644 --- a/libcontainer/utils/utils.go +++ b/libcontainer/utils/utils.go @@ -8,8 +8,9 @@ import ( "os" "path/filepath" "strings" - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) const ( @@ -41,7 +42,7 @@ func ResolveRootfs(uncleanRootfs string) (string, error) { // ExitStatus returns the correct exit status for a process based on if it // was signaled or exited cleanly -func ExitStatus(status syscall.WaitStatus) int { +func ExitStatus(status unix.WaitStatus) int { if status.Signaled() { return exitSignalOffset + int(status.Signal()) } diff --git a/libcontainer/utils/utils_test.go b/libcontainer/utils/utils_test.go index b7746829..fadca4bc 100644 --- a/libcontainer/utils/utils_test.go +++ b/libcontainer/utils/utils_test.go @@ -5,8 +5,9 @@ import ( "fmt" "os" "path/filepath" - "syscall" "testing" + + "golang.org/x/sys/unix" ) func TestGenerateName(t *testing.T) { @@ -94,7 +95,7 @@ func TestResolveRootfsWithNonExistingDir(t *testing.T) { } func TestExitStatus(t *testing.T) { - status := syscall.WaitStatus(0) + status := unix.WaitStatus(0) ex := ExitStatus(status) if ex != 0 { t.Errorf("expected exit status to equal 0 and received %d", ex) @@ -102,7 +103,7 @@ func TestExitStatus(t *testing.T) { } func TestExitStatusSignaled(t *testing.T) { - status := syscall.WaitStatus(2) + status := unix.WaitStatus(2) ex := ExitStatus(status) if ex != 130 { t.Errorf("expected exit status to equal 130 and received %d", ex) diff --git a/libcontainer/utils/utils_unix.go b/libcontainer/utils/utils_unix.go index 7b798cc7..c9608898 100644 --- a/libcontainer/utils/utils_unix.go +++ b/libcontainer/utils/utils_unix.go @@ -6,7 +6,8 @@ import ( "io/ioutil" "os" "strconv" - "syscall" + + "golang.org/x/sys/unix" ) func CloseExecFrom(minFd int) error { @@ -26,8 +27,8 @@ func CloseExecFrom(minFd int) error { continue } - // intentionally ignore errors from syscall.CloseOnExec - syscall.CloseOnExec(fd) + // intentionally ignore errors from unix.CloseOnExec + unix.CloseOnExec(fd) // the cases where this might fail are basically file descriptors that have already been closed (including and especially the one that was created when ioutil.ReadDir did the "opendir" syscall) } return nil @@ -35,7 +36,7 @@ func CloseExecFrom(minFd int) error { // NewSockPair returns a new unix socket pair func NewSockPair(name string) (parent *os.File, child *os.File, err error) { - fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) + fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM|unix.SOCK_CLOEXEC, 0) if err != nil { return nil, nil, err } diff --git a/libcontainer/xattr/xattr_linux.go b/libcontainer/xattr/xattr_linux.go index 933a7527..b01612b6 100644 --- a/libcontainer/xattr/xattr_linux.go +++ b/libcontainer/xattr/xattr_linux.go @@ -3,13 +3,13 @@ package xattr import ( - "syscall" - "github.com/opencontainers/runc/libcontainer/system" + + "golang.org/x/sys/unix" ) func XattrEnabled(path string) bool { - if Setxattr(path, "user.test", "") == syscall.ENOTSUP { + if Setxattr(path, "user.test", "") == unix.ENOTSUP { return false } return true diff --git a/signals.go b/signals.go index d787c940..910ea1ee 100644 --- a/signals.go +++ b/signals.go @@ -5,12 +5,14 @@ package main import ( "os" "os/signal" - "syscall" + "syscall" // only for Signal "github.com/Sirupsen/logrus" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/runc/libcontainer/utils" + + "golang.org/x/sys/unix" ) const signalBufferSize = 2048 @@ -76,9 +78,9 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach tty.resize() for s := range h.signals { switch s { - case syscall.SIGWINCH: + case unix.SIGWINCH: tty.resize() - case syscall.SIGCHLD: + case unix.SIGCHLD: exits, err := h.reap() if err != nil { logrus.Error(err) @@ -101,7 +103,7 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach } default: logrus.Debugf("sending signal to process %s", s) - if err := syscall.Kill(pid1, s.(syscall.Signal)); err != nil { + if err := unix.Kill(pid1, s.(syscall.Signal)); err != nil { logrus.Error(err) } } @@ -113,13 +115,13 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach // then returns all exits to the main event loop for further processing. func (h *signalHandler) reap() (exits []exit, err error) { var ( - ws syscall.WaitStatus - rus syscall.Rusage + ws unix.WaitStatus + rus unix.Rusage ) for { - pid, err := syscall.Wait4(-1, &ws, syscall.WNOHANG, &rus) + pid, err := unix.Wait4(-1, &ws, unix.WNOHANG, &rus) if err != nil { - if err == syscall.ECHILD { + if err == unix.ECHILD { return exits, nil } return nil, err