From 6a9b94927f55b7e8fc59a16a7e59d971c8fb746f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sun, 3 May 2020 16:40:56 +0200 Subject: [PATCH 1/3] Remove remaining uses of libcontainer/system package Signed-off-by: Sebastiaan van Stijn --- archive/tar_unix.go | 4 ++-- diff/apply/apply_linux.go | 4 ++-- sys/oom_unix.go | 4 +--- sys/userns_linux.go | 39 +++++++++++++++++++++++++++++++++++++++ sys/userns_unsupported.go | 25 +++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 sys/userns_linux.go create mode 100644 sys/userns_unsupported.go diff --git a/archive/tar_unix.go b/archive/tar_unix.go index 213408318..c7b08e81c 100644 --- a/archive/tar_unix.go +++ b/archive/tar_unix.go @@ -25,9 +25,9 @@ import ( "sync" "syscall" + "github.com/containerd/containerd/sys" "github.com/containerd/continuity/fs" "github.com/containerd/continuity/sysx" - "github.com/opencontainers/runc/libcontainer/system" "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -90,7 +90,7 @@ var ( ) func setInUserNS() { - inUserNS = system.RunningInUserNS() + inUserNS = sys.RunningInUserNS() } func skipFile(hdr *tar.Header) bool { diff --git a/diff/apply/apply_linux.go b/diff/apply/apply_linux.go index bbe9c17d9..5eeeced5c 100644 --- a/diff/apply/apply_linux.go +++ b/diff/apply/apply_linux.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd/archive" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" - "github.com/opencontainers/runc/libcontainer/system" + "github.com/containerd/containerd/sys" "github.com/pkg/errors" ) @@ -35,7 +35,7 @@ func apply(ctx context.Context, mounts []mount.Mount, r io.Reader) error { case len(mounts) == 1 && mounts[0].Type == "overlay": // OverlayConvertWhiteout (mknod c 0 0) doesn't work in userns. // https://github.com/containerd/containerd/issues/3762 - if system.RunningInUserNS() { + if sys.RunningInUserNS() { break } path, parents, err := getOverlayPath(mounts[0].Options) diff --git a/sys/oom_unix.go b/sys/oom_unix.go index 54412e9c3..d49d5bc8d 100644 --- a/sys/oom_unix.go +++ b/sys/oom_unix.go @@ -24,8 +24,6 @@ import ( "os" "strconv" "strings" - - "github.com/opencontainers/runc/libcontainer/system" ) // OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer @@ -40,7 +38,7 @@ func SetOOMScore(pid, score int) error { } defer f.Close() if _, err = f.WriteString(strconv.Itoa(score)); err != nil { - if os.IsPermission(err) && (system.RunningInUserNS() || RunningUnprivileged()) { + if os.IsPermission(err) && (RunningInUserNS() || RunningUnprivileged()) { return nil } return err diff --git a/sys/userns_linux.go b/sys/userns_linux.go new file mode 100644 index 000000000..4a70afe8a --- /dev/null +++ b/sys/userns_linux.go @@ -0,0 +1,39 @@ +/* + 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. +*/ + +package sys + +import ( + "github.com/opencontainers/runc/libcontainer/user" +) + +// RunningInUserNS detects whether we are currently running in a user namespace. +// Originally copied from github.com/lxc/lxd/shared/util.go +func RunningInUserNS() bool { + uidmap, err := user.CurrentProcessUIDMap() + if err != nil { + // This kernel-provided file only exists if user namespaces are supported + return false + } + /* + * We assume we are in the initial user namespace if we have a full + * range - 4294967295 uids starting at uid 0. + */ + if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 { + return false + } + return true +} diff --git a/sys/userns_unsupported.go b/sys/userns_unsupported.go new file mode 100644 index 000000000..549b50200 --- /dev/null +++ b/sys/userns_unsupported.go @@ -0,0 +1,25 @@ +// +build !linux + +/* + 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. +*/ + +package sys + +// RunningInUserNS is a stub for non-Linux systems +// Always returns false +func RunningInUserNS() bool { + return false +} From 76c62f27222e908b04785e512b1d111d91a54cb0 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 4 May 2020 14:45:37 +0200 Subject: [PATCH 2/3] sys: simplify RunningInUserNS to original implementation Given that we're only interested in detecting if userns is enabled, and no further details about the mapping, we can revert this function to go back to its original implementation in github.com/lxc/lxd/shared/util.go Signed-off-by: Sebastiaan van Stijn --- sys/userns_linux.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/sys/userns_linux.go b/sys/userns_linux.go index 4a70afe8a..534253ad8 100644 --- a/sys/userns_linux.go +++ b/sys/userns_linux.go @@ -17,22 +17,36 @@ package sys import ( - "github.com/opencontainers/runc/libcontainer/user" + "bufio" + "fmt" + "os" ) // RunningInUserNS detects whether we are currently running in a user namespace. // Originally copied from github.com/lxc/lxd/shared/util.go func RunningInUserNS() bool { - uidmap, err := user.CurrentProcessUIDMap() + file, err := os.Open("/proc/self/uid_map") if err != nil { // This kernel-provided file only exists if user namespaces are supported return false } + defer file.Close() + + buf := bufio.NewReader(file) + l, _, err := buf.ReadLine() + if err != nil { + return false + } + + line := string(l) + var a, b, c int64 + fmt.Sscanf(line, "%d %d %d", &a, &b, &c) + /* * We assume we are in the initial user namespace if we have a full * range - 4294967295 uids starting at uid 0. */ - if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 { + if a == 0 && b == 0 && c == 4294967295 { return false } return true From 0088c2de8019dfd38040634931ce05e04b1aa74f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 4 May 2020 15:35:13 +0200 Subject: [PATCH 3/3] sys: RunningInUserNS(): use sync.Once Signed-off-by: Sebastiaan van Stijn --- archive/tar_unix.go | 13 +---------- sys/userns_linux.go | 53 ++++++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/archive/tar_unix.go b/archive/tar_unix.go index c7b08e81c..6e89d2fdb 100644 --- a/archive/tar_unix.go +++ b/archive/tar_unix.go @@ -22,7 +22,6 @@ import ( "archive/tar" "os" "strings" - "sync" "syscall" "github.com/containerd/containerd/sys" @@ -84,21 +83,11 @@ func mkdir(path string, perm os.FileMode) error { return os.Chmod(path, perm) } -var ( - inUserNS bool - nsOnce sync.Once -) - -func setInUserNS() { - inUserNS = sys.RunningInUserNS() -} - func skipFile(hdr *tar.Header) bool { switch hdr.Typeflag { case tar.TypeBlock, tar.TypeChar: // cannot create a device if running in user namespace - nsOnce.Do(setInUserNS) - return inUserNS + return sys.RunningInUserNS() default: return false } diff --git a/sys/userns_linux.go b/sys/userns_linux.go index 534253ad8..3cd1a2222 100644 --- a/sys/userns_linux.go +++ b/sys/userns_linux.go @@ -20,34 +20,43 @@ import ( "bufio" "fmt" "os" + "sync" +) + +var ( + inUserNS bool + nsOnce sync.Once ) // RunningInUserNS detects whether we are currently running in a user namespace. // Originally copied from github.com/lxc/lxd/shared/util.go func RunningInUserNS() bool { - file, err := os.Open("/proc/self/uid_map") - if err != nil { - // This kernel-provided file only exists if user namespaces are supported - return false - } - defer file.Close() + nsOnce.Do(func() { + file, err := os.Open("/proc/self/uid_map") + if err != nil { + // This kernel-provided file only exists if user namespaces are supported + return + } + defer file.Close() - buf := bufio.NewReader(file) - l, _, err := buf.ReadLine() - if err != nil { - return false - } + buf := bufio.NewReader(file) + l, _, err := buf.ReadLine() + if err != nil { + return + } - line := string(l) - var a, b, c int64 - fmt.Sscanf(line, "%d %d %d", &a, &b, &c) + line := string(l) + var a, b, c int64 + fmt.Sscanf(line, "%d %d %d", &a, &b, &c) - /* - * We assume we are in the initial user namespace if we have a full - * range - 4294967295 uids starting at uid 0. - */ - if a == 0 && b == 0 && c == 4294967295 { - return false - } - return true + /* + * We assume we are in the initial user namespace if we have a full + * range - 4294967295 uids starting at uid 0. + */ + if a == 0 && b == 0 && c == 4294967295 { + return + } + inUserNS = true + }) + return inUserNS }