Debian

Available patches from Ubuntu

To see Ubuntu differences wrt. to Debian, write down a grep-dctrl query identifying the packages you're interested in:
grep-dctrl -n -sPackage Sources.Debian
(e.g. -FPackage linux-ntfs or linux-ntfs)

Modified packages are listed below:

Debian ( Changelog | PTS | Bugs ) Ubuntu ( Changelog | txt | LP | Bugs ) | Diff from Ubuntu

Source: golang-github-go-ldap-ldap

golang-github-go-ldap-ldap (2.5.1-4ubuntu1) groovy; urgency=medium * d/p/64bit-align.patch: Ensure 64-bit alignment for atomics on 32-bit platforms. Thanks to Psychotropos <truthbit2@gmail.com>. -- Andreas Hasenack <andreas@canonical.com> Thu, 18 Jun 2020 12:45:55 -0300

Modifications :
  1. Download patch debian/control

    --- 2.5.1-4/debian/control 2018-02-06 04:58:37.000000000 +0000 +++ 2.5.1-4ubuntu1/debian/control 2020-06-18 15:45:55.000000000 +0000 @@ -1,7 +1,8 @@ Source: golang-github-go-ldap-ldap Section: devel Priority: optional -Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> Uploaders: Alexandre Viau <aviau@debian.org> Build-Depends: debhelper (>= 10), dh-golang,
  2. Download patch debian/patches/64bit-align.patch

    --- 2.5.1-4/debian/patches/64bit-align.patch 1970-01-01 00:00:00.000000000 +0000 +++ 2.5.1-4ubuntu1/debian/patches/64bit-align.patch 2020-06-18 15:45:55.000000000 +0000 @@ -0,0 +1,34 @@ +From 412981c96a5ef1da5866f88e9f368a4728b44d6f Mon Sep 17 00:00:00 2001 +From: Psychotropos <truthbit2@gmail.com> +Date: Sat, 1 Dec 2018 04:51:20 +0000 +Subject: [PATCH] conn: Ensure 64-bit alignment for atomics on 32-bit platforms + +--- + conn.go | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Origin: upstream, https://github.com/go-ldap/ldap/commit/412981c96a5ef1da5866f88e9f368a4728b44d6f +Last-Update: 2020-06-18 + +diff --git a/conn.go b/conn.go +index 50d8c3f..526cc30 100644 +--- a/conn.go ++++ b/conn.go +@@ -85,6 +85,9 @@ const ( + + // Conn represents an LDAP Connection + type Conn struct { ++ // requestTimeout is loaded atomically ++ // so we need to ensure 64-bit alignment on 32-bit platforms. ++ requestTimeout int64 + conn net.Conn + isTLS bool + closing uint32 +@@ -98,7 +101,6 @@ type Conn struct { + wgClose sync.WaitGroup + outstandingRequests uint + messageMutex sync.Mutex +- requestTimeout int64 + } + + var _ Client = &Conn{}
  3. Download patch debian/patches/series

    --- 2.5.1-4/debian/patches/series 2018-02-06 04:58:37.000000000 +0000 +++ 2.5.1-4ubuntu1/debian/patches/series 2020-06-18 15:45:55.000000000 +0000 @@ -1,2 +1,3 @@ disable-internet-tests.patch 0002-Require-explicit-intention-for-empty-password.patch +64bit-align.patch

Debian ( Changelog | PTS | Bugs ) Ubuntu ( Changelog | txt | LP | Bugs ) | Diff from Ubuntu

Source: golang-go.uber-zap

golang-go.uber-zap (1.14.1-1ubuntu1) groovy; urgency=medium * d/rules: add an extra timeout scaling factor when building or testing (dep8) on armhf and arm64 to workaround a flaky test that is more likely to fail on slower systems. -- Andreas Hasenack <andreas@canonical.com> Tue, 16 Jun 2020 09:08:55 -0300

Modifications :
  1. Download patch debian/rules

    --- 1.14.1-1/debian/rules 2020-03-22 11:13:28.000000000 +0000 +++ 1.14.1-1ubuntu1/debian/rules 2020-06-16 12:07:11.000000000 +0000 @@ -1,6 +1,14 @@ #!/usr/bin/make -f export DH_GOLANG_EXCLUDES := benchmarks +# https://github.com/uber-go/zap/issues/62 +# and +# https://github.com/uber-go/zap/issues/334 +# The actual scaling factor was found by experimentation +# and is of course subject to change +ifneq (,$(filter $(DEB_BUILD_ARCH),armhf arm64)) +export TEST_TIMEOUT_SCALE := 60 +endif %: dh $@ --buildsystem=golang --with=golang
  2. Download patch debian/control

    --- 1.14.1-1/debian/control 2020-03-22 11:13:28.000000000 +0000 +++ 1.14.1-1ubuntu1/debian/control 2020-06-16 12:08:55.000000000 +0000 @@ -1,7 +1,8 @@ Source: golang-go.uber-zap Section: devel Priority: optional -Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> Uploaders: Alexandre Viau <aviau@debian.org>, Nilesh Patra <npatra974@gmail.com> Build-Depends: debhelper-compat (= 12), dh-golang,

Debian ( Changelog | PTS | Bugs ) Ubuntu ( Changelog | txt | LP | Bugs ) | Diff from Ubuntu

Source: influxdb

influxdb (1.6.4-2ubuntu1) groovy; urgency=medium * Build and runtime depend on golang-github-prometheus-client-golang-dev -- Lucas Kanashiro <kanashiro@ubuntu.com> Mon, 06 Jul 2020 11:14:12 -0300

Modifications :
  1. Download patch debian/control

    --- 1.6.4-2/debian/control 2020-04-21 18:59:01.000000000 +0000 +++ 1.6.4-2ubuntu1/debian/control 2020-07-06 14:14:12.000000000 +0000 @@ -2,7 +2,8 @@ Source: influxdb Section: database Priority: optional Homepage: https://influxdata.com/time-series-platform/influxdb/ -Maintainer: Debian Go Packaging Team <team+pkg-go@tracker.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian Go Packaging Team <team+pkg-go@tracker.debian.org> Uploaders: Alexandre Viau <aviau@debian.org>, Tim Potter <tpot@hpe.com> Build-Depends: debhelper (>= 9.20160709), dh-golang (>=1.9), @@ -41,7 +42,7 @@ Build-Depends: debhelper (>= 9.20160709) golang-github-mattn-go-isatty-dev, golang-golang-x-time-dev, golang-github-opentracing-opentracing-go-dev, - golang-prometheus-client-dev, + golang-github-prometheus-client-golang-dev, golang-github-golang-snappy-dev, golang-github-klauspost-pgzip-dev Standards-Version: 3.9.8 @@ -87,7 +88,7 @@ Depends: ${misc:Depends}, golang-github-mattn-go-isatty-dev, golang-golang-x-time-dev, golang-github-opentracing-opentracing-go-dev, - golang-prometheus-client-dev, + golang-github-prometheus-client-golang-dev, golang-github-golang-snappy-dev, golang-github-klauspost-pgzip-dev Description: Scalable datastore for metrics, events, and real-time analytics. Dev package

Debian ( Changelog | PTS | Bugs ) Ubuntu ( Changelog | txt | LP | Bugs ) | Diff from Ubuntu

Source: runc

runc (1.0.0~rc10-0ubuntu1) focal; urgency=medium [ Lucas Kanashiro ] * Run dh_golang_autopkgtest with isolation-machine restriction (LP: #1856083) - d/control: remove Testsuite field since we are now overwriting the autodep8 test definition. - d/t/control: overwrite autodep8 test definition to add isolation-machine restriction. * d/t/control: Use commas in Restrictions field of basic-smoke test [ Tianon Gravi ] * Update to 1.0.0-rc10 upstream release -- Tianon Gravi <tianon@debian.org> Tue, 18 Feb 2020 09:06:24 +1300 runc (1.0.0~rc8+git20190923.3e425f80-0ubuntu1) eoan; urgency=medium * New upstream snapshot, fixing CVE-2019-16884. -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Mon, 30 Sep 2019 14:12:18 +1300 runc (1.0.0~rc8-0ubuntu1) eoan; urgency=medium * New upstream version. -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Wed, 18 Sep 2019 10:49:47 +0200 runc (1.0.0~rc7+git20190403.029124da-0ubuntu1) disco; urgency=medium * New upstream version. * Fix dependencies of golang-github-opencontainers-runc-dev package. -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Fri, 12 Apr 2019 12:29:03 +1200 runc (1.0.0~rc6+git20190307.2b18fe1d-0ubuntu1) disco; urgency=medium * Update to https://github.com/opencontainers/runc/commit/2b18fe1d885ee5083ef9f0838fee39b62d653e30 - See also: https://github.com/containerd/containerd/blob/v1.2.5/RUNC.md https://github.com/containerd/containerd/blob/v1.2.5/vendor.conf#L23 * d/patches/0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b.patch: dropped, applied upstream. -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Thu, 14 Mar 2019 11:12:22 +1300 runc (1.0.0~rc6+git20181203.96ec2177-0ubuntu1) disco; urgency=medium * Add "basic-smoke" autopkgtest to verify basic functionality -- Tianon Gravi <tianon@debian.org> Thu, 14 Feb 2019 14:23:13 -0800 runc (1.0.0~rc6+git20181203.96ec2177-0~ubuntu2) disco; urgency=medium * d/patches/0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b.patch: Apply upstream fix for CVE-2019-5736. -- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Tue, 12 Feb 2019 11:52:37 +1300 runc (1.0.0~rc6+git20181203.96ec2177-0~ubuntu1) disco; urgency=medium * Update to https://github.com/opencontainers/runc/commit/96ec2177ae841256168fcf76954f7177af9446eb - See also: https://github.com/containerd/containerd/blob/v1.2.2/RUNC.md https://github.com/containerd/containerd/blob/v1.2.2/vendor.conf#L23 -- Tianon Gravi <tianon@debian.org> Thu, 17 Jan 2019 21:06:43 -0800

Modifications :
  1. Download patch libcontainer/cgroups/fs/cpu_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpu_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpu_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -8,6 +8,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" ) func TestCpuSetShares(t *testing.T) { @@ -29,7 +30,7 @@ func TestCpuSetShares(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "cpu.shares") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.shares") if err != nil { t.Fatalf("Failed to parse cpu.shares - %s", err) } @@ -70,7 +71,7 @@ func TestCpuSetBandWidth(t *testing.T) { t.Fatal(err) } - quota, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_quota_us") + quota, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.cfs_quota_us") if err != nil { t.Fatalf("Failed to parse cpu.cfs_quota_us - %s", err) } @@ -78,21 +79,21 @@ func TestCpuSetBandWidth(t *testing.T) { t.Fatal("Got the wrong value, set cpu.cfs_quota_us failed.") } - period, err := getCgroupParamUint(helper.CgroupPath, "cpu.cfs_period_us") + period, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.cfs_period_us") if err != nil { t.Fatalf("Failed to parse cpu.cfs_period_us - %s", err) } if period != periodAfter { t.Fatal("Got the wrong value, set cpu.cfs_period_us failed.") } - rtRuntime, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") + rtRuntime, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") if err != nil { t.Fatalf("Failed to parse cpu.rt_runtime_us - %s", err) } if rtRuntime != rtRuntimeAfter { t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") } - rtPeriod, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") + rtPeriod, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") if err != nil { t.Fatalf("Failed to parse cpu.rt_period_us - %s", err) } @@ -185,21 +186,21 @@ func TestCpuSetRtSchedAtApply(t *testing t.Fatal(err) } - rtRuntime, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") + rtRuntime, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.rt_runtime_us") if err != nil { t.Fatalf("Failed to parse cpu.rt_runtime_us - %s", err) } if rtRuntime != rtRuntimeAfter { t.Fatal("Got the wrong value, set cpu.rt_runtime_us failed.") } - rtPeriod, err := getCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") + rtPeriod, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cpu.rt_period_us") if err != nil { t.Fatalf("Failed to parse cpu.rt_period_us - %s", err) } if rtPeriod != rtPeriodAfter { t.Fatal("Got the wrong value, set cpu.rt_period_us failed.") } - pid, err := getCgroupParamUint(helper.CgroupPath, "cgroup.procs") + pid, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "cgroup.procs") if err != nil { t.Fatalf("Failed to parse cgroup.procs - %s", err) }
  2. Download patch libcontainer/integration/exec_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/integration/exec_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/integration/exec_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -14,6 +14,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runtime-spec/specs-go" @@ -206,6 +207,9 @@ func TestEnter(t *testing.T) { if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } rootfs, err := newRootfs() ok(t, err) @@ -512,6 +516,9 @@ func testFreeze(t *testing.T, systemd bo if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } rootfs, err := newRootfs() ok(t, err) @@ -566,6 +573,10 @@ func testCpuShares(t *testing.T, systemd if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } + rootfs, err := newRootfs() ok(t, err) defer remove(rootfs) @@ -597,6 +608,9 @@ func testPids(t *testing.T, systemd bool if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } rootfs, err := newRootfs() ok(t, err) @@ -680,6 +694,10 @@ func testRunWithKernelMemory(t *testing. if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } + rootfs, err := newRootfs() ok(t, err) defer remove(rootfs)
  3. Download patch README.md

    --- 1.0.0~rc9+dfsg1-1/README.md 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/README.md 2020-01-22 16:19:15.000000000 +0000 @@ -16,9 +16,13 @@ This means that `runc` 1.0.0 should impl You can find official releases of `runc` on the [release](https://github.com/opencontainers/runc/releases) page. +Currently, the following features are not considered to be production-ready: + +* Support for cgroup v2 + ## Security -Reporting process and disclosure communications are outlined in [/org/security](https://github.com/opencontainers/org/blob/master/security/) +The reporting process and disclosure communications are outlined in [/org/security](https://github.com/opencontainers/org/blob/master/security/). ## Building @@ -229,7 +233,14 @@ runc delete mycontainerid This allows higher level systems to augment the containers creation logic with setup of various settings after the container is created and/or before it is deleted. For example, the container's network stack is commonly set up after `create` but before `start`. #### Rootless containers -`runc` has the ability to run containers without root privileges. This is called `rootless`. You need to pass some parameters to `runc` in order to run rootless containers. See below and compare with the previous version. Run the following commands as an ordinary user: +`runc` has the ability to run containers without root privileges. This is called `rootless`. You need to pass some parameters to `runc` in order to run rootless containers. See below and compare with the previous version. + +**Note:** In order to use this feature, "User Namespaces" must be compiled and enabled in your kernel. There are various ways to do this depending on your distribution: +- Confirm `CONFIG_USER_NS=y` is set in your kernel configuration (normally found in `/proc/config.gz`) +- Arch/Debian: `echo 1 > /proc/sys/kernel/unprivileged_userns_clone` +- RHEL/CentOS 7: `echo 28633 > /proc/sys/user/max_user_namespaces` + +Run the following commands as an ordinary user: ```bash # Same as the first example mkdir ~/mycontainer
  4. Download patch libcontainer/cgroups/fs/blkio.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/blkio.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/blkio.go 2020-01-22 16:19:15.000000000 +0000 @@ -11,6 +11,7 @@ import ( "strings" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -31,41 +32,41 @@ func (s *BlkioGroup) Apply(d *cgroupData func (s *BlkioGroup) Set(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.BlkioWeight != 0 { - if err := writeFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { + if err := fscommon.WriteFile(path, "blkio.weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { return err } } if cgroup.Resources.BlkioLeafWeight != 0 { - if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil { + if err := fscommon.WriteFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil { return err } } for _, wd := range cgroup.Resources.BlkioWeightDevice { - if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil { + if err := fscommon.WriteFile(path, "blkio.weight_device", wd.WeightString()); err != nil { return err } - if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { + if err := fscommon.WriteFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { return err } } for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice { - if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { + if err := fscommon.WriteFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { return err } } for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice { - if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { + if err := fscommon.WriteFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { return err } } for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice { - if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { + if err := fscommon.WriteFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { return err } } for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice { - if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { + if err := fscommon.WriteFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { return err } }
  5. Download patch vendor/github.com/cilium/ebpf/asm/alu_string.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/alu_string.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/alu_string.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,107 @@ +// Code generated by "stringer -output alu_string.go -type=Source,Endianness,ALUOp"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidSource-255] + _ = x[ImmSource-0] + _ = x[RegSource-8] +} + +const ( + _Source_name_0 = "ImmSource" + _Source_name_1 = "RegSource" + _Source_name_2 = "InvalidSource" +) + +func (i Source) String() string { + switch { + case i == 0: + return _Source_name_0 + case i == 8: + return _Source_name_1 + case i == 255: + return _Source_name_2 + default: + return "Source(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidEndian-255] + _ = x[LE-0] + _ = x[BE-8] +} + +const ( + _Endianness_name_0 = "LE" + _Endianness_name_1 = "BE" + _Endianness_name_2 = "InvalidEndian" +) + +func (i Endianness) String() string { + switch { + case i == 0: + return _Endianness_name_0 + case i == 8: + return _Endianness_name_1 + case i == 255: + return _Endianness_name_2 + default: + return "Endianness(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidALUOp-255] + _ = x[Add-0] + _ = x[Sub-16] + _ = x[Mul-32] + _ = x[Div-48] + _ = x[Or-64] + _ = x[And-80] + _ = x[LSh-96] + _ = x[RSh-112] + _ = x[Neg-128] + _ = x[Mod-144] + _ = x[Xor-160] + _ = x[Mov-176] + _ = x[ArSh-192] + _ = x[Swap-208] +} + +const _ALUOp_name = "AddSubMulDivOrAndLShRShNegModXorMovArShSwapInvalidALUOp" + +var _ALUOp_map = map[ALUOp]string{ + 0: _ALUOp_name[0:3], + 16: _ALUOp_name[3:6], + 32: _ALUOp_name[6:9], + 48: _ALUOp_name[9:12], + 64: _ALUOp_name[12:14], + 80: _ALUOp_name[14:17], + 96: _ALUOp_name[17:20], + 112: _ALUOp_name[20:23], + 128: _ALUOp_name[23:26], + 144: _ALUOp_name[26:29], + 160: _ALUOp_name[29:32], + 176: _ALUOp_name[32:35], + 192: _ALUOp_name[35:39], + 208: _ALUOp_name[39:43], + 255: _ALUOp_name[43:55], +} + +func (i ALUOp) String() string { + if str, ok := _ALUOp_map[i]; ok { + return str + } + return "ALUOp(" + strconv.FormatInt(int64(i), 10) + ")" +}
  6. Download patch libcontainer/cgroups/fs2/cpu.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/cpu.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/cpu.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,56 @@ +// +build linux + +package fs2 + +import ( + "bufio" + "os" + "path/filepath" + "strconv" + + "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" +) + +func setCpu(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.Resources.CpuWeight != 0 { + if err := fscommon.WriteFile(dirPath, "cpu.weight", strconv.FormatUint(cgroup.Resources.CpuWeight, 10)); err != nil { + return err + } + } + + if cgroup.Resources.CpuMax != "" { + if err := fscommon.WriteFile(dirPath, "cpu.max", cgroup.Resources.CpuMax); err != nil { + return err + } + } + + return nil +} +func statCpu(dirPath string, stats *cgroups.Stats) error { + f, err := os.Open(filepath.Join(dirPath, "cpu.stat")) + if err != nil { + return err + } + defer f.Close() + + sc := bufio.NewScanner(f) + for sc.Scan() { + t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text()) + if err != nil { + return err + } + switch t { + case "usage_usec": + stats.CpuStats.CpuUsage.TotalUsage = v * 1000 + + case "user_usec": + stats.CpuStats.CpuUsage.UsageInUsermode = v * 1000 + + case "system_usec": + stats.CpuStats.CpuUsage.UsageInKernelmode = v * 1000 + } + } + return nil +}
  7. Download patch debian/tests/control

    --- 1.0.0~rc9+dfsg1-1/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/tests/control 2020-02-17 20:05:23.000000000 +0000 @@ -0,0 +1,7 @@ +Tests: basic-smoke +Depends: busybox-static, @ +Restrictions: allow-stderr, isolation-machine, needs-root + +Test-Command: /usr/bin/dh_golang_autopkgtest +Depends: @, @builddeps@, dh-golang +Restrictions: allow-stderr, isolation-machine
  8. Download patch vendor/github.com/cilium/ebpf/asm/jump_string.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/jump_string.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/jump_string.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,53 @@ +// Code generated by "stringer -output jump_string.go -type=JumpOp"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidJumpOp-255] + _ = x[Ja-0] + _ = x[JEq-16] + _ = x[JGT-32] + _ = x[JGE-48] + _ = x[JSet-64] + _ = x[JNE-80] + _ = x[JSGT-96] + _ = x[JSGE-112] + _ = x[Call-128] + _ = x[Exit-144] + _ = x[JLT-160] + _ = x[JLE-176] + _ = x[JSLT-192] + _ = x[JSLE-208] +} + +const _JumpOp_name = "JaJEqJGTJGEJSetJNEJSGTJSGECallExitJLTJLEJSLTJSLEInvalidJumpOp" + +var _JumpOp_map = map[JumpOp]string{ + 0: _JumpOp_name[0:2], + 16: _JumpOp_name[2:5], + 32: _JumpOp_name[5:8], + 48: _JumpOp_name[8:11], + 64: _JumpOp_name[11:15], + 80: _JumpOp_name[15:18], + 96: _JumpOp_name[18:22], + 112: _JumpOp_name[22:26], + 128: _JumpOp_name[26:30], + 144: _JumpOp_name[30:34], + 160: _JumpOp_name[34:37], + 176: _JumpOp_name[37:40], + 192: _JumpOp_name[40:44], + 208: _JumpOp_name[44:48], + 255: _JumpOp_name[48:61], +} + +func (i JumpOp) String() string { + if str, ok := _JumpOp_map[i]; ok { + return str + } + return "JumpOp(" + strconv.FormatInt(int64(i), 10) + ")" +}
  9. Download patch libcontainer/container_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/container_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/container_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -265,22 +265,24 @@ func (c *linuxContainer) Exec() error { func (c *linuxContainer) exec() error { path := filepath.Join(c.root, execFifoFilename) - - fifoOpen := make(chan struct{}) - select { - case <-awaitProcessExit(c.initProcess.pid(), fifoOpen): - return errors.New("container process is already dead") - case result := <-awaitFifoOpen(path): - close(fifoOpen) - if result.err != nil { - return result.err - } - f := result.file - defer f.Close() - if err := readFromExecFifo(f); err != nil { - return err + pid := c.initProcess.pid() + blockingFifoOpenCh := awaitFifoOpen(path) + for { + select { + case result := <-blockingFifoOpenCh: + return handleFifoResult(result) + + case <-time.After(time.Millisecond * 100): + stat, err := system.Stat(pid) + if err != nil || stat.State == system.Zombie { + // could be because process started, ran, and completed between our 100ms timeout and our system.Stat() check. + // see if the fifo exists and has data (with a non-blocking open, which will succeed if the writing process is complete). + if err := handleFifoResult(fifoOpen(path, false)); err != nil { + return errors.New("container process is already dead") + } + return nil + } } - return os.Remove(path) } } @@ -295,38 +297,39 @@ func readFromExecFifo(execFifo io.Reader return nil } -func awaitProcessExit(pid int, exit <-chan struct{}) <-chan struct{} { - isDead := make(chan struct{}) - go func() { - for { - select { - case <-exit: - return - case <-time.After(time.Millisecond * 100): - stat, err := system.Stat(pid) - if err != nil || stat.State == system.Zombie { - close(isDead) - return - } - } - } - }() - return isDead -} - func awaitFifoOpen(path string) <-chan openResult { fifoOpened := make(chan openResult) go func() { - f, err := os.OpenFile(path, os.O_RDONLY, 0) - if err != nil { - fifoOpened <- openResult{err: newSystemErrorWithCause(err, "open exec fifo for reading")} - return - } - fifoOpened <- openResult{file: f} + result := fifoOpen(path, true) + fifoOpened <- result }() return fifoOpened } +func fifoOpen(path string, block bool) openResult { + flags := os.O_RDONLY + if !block { + flags |= syscall.O_NONBLOCK + } + f, err := os.OpenFile(path, flags, 0) + if err != nil { + return openResult{err: newSystemErrorWithCause(err, "open exec fifo for reading")} + } + return openResult{file: f} +} + +func handleFifoResult(result openResult) error { + if result.err != nil { + return result.err + } + f := result.file + defer f.Close() + if err := readFromExecFifo(f); err != nil { + return err + } + return os.Remove(f.Name()) +} + type openResult struct { file *os.File err error @@ -940,7 +943,7 @@ func (c *linuxContainer) Checkpoint(criu // Since a container can be C/R'ed multiple times, // the checkpoint directory may already exist. - if err := os.Mkdir(criuOpts.ImagesDirectory, 0755); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.ImagesDirectory, 0700); err != nil && !os.IsExist(err) { return err } @@ -948,7 +951,7 @@ func (c *linuxContainer) Checkpoint(criu criuOpts.WorkDirectory = filepath.Join(c.root, "criu.work") } - if err := os.Mkdir(criuOpts.WorkDirectory, 0755); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.WorkDirectory, 0700); err != nil && !os.IsExist(err) { return err } @@ -1111,7 +1114,7 @@ func (c *linuxContainer) Checkpoint(criu return err } - err = ioutil.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0655) + err = ioutil.WriteFile(filepath.Join(criuOpts.ImagesDirectory, descriptorsFilename), fdsJSON, 0600) if err != nil { return err } @@ -1246,7 +1249,7 @@ func (c *linuxContainer) Restore(process } // Since a container can be C/R'ed multiple times, // the work directory may already exist. - if err := os.Mkdir(criuOpts.WorkDirectory, 0655); err != nil && !os.IsExist(err) { + if err := os.Mkdir(criuOpts.WorkDirectory, 0700); err != nil && !os.IsExist(err) { return err } workDir, err := os.Open(criuOpts.WorkDirectory) @@ -1824,7 +1827,7 @@ func (c *linuxContainer) isPaused() (boo data, err := ioutil.ReadFile(filepath.Join(fcg, filename)) if err != nil { // If freezer cgroup is not mounted, the container would just be not paused. - if os.IsNotExist(err) { + if os.IsNotExist(err) || err == syscall.ENODEV { return false, nil } return false, newSystemErrorWithCause(err, "checking if container is paused")
  10. Download patch libcontainer/cgroups/fs/pids_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/pids_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/pids_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" - "golang.org/x/sys/unix" -) - -type PidsGroupV2 struct { -} - -func (s *PidsGroupV2) Name() string { - return "pids" -} - -func (s *PidsGroupV2) Apply(d *cgroupData) error { - _, err := d.join("pids") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func (s *PidsGroupV2) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.Resources.PidsLimit != 0 { - // "max" is the fallback value. - limit := "max" - - if cgroup.Resources.PidsLimit > 0 { - limit = strconv.FormatInt(cgroup.Resources.PidsLimit, 10) - } - - if err := writeFile(path, "pids.max", limit); err != nil { - return err - } - } - - return nil -} - -func (s *PidsGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("pids")) -} - -func isNOTSUP(err error) bool { - switch err := err.(type) { - case *os.PathError: - return err.Err == unix.ENOTSUP - default: - return false - } -} - -func (s *PidsGroupV2) GetStats(path string, stats *cgroups.Stats) error { - current, err := getCgroupParamUint(path, "pids.current") - if os.IsNotExist(err) { - // if the controller is not enabled, let's read the list - // PIDs (or threads if cgroup.threads is enabled) - contents, err := ioutil.ReadFile(filepath.Join(path, "cgroup.procs")) - if err != nil && isNOTSUP(err) { - contents, err = ioutil.ReadFile(filepath.Join(path, "cgroup.threads")) - } - if err != nil { - return err - } - pids := make(map[string]string) - for _, i := range strings.Split(string(contents), "\n") { - if i != "" { - pids[i] = i - } - } - stats.PidsStats.Current = uint64(len(pids)) - stats.PidsStats.Limit = 0 - return nil - - } - if err != nil { - return fmt.Errorf("failed to parse pids.current - %s", err) - } - - maxString, err := getCgroupParamString(path, "pids.max") - if err != nil { - return fmt.Errorf("failed to parse pids.max - %s", err) - } - - // Default if pids.max == "max" is 0 -- which represents "no limit". - var max uint64 - if maxString != "max" { - max, err = parseUint(maxString, 10, 64) - if err != nil { - return fmt.Errorf("failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q", maxString, filepath.Join(path, "pids.max")) - } - } - - stats.PidsStats.Current = current - stats.PidsStats.Limit = max - return nil -}
  11. Download patch libcontainer/cgroups/systemd/unified_hierarchy.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/systemd/unified_hierarchy.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/systemd/unified_hierarchy.go 2020-01-22 16:19:15.000000000 +0000 @@ -1,4 +1,4 @@ -// +build linux,!static_build +// +build linux package systemd @@ -14,8 +14,9 @@ import ( systemdDbus "github.com/coreos/go-systemd/dbus" "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/cgroups/fs" + "github.com/opencontainers/runc/libcontainer/cgroups/fs2" "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -25,15 +26,6 @@ type UnifiedManager struct { Paths map[string]string } -var unifiedSubsystems = subsystemSet{ - &fs.CpusetGroupV2{}, - &fs.FreezerGroupV2{}, - &fs.CpuGroupV2{}, - &fs.MemoryGroupV2{}, - &fs.IOGroupV2{}, - &fs.PidsGroupV2{}, -} - func (m *UnifiedManager) Apply(pid int) error { var ( c = m.Cgroups @@ -159,19 +151,19 @@ func (m *UnifiedManager) Apply(pid int) return err } - paths := make(map[string]string) - for _, s := range unifiedSubsystems { - subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name()) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if cgroups.IsNotFound(err) { - continue - } - return err - } - paths[s.Name()] = subsystemPath + path, err := getSubsystemPath(m.Cgroups, "") + if err != nil { + return err + } + m.Paths = map[string]string{ + "pids": path, + "memory": path, + "io": path, + "cpu": path, + "devices": path, + "cpuset": path, + "freezer": path, } - m.Paths = paths return nil } @@ -195,7 +187,24 @@ func (m *UnifiedManager) GetPaths() map[ m.mu.Unlock() return paths } - +func (m *UnifiedManager) GetUnifiedPath() (string, error) { + unifiedPath := "" + m.mu.Lock() + defer m.mu.Unlock() + for k, v := range m.Paths { + if unifiedPath == "" { + unifiedPath = v + } else if v != unifiedPath { + return unifiedPath, + errors.Errorf("expected %q path to be unified path %q, got %q", k, unifiedPath, v) + } + } + if unifiedPath == "" { + // FIXME: unified path could be detected even when no controller is available + return unifiedPath, errors.New("cannot detect unified path") + } + return unifiedPath, nil +} func createCgroupsv2Path(path string) (Err error) { content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers") if err != nil { @@ -250,27 +259,24 @@ func joinCgroupsV2(c *configs.Cgroup, pi return createCgroupsv2Path(path) } -func (m *UnifiedManager) Freeze(state configs.FreezerState) error { - path, err := getSubsystemPath(m.Cgroups, "freezer") - if err != nil { - return err - } - prevState := m.Cgroups.Resources.Freezer - m.Cgroups.Resources.Freezer = state - freezer, err := unifiedSubsystems.Get("freezer") +func (m *UnifiedManager) fsManager() (cgroups.Manager, error) { + path, err := m.GetUnifiedPath() if err != nil { - return err + return nil, err } - err = freezer.Set(path, m.Cgroups) + return fs2.NewManager(m.Cgroups, path, false) +} + +func (m *UnifiedManager) Freeze(state configs.FreezerState) error { + fsMgr, err := m.fsManager() if err != nil { - m.Cgroups.Resources.Freezer = prevState return err } - return nil + return fsMgr.Freeze(state) } func (m *UnifiedManager) GetPids() ([]int, error) { - path, err := getSubsystemPath(m.Cgroups, "devices") + path, err := m.GetUnifiedPath() if err != nil { return nil, err } @@ -278,7 +284,7 @@ func (m *UnifiedManager) GetPids() ([]in } func (m *UnifiedManager) GetAllPids() ([]int, error) { - path, err := getSubsystemPath(m.Cgroups, "devices") + path, err := m.GetUnifiedPath() if err != nil { return nil, err } @@ -286,44 +292,21 @@ func (m *UnifiedManager) GetAllPids() ([ } func (m *UnifiedManager) GetStats() (*cgroups.Stats, error) { - m.mu.Lock() - defer m.mu.Unlock() - stats := cgroups.NewStats() - for name, path := range m.Paths { - sys, err := unifiedSubsystems.Get(name) - if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) { - continue - } - if err := sys.GetStats(path, stats); err != nil { - return nil, err - } + fsMgr, err := m.fsManager() + if err != nil { + return nil, err } - - return stats, nil + return fsMgr.GetStats() } func (m *UnifiedManager) Set(container *configs.Config) error { - // If Paths are set, then we are just joining cgroups paths - // and there is no need to set any values. - if m.Cgroups.Paths != nil { - return nil - } - for _, sys := range unifiedSubsystems { - // Get the subsystem path, but don't error out for not found cgroups. - path, err := getSubsystemPath(container.Cgroups, sys.Name()) - if err != nil && !cgroups.IsNotFound(err) { - return err - } - - if err := sys.Set(path, container.Cgroups); err != nil { - return err - } + fsMgr, err := m.fsManager() + if err != nil { + return err } + return fsMgr.Set(container) +} - if m.Paths["cpu"] != "" { - if err := fs.CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil { - return err - } - } - return nil +func (m *UnifiedManager) GetCgroups() (*configs.Cgroup, error) { + return m.Cgroups, nil }
  12. Download patch libcontainer/cgroups/fs/hugetlb.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/hugetlb.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/hugetlb.go 2020-01-22 16:19:15.000000000 +0000 @@ -8,6 +8,7 @@ import ( "strings" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -28,7 +29,7 @@ func (s *HugetlbGroup) Apply(d *cgroupDa func (s *HugetlbGroup) Set(path string, cgroup *configs.Cgroup) error { for _, hugetlb := range cgroup.Resources.HugetlbLimit { - if err := writeFile(path, strings.Join([]string{"hugetlb", hugetlb.Pagesize, "limit_in_bytes"}, "."), strconv.FormatUint(hugetlb.Limit, 10)); err != nil { + if err := fscommon.WriteFile(path, strings.Join([]string{"hugetlb", hugetlb.Pagesize, "limit_in_bytes"}, "."), strconv.FormatUint(hugetlb.Limit, 10)); err != nil { return err } } @@ -44,21 +45,21 @@ func (s *HugetlbGroup) GetStats(path str hugetlbStats := cgroups.HugetlbStats{} for _, pageSize := range HugePageSizes { usage := strings.Join([]string{"hugetlb", pageSize, "usage_in_bytes"}, ".") - value, err := getCgroupParamUint(path, usage) + value, err := fscommon.GetCgroupParamUint(path, usage) if err != nil { return fmt.Errorf("failed to parse %s - %v", usage, err) } hugetlbStats.Usage = value maxUsage := strings.Join([]string{"hugetlb", pageSize, "max_usage_in_bytes"}, ".") - value, err = getCgroupParamUint(path, maxUsage) + value, err = fscommon.GetCgroupParamUint(path, maxUsage) if err != nil { return fmt.Errorf("failed to parse %s - %v", maxUsage, err) } hugetlbStats.MaxUsage = value failcnt := strings.Join([]string{"hugetlb", pageSize, "failcnt"}, ".") - value, err = getCgroupParamUint(path, failcnt) + value, err = fscommon.GetCgroupParamUint(path, failcnt) if err != nil { return fmt.Errorf("failed to parse %s - %v", failcnt, err) }
  13. Download patch vendor/github.com/cilium/ebpf/asm/alu.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/alu.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/alu.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,149 @@ +package asm + +//go:generate stringer -output alu_string.go -type=Source,Endianness,ALUOp + +// Source of ALU / ALU64 / Branch operations +// +// msb lsb +// +----+-+---+ +// |op |S|cls| +// +----+-+---+ +type Source uint8 + +const sourceMask OpCode = 0x08 + +// Source bitmask +const ( + // InvalidSource is returned by getters when invoked + // on non ALU / branch OpCodes. + InvalidSource Source = 0xff + // ImmSource src is from constant + ImmSource Source = 0x00 + // RegSource src is from register + RegSource Source = 0x08 +) + +// The Endianness of a byte swap instruction. +type Endianness uint8 + +const endianMask = sourceMask + +// Endian flags +const ( + InvalidEndian Endianness = 0xff + // Convert to little endian + LE Endianness = 0x00 + // Convert to big endian + BE Endianness = 0x08 +) + +// ALUOp are ALU / ALU64 operations +// +// msb lsb +// +----+-+---+ +// |OP |s|cls| +// +----+-+---+ +type ALUOp uint8 + +const aluMask OpCode = 0xf0 + +const ( + // InvalidALUOp is returned by getters when invoked + // on non ALU OpCodes + InvalidALUOp ALUOp = 0xff + // Add - addition + Add ALUOp = 0x00 + // Sub - subtraction + Sub ALUOp = 0x10 + // Mul - multiplication + Mul ALUOp = 0x20 + // Div - division + Div ALUOp = 0x30 + // Or - bitwise or + Or ALUOp = 0x40 + // And - bitwise and + And ALUOp = 0x50 + // LSh - bitwise shift left + LSh ALUOp = 0x60 + // RSh - bitwise shift right + RSh ALUOp = 0x70 + // Neg - sign/unsign signing bit + Neg ALUOp = 0x80 + // Mod - modulo + Mod ALUOp = 0x90 + // Xor - bitwise xor + Xor ALUOp = 0xa0 + // Mov - move value from one place to another + Mov ALUOp = 0xb0 + // ArSh - arithmatic shift + ArSh ALUOp = 0xc0 + // Swap - endian conversions + Swap ALUOp = 0xd0 +) + +// HostTo converts from host to another endianness. +func HostTo(endian Endianness, dst Register, size Size) Instruction { + var imm int64 + switch size { + case Half: + imm = 16 + case Word: + imm = 32 + case DWord: + imm = 64 + default: + return Instruction{OpCode: InvalidOpCode} + } + + return Instruction{ + OpCode: OpCode(ALUClass).SetALUOp(Swap).SetSource(Source(endian)), + Dst: dst, + Constant: imm, + } +} + +// Op returns the OpCode for an ALU operation with a given source. +func (op ALUOp) Op(source Source) OpCode { + return OpCode(ALU64Class).SetALUOp(op).SetSource(source) +} + +// Reg emits `dst (op) src`. +func (op ALUOp) Reg(dst, src Register) Instruction { + return Instruction{ + OpCode: op.Op(RegSource), + Dst: dst, + Src: src, + } +} + +// Imm emits `dst (op) value`. +func (op ALUOp) Imm(dst Register, value int32) Instruction { + return Instruction{ + OpCode: op.Op(ImmSource), + Dst: dst, + Constant: int64(value), + } +} + +// Op32 returns the OpCode for a 32-bit ALU operation with a given source. +func (op ALUOp) Op32(source Source) OpCode { + return OpCode(ALUClass).SetALUOp(op).SetSource(source) +} + +// Reg32 emits `dst (op) src`, zeroing the upper 32 bit of dst. +func (op ALUOp) Reg32(dst, src Register) Instruction { + return Instruction{ + OpCode: op.Op32(RegSource), + Dst: dst, + Src: src, + } +} + +// Imm32 emits `dst (op) value`, zeroing the upper 32 bit of dst. +func (op ALUOp) Imm32(dst Register, value int32) Instruction { + return Instruction{ + OpCode: op.Op32(ImmSource), + Dst: dst, + Constant: int64(value), + } +}
  14. Download patch libcontainer/cgroups/fs/memory_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/memory_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/memory_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type MemoryGroupV2 struct { -} - -func (s *MemoryGroupV2) Name() string { - return "memory" -} - -func (s *MemoryGroupV2) Apply(d *cgroupData) (err error) { - path, err := d.path("memory") - if err != nil && !cgroups.IsNotFound(err) { - return err - } else if path == "" { - return nil - } - if memoryAssigned(d.config) { - if _, err := os.Stat(path); os.IsNotExist(err) { - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - // Only enable kernel memory accouting when this cgroup - // is created by libcontainer, otherwise we might get - // error when people use `cgroupsPath` to join an existed - // cgroup whose kernel memory is not initialized. - if err := EnableKernelMemoryAccounting(path); err != nil { - return err - } - } - } - defer func() { - if err != nil { - os.RemoveAll(path) - } - }() - - // We need to join memory cgroup after set memory limits, because - // kmem.limit_in_bytes can only be set when the cgroup is empty. - _, err = d.join("memory") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func setMemoryAndSwapCgroups(path string, cgroup *configs.Cgroup) error { - if cgroup.Resources.MemorySwap != 0 { - if err := writeFile(path, "memory.swap.max", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { - return err - } - } - if cgroup.Resources.Memory != 0 { - if err := writeFile(path, "memory.max", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { - return err - } - } - return nil -} - -func (s *MemoryGroupV2) Set(path string, cgroup *configs.Cgroup) error { - - if err := setMemoryAndSwapCgroups(path, cgroup); err != nil { - return err - } - - if cgroup.Resources.KernelMemory != 0 { - if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil { - return err - } - } - - if cgroup.Resources.MemoryReservation != 0 { - if err := writeFile(path, "memory.high", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil { - return err - } - } - - return nil -} - -func (s *MemoryGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("memory")) -} - -func (s *MemoryGroupV2) GetStats(path string, stats *cgroups.Stats) error { - // Set stats from memory.stat. - statsFile, err := os.Open(filepath.Join(path, "memory.stat")) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - defer statsFile.Close() - - sc := bufio.NewScanner(statsFile) - for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) - if err != nil { - return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err) - } - stats.MemoryStats.Stats[t] = v - } - stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"] - - memoryUsage, err := getMemoryDataV2(path, "") - if err != nil { - return err - } - stats.MemoryStats.Usage = memoryUsage - swapUsage, err := getMemoryDataV2(path, "swap") - if err != nil { - return err - } - stats.MemoryStats.SwapUsage = swapUsage - - stats.MemoryStats.UseHierarchy = true - return nil -} - -func getMemoryDataV2(path, name string) (cgroups.MemoryData, error) { - memoryData := cgroups.MemoryData{} - - moduleName := "memory" - if name != "" { - moduleName = strings.Join([]string{"memory", name}, ".") - } - usage := strings.Join([]string{moduleName, "current"}, ".") - limit := strings.Join([]string{moduleName, "max"}, ".") - - value, err := getCgroupParamUint(path, usage) - if err != nil { - if moduleName != "memory" && os.IsNotExist(err) { - return cgroups.MemoryData{}, nil - } - return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err) - } - memoryData.Usage = value - - value, err = getCgroupParamUint(path, limit) - if err != nil { - if moduleName != "memory" && os.IsNotExist(err) { - return cgroups.MemoryData{}, nil - } - return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", limit, err) - } - memoryData.Limit = value - - return memoryData, nil -}
  15. Download patch libcontainer/cgroups/fs/io_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/io_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/io_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,191 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type IOGroupV2 struct { -} - -func (s *IOGroupV2) Name() string { - return "blkio" -} - -func (s *IOGroupV2) Apply(d *cgroupData) error { - _, err := d.join("blkio") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func (s *IOGroupV2) Set(path string, cgroup *configs.Cgroup) error { - cgroupsv2 := cgroups.IsCgroup2UnifiedMode() - - if cgroup.Resources.BlkioWeight != 0 { - filename := "blkio.weight" - if cgroupsv2 { - filename = "io.bfq.weight" - } - if err := writeFile(path, filename, strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { - return err - } - } - - if cgroup.Resources.BlkioLeafWeight != 0 { - if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil { - return err - } - } - for _, wd := range cgroup.Resources.BlkioWeightDevice { - if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil { - return err - } - if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil { - return err - } - } - for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice { - if cgroupsv2 { - if err := writeFile(path, "io.max", td.StringName("rbps")); err != nil { - return err - } - } else { - if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil { - return err - } - } - } - for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice { - if cgroupsv2 { - if err := writeFile(path, "io.max", td.StringName("wbps")); err != nil { - return err - } - } else { - if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil { - return err - } - } - } - for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice { - if cgroupsv2 { - if err := writeFile(path, "io.max", td.StringName("riops")); err != nil { - return err - } - } else { - if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil { - return err - } - } - } - for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice { - if cgroupsv2 { - if err := writeFile(path, "io.max", td.StringName("wiops")); err != nil { - return err - } - } else { - if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil { - return err - } - } - } - - return nil -} - -func (s *IOGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("blkio")) -} - -func readCgroup2MapFile(path string, name string) (map[string][]string, error) { - ret := map[string][]string{} - p := filepath.Join("/sys/fs/cgroup", path, name) - f, err := os.Open(p) - if err != nil { - if os.IsNotExist(err) { - return ret, nil - } - return nil, err - } - defer f.Close() - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := scanner.Text() - parts := strings.Fields(line) - if len(parts) < 2 { - continue - } - ret[parts[0]] = parts[1:] - } - if err := scanner.Err(); err != nil { - return nil, err - } - return ret, nil -} - -func (s *IOGroupV2) getCgroupV2Stats(path string, stats *cgroups.Stats) error { - // more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt - var ioServiceBytesRecursive []cgroups.BlkioStatEntry - values, err := readCgroup2MapFile(path, "io.stat") - if err != nil { - return err - } - for k, v := range values { - d := strings.Split(k, ":") - if len(d) != 2 { - continue - } - minor, err := strconv.ParseUint(d[0], 10, 0) - if err != nil { - return err - } - major, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - for _, item := range v { - d := strings.Split(item, "=") - if len(d) != 2 { - continue - } - op := d[0] - - // Accommodate the cgroup v1 naming - switch op { - case "rbytes": - op = "read" - case "wbytes": - op = "write" - } - - value, err := strconv.ParseUint(d[1], 10, 0) - if err != nil { - return err - } - - entry := cgroups.BlkioStatEntry{ - Op: op, - Major: major, - Minor: minor, - Value: value, - } - ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) - } - } - stats.BlkioStats = cgroups.BlkioStats{IoServiceBytesRecursive: ioServiceBytesRecursive} - return nil -} - -func (s *IOGroupV2) GetStats(path string, stats *cgroups.Stats) error { - return s.getCgroupV2Stats(path, stats) -}
  16. Download patch libcontainer/cgroups/fs/freezer.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/freezer.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/freezer.go 2020-01-22 16:19:15.000000000 +0000 @@ -8,6 +8,7 @@ import ( "time" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -34,11 +35,11 @@ func (s *FreezerGroup) Set(path string, // state, let's write again this state, hoping it's going to be properly // set this time. Otherwise, this loop could run infinitely, waiting for // a state change that would never happen. - if err := writeFile(path, "freezer.state", string(cgroup.Resources.Freezer)); err != nil { + if err := fscommon.WriteFile(path, "freezer.state", string(cgroup.Resources.Freezer)); err != nil { return err } - state, err := readFile(path, "freezer.state") + state, err := fscommon.ReadFile(path, "freezer.state") if err != nil { return err }
  17. Download patch debian/runc.docs

    --- 1.0.0~rc9+dfsg1-1/debian/runc.docs 2018-06-15 11:50:30.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/runc.docs 2019-01-30 21:27:05.000000000 +0000 @@ -1,2 +1,2 @@ -README* NOTICE +README*
  18. Download patch debian/rules

    --- 1.0.0~rc9+dfsg1-1/debian/rules 2019-09-09 14:31:41.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/rules 2019-09-18 08:47:04.000000000 +0000 @@ -4,43 +4,23 @@ #export DH_VERBOSE=1 export DH_GOPKG := github.com/opencontainers/runc -export DH_GOLANG_INSTALL_EXTRA := libcontainer/seccomp/fixtures - -include /usr/share/dpkg/pkg-info.mk - +export DH_GOLANG_INSTALL_EXTRA := libcontainer/seccomp/fixtures libcontainer/criurpc TAGS=apparmor seccomp selinux ambient -LDFLAGS := -X main.version=$(DEB_VERSION_UPSTREAM) -X main.gitCommit=$(DEB_VERSION) %: dh $@ --buildsystem=golang --with=golang --builddirectory=_build -override_dh_clean: - dh_clean - ## Remove Files-Excluded (when built from checkout or non-DFSG tarball): - $(RM) -rv `perl -0nE 'say $$1 if m{^Files\-Excluded\:\s*(.*?)(?:\n\n|Files:|Comment:)}sm;' debian/copyright` - override_dh_auto_configure: cd man && ./md2man-all.sh dh_auto_configure -# ## Sub-vendor "github.com/docker/docker/pkg" (system lib takes preference over bundled one): -# mkdir -p _build/src/$(DH_GOPKG)/vendor/github.com/docker/docker -# if [ -d "/usr/share/gocode/src/github.com/docker/docker/pkg" ]; then \ -# cp -vr /usr/share/gocode/src/github.com/docker/docker/pkg _build/src/$(DH_GOPKG)/vendor/github.com/docker/docker/ ;\ -# elif [ -d "vendor/github.com/docker/docker/pkg" ]; then \ -# cp -vr vendor/github.com/docker/docker/pkg _build/src/$(DH_GOPKG)/vendor/github.com/docker/docker/ ;\ -# fi ## Remove extra license files: $(RM) -v \ _build/src/$(DH_GOPKG)/vendor/github.com/docker/docker/*/*/LICENSE* \ ; -# ln -svrf vendor/github.com/opencontainers/specs _build/src/github.com/opencontainers/ override_dh_auto_build: - dh_auto_build -- -tags "$(TAGS)" -ldflags "$(LDFLAGS)" + dh_auto_build -- -tags "$(TAGS)" override_dh_auto_test: DH_GOLANG_EXCLUDES="libcontainer/integration" \ dh_auto_test -- -tags "$(TAGS)" - -override_dh_dwz: - :
  19. Download patch libcontainer/cgroups/fs/devices.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/devices.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/devices.go 2020-01-22 16:19:15.000000000 +0000 @@ -4,6 +4,7 @@ package fs import ( "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" ) @@ -37,7 +38,7 @@ func (s *DevicesGroup) Set(path string, if dev.Allow { file = "devices.allow" } - if err := writeFile(path, file, dev.CgroupString()); err != nil { + if err := fscommon.WriteFile(path, file, dev.CgroupString()); err != nil { return err } } @@ -45,25 +46,25 @@ func (s *DevicesGroup) Set(path string, } if cgroup.Resources.AllowAllDevices != nil { if *cgroup.Resources.AllowAllDevices == false { - if err := writeFile(path, "devices.deny", "a"); err != nil { + if err := fscommon.WriteFile(path, "devices.deny", "a"); err != nil { return err } for _, dev := range cgroup.Resources.AllowedDevices { - if err := writeFile(path, "devices.allow", dev.CgroupString()); err != nil { + if err := fscommon.WriteFile(path, "devices.allow", dev.CgroupString()); err != nil { return err } } return nil } - if err := writeFile(path, "devices.allow", "a"); err != nil { + if err := fscommon.WriteFile(path, "devices.allow", "a"); err != nil { return err } } for _, dev := range cgroup.Resources.DeniedDevices { - if err := writeFile(path, "devices.deny", dev.CgroupString()); err != nil { + if err := fscommon.WriteFile(path, "devices.deny", dev.CgroupString()); err != nil { return err } }
  20. Download patch vendor/github.com/cilium/ebpf/collection.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/collection.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/collection.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,148 @@ +package ebpf + +import ( + "github.com/cilium/ebpf/asm" + "github.com/pkg/errors" +) + +// CollectionOptions control loading a collection into the kernel. +type CollectionOptions struct { + Programs ProgramOptions +} + +// CollectionSpec describes a collection. +type CollectionSpec struct { + Maps map[string]*MapSpec + Programs map[string]*ProgramSpec +} + +// Copy returns a recursive copy of the spec. +func (cs *CollectionSpec) Copy() *CollectionSpec { + if cs == nil { + return nil + } + + cpy := CollectionSpec{ + Maps: make(map[string]*MapSpec, len(cs.Maps)), + Programs: make(map[string]*ProgramSpec, len(cs.Programs)), + } + + for name, spec := range cs.Maps { + cpy.Maps[name] = spec.Copy() + } + + for name, spec := range cs.Programs { + cpy.Programs[name] = spec.Copy() + } + + return &cpy +} + +// Collection is a collection of Programs and Maps associated +// with their symbols +type Collection struct { + Programs map[string]*Program + Maps map[string]*Map +} + +// NewCollection creates a Collection from a specification. +// +// Only maps referenced by at least one of the programs are initialized. +func NewCollection(spec *CollectionSpec) (*Collection, error) { + return NewCollectionWithOptions(spec, CollectionOptions{}) +} + +// NewCollectionWithOptions creates a Collection from a specification. +// +// Only maps referenced by at least one of the programs are initialized. +func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) { + maps := make(map[string]*Map) + for mapName, mapSpec := range spec.Maps { + m, err := NewMap(mapSpec) + if err != nil { + return nil, errors.Wrapf(err, "map %s", mapName) + } + maps[mapName] = m + } + + progs := make(map[string]*Program) + for progName, origProgSpec := range spec.Programs { + progSpec := origProgSpec.Copy() + + // Rewrite any reference to a valid map. + for i := range progSpec.Instructions { + var ( + ins = &progSpec.Instructions[i] + m = maps[ins.Reference] + ) + + if ins.Reference == "" || m == nil { + continue + } + + if ins.Src == asm.R1 { + // Don't overwrite maps already rewritten, users can + // rewrite programs in the spec themselves + continue + } + + if err := ins.RewriteMapPtr(m.FD()); err != nil { + return nil, errors.Wrapf(err, "progam %s: map %s", progName, ins.Reference) + } + } + + prog, err := NewProgramWithOptions(progSpec, opts.Programs) + if err != nil { + return nil, errors.Wrapf(err, "program %s", progName) + } + progs[progName] = prog + } + + return &Collection{ + progs, + maps, + }, nil +} + +// LoadCollection parses an object file and converts it to a collection. +func LoadCollection(file string) (*Collection, error) { + spec, err := LoadCollectionSpec(file) + if err != nil { + return nil, err + } + return NewCollection(spec) +} + +// Close frees all maps and programs associated with the collection. +// +// The collection mustn't be used afterwards. +func (coll *Collection) Close() { + for _, prog := range coll.Programs { + prog.Close() + } + for _, m := range coll.Maps { + m.Close() + } +} + +// DetachMap removes the named map from the Collection. +// +// This means that a later call to Close() will not affect this map. +// +// Returns nil if no map of that name exists. +func (coll *Collection) DetachMap(name string) *Map { + m := coll.Maps[name] + delete(coll.Maps, name) + return m +} + +// DetachProgram removes the named program from the Collection. +// +// This means that a later call to Close() will not affect this program. +// +// Returns nil if no program of that name exists. +func (coll *Collection) DetachProgram(name string) *Program { + p := coll.Programs[name] + delete(coll.Programs, name) + return p +}
  21. Download patch libcontainer/specconv/spec_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/specconv/spec_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/specconv/spec_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -43,7 +43,8 @@ var mountPropagationMapping = map[string "": 0, } -var allowedDevices = []*configs.Device{ +// AllowedDevices is exposed for devicefilter_test.go +var AllowedDevices = []*configs.Device{ // allow mknod for any device { Type: 'c', @@ -195,7 +196,7 @@ func CreateLibcontainerConfig(opts *Crea if err := createDevices(spec, config); err != nil { return nil, err } - c, err := createCgroupConfig(opts) + c, err := CreateCgroupConfig(opts) if err != nil { return nil, err } @@ -296,7 +297,7 @@ func createLibcontainerMount(cwd string, } } -func createCgroupConfig(opts *CreateOpts) (*configs.Cgroup, error) { +func CreateCgroupConfig(opts *CreateOpts) (*configs.Cgroup, error) { var ( myCgroupPath string @@ -341,7 +342,7 @@ func createCgroupConfig(opts *CreateOpts // In rootless containers, any attempt to make cgroup changes is likely to fail. // libcontainer will validate this but ignores the error. - c.Resources.AllowedDevices = allowedDevices + c.Resources.AllowedDevices = AllowedDevices if spec.Linux != nil { r := spec.Linux.Resources if r == nil { @@ -495,7 +496,7 @@ func createCgroupConfig(opts *CreateOpts } } // append the default allowed devices to the end of the list - c.Resources.Devices = append(c.Resources.Devices, allowedDevices...) + c.Resources.Devices = append(c.Resources.Devices, AllowedDevices...) return c, nil }
  22. Download patch debian/compat

    --- 1.0.0~rc9+dfsg1-1/debian/compat 2019-09-09 13:47:31.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/compat 2019-09-18 08:47:04.000000000 +0000 @@ -1 +1 @@ -12 +10
  23. Download patch vendor/github.com/cilium/ebpf/asm/instruction.go
  24. Download patch vendor/github.com/cilium/ebpf/doc.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/doc.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/doc.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,17 @@ +// Package ebpf is a toolkit for working with eBPF programs. +// +// eBPF programs are small snippets of code which are executed directly +// in a VM in the Linux kernel, which makes them very fast and flexible. +// Many Linux subsystems now accept eBPF programs. This makes it possible +// to implement highly application specific logic inside the kernel, +// without having to modify the actual kernel itself. +// +// This package is designed for long-running processes which +// want to use eBPF to implement part of their application logic. It has no +// run-time dependencies outside of the library and the Linux kernel itself. +// eBPF code should be compiled ahead of time using clang, and shipped with +// your application as any other resource. +// +// This package doesn't include code required to attach eBPF to Linux +// subsystems, since this varies per subsystem. +package ebpf
  25. Download patch libcontainer/cgroups/fs2/pids.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/pids.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/pids.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,90 @@ +// +build linux + +package fs2 + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func setPids(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.Resources.PidsLimit != 0 { + // "max" is the fallback value. + limit := "max" + + if cgroup.Resources.PidsLimit > 0 { + limit = strconv.FormatInt(cgroup.Resources.PidsLimit, 10) + } + + if err := fscommon.WriteFile(dirPath, "pids.max", limit); err != nil { + return err + } + } + + return nil +} + +func isNOTSUP(err error) bool { + switch err := err.(type) { + case *os.PathError: + return err.Err == unix.ENOTSUP + default: + return false + } +} + +func statPidsWithoutController(dirPath string, stats *cgroups.Stats) error { + // if the controller is not enabled, let's read PIDS from cgroups.procs + // (or threads if cgroup.threads is enabled) + contents, err := ioutil.ReadFile(filepath.Join(dirPath, "cgroup.procs")) + if err != nil && isNOTSUP(err) { + contents, err = ioutil.ReadFile(filepath.Join(dirPath, "cgroup.threads")) + } + if err != nil { + return err + } + pids := make(map[string]string) + for _, i := range strings.Split(string(contents), "\n") { + if i != "" { + pids[i] = i + } + } + stats.PidsStats.Current = uint64(len(pids)) + stats.PidsStats.Limit = 0 + return nil +} + +func statPids(dirPath string, stats *cgroups.Stats) error { + current, err := fscommon.GetCgroupParamUint(dirPath, "pids.current") + if err != nil { + return errors.Wrap(err, "failed to parse pids.current") + } + + maxString, err := fscommon.GetCgroupParamString(dirPath, "pids.max") + if err != nil { + return errors.Wrap(err, "failed to parse pids.max") + } + + // Default if pids.max == "max" is 0 -- which represents "no limit". + var max uint64 + if maxString != "max" { + max, err = fscommon.ParseUint(maxString, 10, 64) + if err != nil { + return errors.Wrapf(err, "failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q", + maxString, filepath.Join(dirPath, "pids.max")) + } + } + + stats.PidsStats.Current = current + stats.PidsStats.Limit = max + return nil +}
  26. Download patch libcontainer/cgroups/fs/freezer_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/freezer_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/freezer_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -// +build linux - -package fs - -import ( - "fmt" - "strings" - "time" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type FreezerGroupV2 struct { -} - -func (s *FreezerGroupV2) Name() string { - return "freezer" -} - -func (s *FreezerGroupV2) Apply(d *cgroupData) error { - _, err := d.join("freezer") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return nil -} - -func (s *FreezerGroupV2) Set(path string, cgroup *configs.Cgroup) error { - var desiredState string - filename := "cgroup.freeze" - if cgroup.Resources.Freezer == configs.Frozen { - desiredState = "1" - } else { - desiredState = "0" - } - - switch cgroup.Resources.Freezer { - case configs.Frozen, configs.Thawed: - for { - // In case this loop does not exit because it doesn't get the expected - // state, let's write again this state, hoping it's going to be properly - // set this time. Otherwise, this loop could run infinitely, waiting for - // a state change that would never happen. - if err := writeFile(path, filename, desiredState); err != nil { - return err - } - - state, err := readFile(path, filename) - if err != nil { - return err - } - if strings.TrimSpace(state) == desiredState { - break - } - - time.Sleep(1 * time.Millisecond) - } - case configs.Undefined: - return nil - default: - return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer)) - } - - return nil -} - -func (s *FreezerGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("freezer")) -} - -func (s *FreezerGroupV2) GetStats(path string, stats *cgroups.Stats) error { - return nil -}
  27. Download patch libcontainer/cgroups/ebpf/devicefilter/devicefilter_test.go
  28. Download patch debian/control

    --- 1.0.0~rc9+dfsg1-1/debian/control 2019-10-09 08:09:07.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/control 2020-02-17 20:05:23.000000000 +0000 @@ -1,44 +1,30 @@ Source: runc Section: devel Priority: optional -Standards-Version: 4.4.0 -Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> -Uploaders: Alexandre Viau <aviau@debian.org>, Dmitry Smirnov <onlyjob@debian.org>, +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> +Uploaders: Alexandre Viau <aviau@debian.org>, + Dmitry Smirnov <onlyjob@debian.org>, Tim Potter <tpot@hpe.com> -Build-Depends: debhelper (>= 12~), +Build-Depends: debhelper (>= 11~), dh-golang, go-md2man, golang-any, - golang-dbus-dev, - golang-github-containerd-console-dev, - golang-github-coreos-go-systemd-dev (>= 20~), - golang-github-cyphar-filepath-securejoin-dev, - golang-github-docker-go-units-dev (>= 0.4.0~), - golang-github-mrunalp-fileutils-dev, - golang-github-opencontainers-selinux-dev (>= 1.3.0~), - golang-github-opencontainers-specs-dev (>= 1.0.1-5~), - golang-github-pkg-errors-dev, - golang-github-seccomp-libseccomp-golang-dev (>= 0.9.1~), - golang-github-sirupsen-logrus-dev (>= 1.0.2~), - golang-github-urfave-cli-dev, - golang-github-vishvananda-netlink-dev, - golang-gocapability-dev (>= 0.0+git20180916~), - golang-goprotobuf-dev, libapparmor-dev, + libseccomp-dev, + pkg-config, protobuf-compiler +Standards-Version: 4.1.4 Homepage: https://github.com/opencontainers/runc Vcs-Git: https://salsa.debian.org/go-team/packages/runc.git Vcs-Browser: https://salsa.debian.org/go-team/packages/runc XS-Go-Import-Path: github.com/opencontainers/runc -Testsuite: autopkgtest-pkg-go Package: runc Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends} Breaks: docker.io (<= 1.13.1~ds1-2) Built-Using: ${misc:Built-Using} -Recommends: ${misc:Recommends} - ,criu Description: Open Container Project - runtime "runc" is a command line client for running applications packaged according to the Open Container Format (OCF) and is a compliant implementation of @@ -46,19 +32,7 @@ Description: Open Container Project - ru Package: golang-github-opencontainers-runc-dev Architecture: all -Depends: ${misc:Depends}, - golang-dbus-dev, - golang-github-coreos-go-systemd-dev (>= 20~), - golang-github-cyphar-filepath-securejoin-dev, - golang-github-docker-go-units-dev (>= 0.4.0~), - golang-github-opencontainers-selinux-dev (>= 1.3.0~), - golang-github-opencontainers-specs-dev (>= 1.0.1-5~), - golang-github-seccomp-libseccomp-golang-dev (>= 0.9.1~), - golang-github-sirupsen-logrus-dev (>= 1.0.2~), - golang-github-urfave-cli-dev, - golang-github-vishvananda-netlink-dev, - golang-gocapability-dev (>= 0.0+git20180916~), - golang-goprotobuf-dev +Depends: ${misc:Depends} Description: Open Container Project - development files "runc" is a command line client for running applications packaged according to the Open Container Format (OCF) and is a compliant implementation of
  29. Download patch .travis.yml

    --- 1.0.0~rc9+dfsg1-1/.travis.yml 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/.travis.yml 2020-01-22 16:19:15.000000000 +0000 @@ -1,4 +1,4 @@ -dist: xenial +dist: bionic language: go go: - 1.11.x @@ -13,6 +13,20 @@ matrix: script: - make BUILDTAGS="${BUILDTAGS}" all - sudo PATH="$PATH" make localintegration RUNC_USE_SYSTEMD=1 + - go: 1.12.x + env: + - VIRTUALBOX_VERSION=6.0 + - VAGRANT_VERSION=2.2.6 + - FEDORA_VERSION=31 + before_install: + - cat /proc/cpuinfo + - wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - && sudo sh -c "echo deb https://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib >> /etc/apt/sources.list" && sudo apt-get update && sudo apt-get install -yq build-essential gcc make linux-headers-$(uname -r) virtualbox-${VIRTUALBOX_VERSION} && sudo usermod -aG vboxusers $(whoami) + - wget https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}_$(uname -m).deb && sudo dpkg -i vagrant_${VAGRANT_VERSION}_$(uname -m).deb + - vagrant init bento/fedora-${FEDORA_VERSION} && vagrant up && mkdir -p ~/.ssh && vagrant ssh-config >> ~/.ssh/config + - ssh default sudo dnf install -y podman + script: + - ssh default sudo podman build -t test /vagrant + - ssh default sudo podman run --privileged --cgroupns=private test make localunittest allow_failures: - go: tip
  30. Download patch libcontainer/integration/checkpoint_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/integration/checkpoint_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/integration/checkpoint_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -11,6 +11,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "golang.org/x/sys/unix" @@ -41,6 +42,7 @@ func showFile(t *testing.T, fname string } func TestUsernsCheckpoint(t *testing.T) { + t.Skip("Ubuntu kernel is broken to run criu (#2196, #2198)") if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) { t.Skip("userns is unsupported") } @@ -52,6 +54,7 @@ func TestUsernsCheckpoint(t *testing.T) } func TestCheckpoint(t *testing.T) { + t.Skip("Ubuntu kernel is broken to run criu (#2196, #2198)") testCheckpoint(t, false) } @@ -59,6 +62,10 @@ func testCheckpoint(t *testing.T, userns if testing.Short() { return } + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } + root, err := newTestRoot() if err != nil { t.Fatal(err)
  31. Download patch libcontainer/cgroups/fscommon/utils_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fscommon/utils_test.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fscommon/utils_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,97 @@ +// +build linux + +package fscommon + +import ( + "io/ioutil" + "math" + "os" + "path/filepath" + "strconv" + "testing" +) + +const ( + cgroupFile = "cgroup.file" + floatValue = 2048.0 + floatString = "2048" +) + +func TestGetCgroupParamsInt(t *testing.T) { + // Setup tempdir. + tempDir, err := ioutil.TempDir("", "cgroup_utils_test") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tempDir) + tempFile := filepath.Join(tempDir, cgroupFile) + + // Success. + err = ioutil.WriteFile(tempFile, []byte(floatString), 0755) + if err != nil { + t.Fatal(err) + } + value, err := GetCgroupParamUint(tempDir, cgroupFile) + if err != nil { + t.Fatal(err) + } else if value != floatValue { + t.Fatalf("Expected %d to equal %f", value, floatValue) + } + + // Success with new line. + err = ioutil.WriteFile(tempFile, []byte(floatString+"\n"), 0755) + if err != nil { + t.Fatal(err) + } + value, err = GetCgroupParamUint(tempDir, cgroupFile) + if err != nil { + t.Fatal(err) + } else if value != floatValue { + t.Fatalf("Expected %d to equal %f", value, floatValue) + } + + // Success with negative values + err = ioutil.WriteFile(tempFile, []byte("-12345"), 0755) + if err != nil { + t.Fatal(err) + } + value, err = GetCgroupParamUint(tempDir, cgroupFile) + if err != nil { + t.Fatal(err) + } else if value != 0 { + t.Fatalf("Expected %d to equal %d", value, 0) + } + + // Success with negative values lesser than min int64 + s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) + err = ioutil.WriteFile(tempFile, []byte(s), 0755) + if err != nil { + t.Fatal(err) + } + value, err = GetCgroupParamUint(tempDir, cgroupFile) + if err != nil { + t.Fatal(err) + } else if value != 0 { + t.Fatalf("Expected %d to equal %d", value, 0) + } + + // Not a float. + err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0755) + if err != nil { + t.Fatal(err) + } + _, err = GetCgroupParamUint(tempDir, cgroupFile) + if err == nil { + t.Fatal("Expecting error, got none") + } + + // Unknown file. + err = os.Remove(tempFile) + if err != nil { + t.Fatal(err) + } + _, err = GetCgroupParamUint(tempDir, cgroupFile) + if err == nil { + t.Fatal("Expecting error, got none") + } +}
  32. Download patch libcontainer/cgroups/fs2/io.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/io.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/io.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,124 @@ +// +build linux + +package fs2 + +import ( + "bufio" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" +) + +func setIo(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.Resources.BlkioWeight != 0 { + filename := "io.bfq.weight" + if err := fscommon.WriteFile(dirPath, filename, strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil { + return err + } + } + + for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice { + if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("rbps")); err != nil { + return err + } + } + for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice { + if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wbps")); err != nil { + return err + } + } + for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice { + if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("riops")); err != nil { + return err + } + } + for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice { + if err := fscommon.WriteFile(dirPath, "io.max", td.StringName("wiops")); err != nil { + return err + } + } + + return nil +} + +func readCgroup2MapFile(dirPath string, name string) (map[string][]string, error) { + ret := map[string][]string{} + p := filepath.Join(dirPath, name) + f, err := os.Open(p) + if err != nil { + return nil, err + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + parts := strings.Fields(line) + if len(parts) < 2 { + continue + } + ret[parts[0]] = parts[1:] + } + if err := scanner.Err(); err != nil { + return nil, err + } + return ret, nil +} + +func statIo(dirPath string, stats *cgroups.Stats) error { + // more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt + var ioServiceBytesRecursive []cgroups.BlkioStatEntry + values, err := readCgroup2MapFile(dirPath, "io.stat") + if err != nil { + return err + } + for k, v := range values { + d := strings.Split(k, ":") + if len(d) != 2 { + continue + } + minor, err := strconv.ParseUint(d[0], 10, 0) + if err != nil { + return err + } + major, err := strconv.ParseUint(d[1], 10, 0) + if err != nil { + return err + } + + for _, item := range v { + d := strings.Split(item, "=") + if len(d) != 2 { + continue + } + op := d[0] + + // Accommodate the cgroup v1 naming + switch op { + case "rbytes": + op = "read" + case "wbytes": + op = "write" + } + + value, err := strconv.ParseUint(d[1], 10, 0) + if err != nil { + return err + } + + entry := cgroups.BlkioStatEntry{ + Op: op, + Major: major, + Minor: minor, + Value: value, + } + ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry) + } + } + stats.BlkioStats = cgroups.BlkioStats{IoServiceBytesRecursive: ioServiceBytesRecursive} + return nil +}
  33. Download patch libcontainer/cgroups/fs/util_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/util_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/util_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -13,6 +13,7 @@ import ( "path/filepath" "testing" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -59,7 +60,7 @@ func (c *cgroupTestUtil) cleanup() { // Write the specified contents on the mock of the specified cgroup files. func (c *cgroupTestUtil) writeFileContents(fileContents map[string]string) { for file, contents := range fileContents { - err := writeFile(c.CgroupPath, file, contents) + err := fscommon.WriteFile(c.CgroupPath, file, contents) if err != nil { c.t.Fatal(err) }
  34. Download patch libcontainer/cgroups/fs/cpu.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpu.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpu.go 2020-01-22 16:19:15.000000000 +0000 @@ -9,6 +9,7 @@ import ( "strconv" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -51,12 +52,12 @@ func (s *CpuGroup) ApplyDir(path string, func (s *CpuGroup) SetRtSched(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.CpuRtPeriod != 0 { - if err := writeFile(path, "cpu.rt_period_us", strconv.FormatUint(cgroup.Resources.CpuRtPeriod, 10)); err != nil { + if err := fscommon.WriteFile(path, "cpu.rt_period_us", strconv.FormatUint(cgroup.Resources.CpuRtPeriod, 10)); err != nil { return err } } if cgroup.Resources.CpuRtRuntime != 0 { - if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil { + if err := fscommon.WriteFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil { return err } } @@ -65,17 +66,17 @@ func (s *CpuGroup) SetRtSched(path strin func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.CpuShares != 0 { - if err := writeFile(path, "cpu.shares", strconv.FormatUint(cgroup.Resources.CpuShares, 10)); err != nil { + if err := fscommon.WriteFile(path, "cpu.shares", strconv.FormatUint(cgroup.Resources.CpuShares, 10)); err != nil { return err } } if cgroup.Resources.CpuPeriod != 0 { - if err := writeFile(path, "cpu.cfs_period_us", strconv.FormatUint(cgroup.Resources.CpuPeriod, 10)); err != nil { + if err := fscommon.WriteFile(path, "cpu.cfs_period_us", strconv.FormatUint(cgroup.Resources.CpuPeriod, 10)); err != nil { return err } } if cgroup.Resources.CpuQuota != 0 { - if err := writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil { + if err := fscommon.WriteFile(path, "cpu.cfs_quota_us", strconv.FormatInt(cgroup.Resources.CpuQuota, 10)); err != nil { return err } } @@ -98,7 +99,7 @@ func (s *CpuGroup) GetStats(path string, sc := bufio.NewScanner(f) for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) + t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text()) if err != nil { return err }
  35. Download patch types/events.go

    --- 1.0.0~rc9+dfsg1-1/types/events.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/types/events.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,130 @@ +package types + +// Event struct for encoding the event data to json. +type Event struct { + Type string `json:"type"` + ID string `json:"id"` + Data interface{} `json:"data,omitempty"` +} + +// stats is the runc specific stats structure for stability when encoding and decoding stats. +type Stats struct { + CPU Cpu `json:"cpu"` + Memory Memory `json:"memory"` + Pids Pids `json:"pids"` + Blkio Blkio `json:"blkio"` + Hugetlb map[string]Hugetlb `json:"hugetlb"` + IntelRdt IntelRdt `json:"intel_rdt"` + NetworkInterfaces []*NetworkInterface `json:"network_interfaces"` +} + +type Hugetlb struct { + Usage uint64 `json:"usage,omitempty"` + Max uint64 `json:"max,omitempty"` + Failcnt uint64 `json:"failcnt"` +} + +type BlkioEntry struct { + Major uint64 `json:"major,omitempty"` + Minor uint64 `json:"minor,omitempty"` + Op string `json:"op,omitempty"` + Value uint64 `json:"value,omitempty"` +} + +type Blkio struct { + IoServiceBytesRecursive []BlkioEntry `json:"ioServiceBytesRecursive,omitempty"` + IoServicedRecursive []BlkioEntry `json:"ioServicedRecursive,omitempty"` + IoQueuedRecursive []BlkioEntry `json:"ioQueueRecursive,omitempty"` + IoServiceTimeRecursive []BlkioEntry `json:"ioServiceTimeRecursive,omitempty"` + IoWaitTimeRecursive []BlkioEntry `json:"ioWaitTimeRecursive,omitempty"` + IoMergedRecursive []BlkioEntry `json:"ioMergedRecursive,omitempty"` + IoTimeRecursive []BlkioEntry `json:"ioTimeRecursive,omitempty"` + SectorsRecursive []BlkioEntry `json:"sectorsRecursive,omitempty"` +} + +type Pids struct { + Current uint64 `json:"current,omitempty"` + Limit uint64 `json:"limit,omitempty"` +} + +type Throttling struct { + Periods uint64 `json:"periods,omitempty"` + ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"` + ThrottledTime uint64 `json:"throttledTime,omitempty"` +} + +type CpuUsage struct { + // Units: nanoseconds. + Total uint64 `json:"total,omitempty"` + Percpu []uint64 `json:"percpu,omitempty"` + Kernel uint64 `json:"kernel"` + User uint64 `json:"user"` +} + +type Cpu struct { + Usage CpuUsage `json:"usage,omitempty"` + Throttling Throttling `json:"throttling,omitempty"` +} + +type MemoryEntry struct { + Limit uint64 `json:"limit"` + Usage uint64 `json:"usage,omitempty"` + Max uint64 `json:"max,omitempty"` + Failcnt uint64 `json:"failcnt"` +} + +type Memory struct { + Cache uint64 `json:"cache,omitempty"` + Usage MemoryEntry `json:"usage,omitempty"` + Swap MemoryEntry `json:"swap,omitempty"` + Kernel MemoryEntry `json:"kernel,omitempty"` + KernelTCP MemoryEntry `json:"kernelTCP,omitempty"` + Raw map[string]uint64 `json:"raw,omitempty"` +} + +type L3CacheInfo struct { + CbmMask string `json:"cbm_mask,omitempty"` + MinCbmBits uint64 `json:"min_cbm_bits,omitempty"` + NumClosids uint64 `json:"num_closids,omitempty"` +} + +type MemBwInfo struct { + BandwidthGran uint64 `json:"bandwidth_gran,omitempty"` + DelayLinear uint64 `json:"delay_linear,omitempty"` + MinBandwidth uint64 `json:"min_bandwidth,omitempty"` + NumClosids uint64 `json:"num_closids,omitempty"` +} + +type IntelRdt struct { + // The read-only L3 cache information + L3CacheInfo *L3CacheInfo `json:"l3_cache_info,omitempty"` + + // The read-only L3 cache schema in root + L3CacheSchemaRoot string `json:"l3_cache_schema_root,omitempty"` + + // The L3 cache schema in 'container_id' group + L3CacheSchema string `json:"l3_cache_schema,omitempty"` + + // The read-only memory bandwidth information + MemBwInfo *MemBwInfo `json:"mem_bw_info,omitempty"` + + // The read-only memory bandwidth schema in root + MemBwSchemaRoot string `json:"mem_bw_schema_root,omitempty"` + + // The memory bandwidth schema in 'container_id' group + MemBwSchema string `json:"mem_bw_schema,omitempty"` +} + +type NetworkInterface struct { + // Name is the name of the network interface. + Name string + + RxBytes uint64 + RxPackets uint64 + RxErrors uint64 + RxDropped uint64 + TxBytes uint64 + TxPackets uint64 + TxErrors uint64 + TxDropped uint64 +}
  36. Download patch libcontainer/cgroups/fscommon/fscommon.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fscommon/fscommon.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fscommon/fscommon.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,36 @@ +// +build linux + +package fscommon + +import ( + "io/ioutil" + + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/pkg/errors" +) + +func WriteFile(dir, file, data string) error { + if dir == "" { + return errors.Errorf("no directory specified for %s", file) + } + path, err := securejoin.SecureJoin(dir, file) + if err != nil { + return err + } + if err := ioutil.WriteFile(path, []byte(data), 0700); err != nil { + return errors.Wrapf(err, "failed to write %q to %q", data, path) + } + return nil +} + +func ReadFile(dir, file string) (string, error) { + if dir == "" { + return "", errors.Errorf("no directory specified for %s", file) + } + path, err := securejoin.SecureJoin(dir, file) + if err != nil { + return "", err + } + data, err := ioutil.ReadFile(path) + return string(data), err +}
  37. Download patch libcontainer/cgroups/fs/net_prio_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/net_prio_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/net_prio_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -28,7 +29,7 @@ func TestNetPrioSetIfPrio(t *testing.T) t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "net_prio.ifpriomap") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "net_prio.ifpriomap") if err != nil { t.Fatalf("Failed to parse net_prio.ifpriomap - %s", err) }
  38. Download patch libcontainer/cgroups/fs/net_prio.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/net_prio.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/net_prio.go 2020-01-22 16:19:15.000000000 +0000 @@ -4,6 +4,7 @@ package fs import ( "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -24,7 +25,7 @@ func (s *NetPrioGroup) Apply(d *cgroupDa func (s *NetPrioGroup) Set(path string, cgroup *configs.Cgroup) error { for _, prioMap := range cgroup.Resources.NetPrioIfpriomap { - if err := writeFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil { + if err := fscommon.WriteFile(path, "net_prio.ifpriomap", prioMap.CgroupString()); err != nil { return err } }
  39. Download patch vendor/github.com/cilium/ebpf/asm/func.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/func.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/func.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,143 @@ +package asm + +//go:generate stringer -output func_string.go -type=BuiltinFunc + +// BuiltinFunc is a built-in eBPF function. +type BuiltinFunc int32 + +// eBPF built-in functions +// +// You can renegerate this list using the following gawk script: +// +// /FN\(.+\),/ { +// match($1, /\((.+)\)/, r) +// split(r[1], p, "_") +// printf "Fn" +// for (i in p) { +// printf "%s%s", toupper(substr(p[i], 1, 1)), substr(p[i], 2) +// } +// print "" +// } +// +// The script expects include/uapi/linux/bpf.h as it's input. +const ( + FnUnspec BuiltinFunc = iota + FnMapLookupElem + FnMapUpdateElem + FnMapDeleteElem + FnProbeRead + FnKtimeGetNs + FnTracePrintk + FnGetPrandomU32 + FnGetSmpProcessorId + FnSkbStoreBytes + FnL3CsumReplace + FnL4CsumReplace + FnTailCall + FnCloneRedirect + FnGetCurrentPidTgid + FnGetCurrentUidGid + FnGetCurrentComm + FnGetCgroupClassid + FnSkbVlanPush + FnSkbVlanPop + FnSkbGetTunnelKey + FnSkbSetTunnelKey + FnPerfEventRead + FnRedirect + FnGetRouteRealm + FnPerfEventOutput + FnSkbLoadBytes + FnGetStackid + FnCsumDiff + FnSkbGetTunnelOpt + FnSkbSetTunnelOpt + FnSkbChangeProto + FnSkbChangeType + FnSkbUnderCgroup + FnGetHashRecalc + FnGetCurrentTask + FnProbeWriteUser + FnCurrentTaskUnderCgroup + FnSkbChangeTail + FnSkbPullData + FnCsumUpdate + FnSetHashInvalid + FnGetNumaNodeId + FnSkbChangeHead + FnXdpAdjustHead + FnProbeReadStr + FnGetSocketCookie + FnGetSocketUid + FnSetHash + FnSetsockopt + FnSkbAdjustRoom + FnRedirectMap + FnSkRedirectMap + FnSockMapUpdate + FnXdpAdjustMeta + FnPerfEventReadValue + FnPerfProgReadValue + FnGetsockopt + FnOverrideReturn + FnSockOpsCbFlagsSet + FnMsgRedirectMap + FnMsgApplyBytes + FnMsgCorkBytes + FnMsgPullData + FnBind + FnXdpAdjustTail + FnSkbGetXfrmState + FnGetStack + FnSkbLoadBytesRelative + FnFibLookup + FnSockHashUpdate + FnMsgRedirectHash + FnSkRedirectHash + FnLwtPushEncap + FnLwtSeg6StoreBytes + FnLwtSeg6AdjustSrh + FnLwtSeg6Action + FnRcRepeat + FnRcKeydown + FnSkbCgroupId + FnGetCurrentCgroupId + FnGetLocalStorage + FnSkSelectReuseport + FnSkbAncestorCgroupId + FnSkLookupTcp + FnSkLookupUdp + FnSkRelease + FnMapPushElem + FnMapPopElem + FnMapPeekElem + FnMsgPushData + FnMsgPopData + FnRcPointerRel + FnSpinLock + FnSpinUnlock + FnSkFullsock + FnTcpSock + FnSkbEcnSetCe + FnGetListenerSock + FnSkcLookupTcp + FnTcpCheckSyncookie + FnSysctlGetName + FnSysctlGetCurrentValue + FnSysctlGetNewValue + FnSysctlSetNewValue + FnStrtol + FnStrtoul + FnSkStorageGet + FnSkStorageDelete + FnSendSignal + FnTcpGenSyncookie +) + +// Call emits a function call. +func (fn BuiltinFunc) Call() Instruction { + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(Call), + Constant: int64(fn), + } +}
  40. Download patch tests/integration/tty.bats

    --- 1.0.0~rc9+dfsg1-1/tests/integration/tty.bats 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/tests/integration/tty.bats 2020-01-22 16:19:15.000000000 +0000 @@ -205,7 +205,7 @@ EOF __runc run test_busybox ) & - wait_for_container 15 1 test_busybox + wait_for_container 15 1 test_busybox running testcontainer test_busybox running # Kill the container.
  41. Download patch libcontainer/cgroups/fs/memory_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/memory_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/memory_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -7,6 +7,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" ) const ( @@ -42,7 +43,7 @@ func TestMemorySetMemory(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.limit_in_bytes - %s", err) } @@ -50,7 +51,7 @@ func TestMemorySetMemory(t *testing.T) { t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") } - value, err = getCgroupParamUint(helper.CgroupPath, "memory.soft_limit_in_bytes") + value, err = fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.soft_limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.soft_limit_in_bytes - %s", err) } @@ -78,7 +79,7 @@ func TestMemorySetMemoryswap(t *testing. t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) } @@ -115,14 +116,14 @@ func TestMemorySetMemoryLargerThanSwap(t t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.limit_in_bytes - %s", err) } if value != memoryAfter { t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") } - value, err = getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") + value, err = fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) } @@ -159,14 +160,14 @@ func TestMemorySetSwapSmallerThanMemory( t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.limit_in_bytes - %s", err) } if value != memoryAfter { t.Fatal("Got the wrong value, set memory.limit_in_bytes failed.") } - value, err = getCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") + value, err = fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.memsw.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.memsw.limit_in_bytes - %s", err) } @@ -194,7 +195,7 @@ func TestMemorySetKernelMemory(t *testin t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.kmem.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.kmem.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.kmem.limit_in_bytes - %s", err) } @@ -222,7 +223,7 @@ func TestMemorySetKernelMemoryTCP(t *tes t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.kmem.tcp.limit_in_bytes") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.kmem.tcp.limit_in_bytes") if err != nil { t.Fatalf("Failed to parse memory.kmem.tcp.limit_in_bytes - %s", err) } @@ -248,7 +249,7 @@ func TestMemorySetMemorySwappinessDefaul t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.swappiness") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.swappiness") if err != nil { t.Fatalf("Failed to parse memory.swappiness - %s", err) } @@ -444,7 +445,7 @@ func TestMemorySetOomControl(t *testing. t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "memory.oom_control") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "memory.oom_control") if err != nil { t.Fatalf("Failed to parse memory.oom_control - %s", err) }
  42. Download patch debian/patches/test--fix_TestGetAdditionalGroups.patch

    --- 1.0.0~rc9+dfsg1-1/debian/patches/test--fix_TestGetAdditionalGroups.patch 2019-01-25 01:41:16.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/patches/test--fix_TestGetAdditionalGroups.patch 2019-01-30 21:27:05.000000000 +0000 @@ -20,7 +20,7 @@ Description: fix FTBFS on i686 } --- a/libcontainer/user/user.go +++ b/libcontainer/user/user.go -@@ -472,9 +472,9 @@ +@@ -413,9 +413,9 @@ if err != nil { return nil, fmt.Errorf("Unable to find group %s", ag) }
  43. Download patch debian/clean

    --- 1.0.0~rc9+dfsg1-1/debian/clean 2018-06-15 11:50:30.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/clean 2019-01-30 21:27:05.000000000 +0000 @@ -1,5 +1,3 @@ -libcontainer/criurpc/criurpc.pb.go - ## Remove generated man pages: man/man8/* @@ -7,10 +5,6 @@ man/man8/* ## https://github.com/opencontainers/runc/issues/692 libcontainer/nsenter/nsenter_test.go -## Generated: -libcontainer/criurpc/criurpc.pb.go - - ## Failing tests: ## Privileged tests:
  44. Download patch debian/tests/basic-smoke

    --- 1.0.0~rc9+dfsg1-1/debian/tests/basic-smoke 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/tests/basic-smoke 2019-02-14 22:25:50.000000000 +0000 @@ -0,0 +1,34 @@ +#!/bin/bash +set -Eeuo pipefail +set -x + +runc --version + +tempDir="$(mktemp -d)" +trap 'rm -rf "$tempDir"' EXIT + +# build up rootfs with busybox +busybox="$(which busybox)" # from busybox-static +mkdir "$tempDir/rootfs" +cp -a "$busybox" "$tempDir/rootfs/" + +# rough "rootfs" smoke test (makes sure "busybox" is actually static) +chroot "$tempDir/rootfs" /busybox true + +# make a config.json file for our "bundle" +runc spec --bundle "$tempDir" + +# edit the default command to something we can actually run with our rootfs +grep '"sh"' "$tempDir/config.json" +sed -i 's@"sh"@"/busybox","echo","success"@g' "$tempDir/config.json" +grep '"/busybox","echo","success"' "$tempDir/config.json" +# and disable the TTY +grep '"terminal": true,' "$tempDir/config.json" +sed -i 's/"terminal": true,/"terminal": false,/g' "$tempDir/config.json" +grep '"terminal": false,' "$tempDir/config.json" + +# run it and capture the output +output="$(runc run --bundle "$tempDir" "test-$$-$RANDOM")" + +# ensure the output was exactly what we expected +[ "$output" = 'success' ]
  45. Download patch debian/patches/test--skip_TestFactoryNewTmpfs.patch

    --- 1.0.0~rc9+dfsg1-1/debian/patches/test--skip_TestFactoryNewTmpfs.patch 2019-01-25 01:41:16.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/debian/patches/test--skip_TestFactoryNewTmpfs.patch 2019-01-30 21:27:05.000000000 +0000 @@ -5,7 +5,7 @@ Description: disable test (requires root --- a/libcontainer/factory_linux_test.go +++ b/libcontainer/factory_linux_test.go -@@ -77,8 +77,9 @@ +@@ -76,8 +76,9 @@ } }
  46. Download patch vendor/github.com/cilium/ebpf/abi.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/abi.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/abi.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,183 @@ +package ebpf + +import ( + "github.com/pkg/errors" +) + +// CollectionABI describes the interface of an eBPF collection. +type CollectionABI struct { + Maps map[string]*MapABI + Programs map[string]*ProgramABI +} + +// CheckSpec verifies that all maps and programs mentioned +// in the ABI are present in the spec. +func (abi *CollectionABI) CheckSpec(cs *CollectionSpec) error { + for name := range abi.Maps { + if cs.Maps[name] == nil { + return errors.Errorf("missing map %s", name) + } + } + + for name := range abi.Programs { + if cs.Programs[name] == nil { + return errors.Errorf("missing program %s", name) + } + } + + return nil +} + +// Check verifies that all items in a collection conform to this ABI. +func (abi *CollectionABI) Check(coll *Collection) error { + for name, mapABI := range abi.Maps { + m := coll.Maps[name] + if m == nil { + return errors.Errorf("missing map %s", name) + } + if err := mapABI.Check(m); err != nil { + return errors.Wrapf(err, "map %s", name) + } + } + + for name, progABI := range abi.Programs { + p := coll.Programs[name] + if p == nil { + return errors.Errorf("missing program %s", name) + } + if err := progABI.Check(p); err != nil { + return errors.Wrapf(err, "program %s", name) + } + } + + return nil +} + +// MapABI describes a Map. +// +// Use it to assert that a Map matches what your code expects. +type MapABI struct { + Type MapType + KeySize uint32 + ValueSize uint32 + MaxEntries uint32 + InnerMap *MapABI +} + +func newMapABIFromSpec(spec *MapSpec) *MapABI { + var inner *MapABI + if spec.InnerMap != nil { + inner = newMapABIFromSpec(spec.InnerMap) + } + + return &MapABI{ + spec.Type, + spec.KeySize, + spec.ValueSize, + spec.MaxEntries, + inner, + } +} + +func newMapABIFromFd(fd *bpfFD) (*MapABI, error) { + info, err := bpfGetMapInfoByFD(fd) + if err != nil { + return nil, err + } + + mapType := MapType(info.mapType) + if mapType == ArrayOfMaps || mapType == HashOfMaps { + return nil, errors.New("can't get map info for nested maps") + } + + return &MapABI{ + mapType, + info.keySize, + info.valueSize, + info.maxEntries, + nil, + }, nil +} + +// Check verifies that a Map conforms to the ABI. +// +// Members of ABI which have the zero value of their type are not checked. +func (abi *MapABI) Check(m *Map) error { + return abi.check(&m.abi) +} + +func (abi *MapABI) check(other *MapABI) error { + if abi.Type != UnspecifiedMap && other.Type != abi.Type { + return errors.Errorf("expected map type %s, have %s", abi.Type, other.Type) + } + if err := checkUint32("key size", abi.KeySize, other.KeySize); err != nil { + return err + } + if err := checkUint32("value size", abi.ValueSize, other.ValueSize); err != nil { + return err + } + if err := checkUint32("max entries", abi.MaxEntries, other.MaxEntries); err != nil { + return err + } + + if abi.InnerMap == nil { + if abi.Type == ArrayOfMaps || abi.Type == HashOfMaps { + return errors.New("missing inner map ABI") + } + + return nil + } + + if other.InnerMap == nil { + return errors.New("missing inner map") + } + + return errors.Wrap(abi.InnerMap.check(other.InnerMap), "inner map") +} + +// ProgramABI describes a Program. +// +// Use it to assert that a Program matches what your code expects. +type ProgramABI struct { + Type ProgramType +} + +func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI { + return &ProgramABI{ + spec.Type, + } +} + +func newProgramABIFromFd(fd *bpfFD) (*ProgramABI, error) { + info, err := bpfGetProgInfoByFD(fd) + if err != nil { + return nil, err + } + + return newProgramABIFromInfo(info), nil +} + +func newProgramABIFromInfo(info *bpfProgInfo) *ProgramABI { + return &ProgramABI{ + Type: ProgramType(info.progType), + } +} + +// Check verifies that a Program conforms to the ABI. +// +// Members which have the zero value of their type +// are not checked. +func (abi *ProgramABI) Check(prog *Program) error { + if abi.Type != UnspecifiedProgram && prog.abi.Type != abi.Type { + return errors.Errorf("expected program type %s, have %s", abi.Type, prog.abi.Type) + } + + return nil +} + +func checkUint32(name string, want, have uint32) error { + if want != 0 && have != want { + return errors.Errorf("expected %s to be %d, have %d", name, want, have) + } + return nil +}
  47. Download patch libcontainer/cgroups/fs/cpu_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpu_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpu_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -// +build linux - -package fs - -import ( - "bufio" - "os" - "path/filepath" - "strconv" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" -) - -type CpuGroupV2 struct { -} - -func (s *CpuGroupV2) Name() string { - return "cpu" -} - -func (s *CpuGroupV2) Apply(d *cgroupData) error { - // We always want to join the cpu group, to allow fair cpu scheduling - // on a container basis - path, err := d.path("cpu") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return s.ApplyDir(path, d.config, d.pid) -} - -func (s *CpuGroupV2) ApplyDir(path string, cgroup *configs.Cgroup, pid int) error { - // This might happen if we have no cpu cgroup mounted. - // Just do nothing and don't fail. - if path == "" { - return nil - } - if err := os.MkdirAll(path, 0755); err != nil { - return err - } - return cgroups.WriteCgroupProc(path, pid) -} - -func (s *CpuGroupV2) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.Resources.CpuWeight != 0 { - if err := writeFile(path, "cpu.weight", strconv.FormatUint(cgroup.Resources.CpuWeight, 10)); err != nil { - return err - } - } - - if cgroup.Resources.CpuMax != "" { - if err := writeFile(path, "cpu.max", cgroup.Resources.CpuMax); err != nil { - return err - } - } - - return nil -} - -func (s *CpuGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("cpu")) -} - -func (s *CpuGroupV2) GetStats(path string, stats *cgroups.Stats) error { - f, err := os.Open(filepath.Join(path, "cpu.stat")) - if err != nil { - if os.IsNotExist(err) { - return nil - } - return err - } - defer f.Close() - - sc := bufio.NewScanner(f) - for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) - if err != nil { - return err - } - switch t { - case "usage_usec": - stats.CpuStats.CpuUsage.TotalUsage = v * 1000 - - case "user_usec": - stats.CpuStats.CpuUsage.UsageInUsermode = v * 1000 - - case "system_usec": - stats.CpuStats.CpuUsage.UsageInKernelmode = v * 1000 - } - } - return nil -}
  48. Download patch libcontainer/cgroups/cgroups.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/cgroups.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/cgroups.go 2020-01-22 16:19:15.000000000 +0000 @@ -37,8 +37,18 @@ type Manager interface { // restore the object later. GetPaths() map[string]string + // GetUnifiedPath returns the unified path when running in unified mode. + // The value corresponds to the all values of GetPaths() map. + // + // GetUnifiedPath returns error when running in hybrid mode as well as + // in legacy mode. + GetUnifiedPath() (string, error) + // Sets the cgroup as configured. Set(container *configs.Config) error + + // Gets the cgroup as configured. + GetCgroups() (*configs.Cgroup, error) } type NotFoundError struct {
  49. Download patch libcontainer/cgroups/fs/cpuset.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpuset.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpuset.go 2020-01-22 16:19:15.000000000 +0000 @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" ) @@ -31,12 +32,12 @@ func (s *CpusetGroup) Apply(d *cgroupDat func (s *CpusetGroup) Set(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.CpusetCpus != "" { - if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil { + if err := fscommon.WriteFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil { return err } } if cgroup.Resources.CpusetMems != "" { - if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil { + if err := fscommon.WriteFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil { return err } } @@ -135,12 +136,12 @@ func (s *CpusetGroup) copyIfNeeded(curre } if s.isEmpty(currentCpus) { - if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil { + if err := fscommon.WriteFile(current, "cpuset.cpus", string(parentCpus)); err != nil { return err } } if s.isEmpty(currentMems) { - if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil { + if err := fscommon.WriteFile(current, "cpuset.mems", string(parentMems)); err != nil { return err } }
  50. Download patch libcontainer/cgroups/fs/utils_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/utils_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/utils_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -// +build linux - -package fs - -import ( - "io/ioutil" - "math" - "os" - "path/filepath" - "strconv" - "testing" -) - -const ( - cgroupFile = "cgroup.file" - floatValue = 2048.0 - floatString = "2048" -) - -func TestGetCgroupParamsInt(t *testing.T) { - // Setup tempdir. - tempDir, err := ioutil.TempDir("", "cgroup_utils_test") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tempDir) - tempFile := filepath.Join(tempDir, cgroupFile) - - // Success. - err = ioutil.WriteFile(tempFile, []byte(floatString), 0755) - if err != nil { - t.Fatal(err) - } - value, err := getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with new line. - err = ioutil.WriteFile(tempFile, []byte(floatString+"\n"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != floatValue { - t.Fatalf("Expected %d to equal %f", value, floatValue) - } - - // Success with negative values - err = ioutil.WriteFile(tempFile, []byte("-12345"), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Success with negative values lesser than min int64 - s := strconv.FormatFloat(math.MinInt64, 'f', -1, 64) - err = ioutil.WriteFile(tempFile, []byte(s), 0755) - if err != nil { - t.Fatal(err) - } - value, err = getCgroupParamUint(tempDir, cgroupFile) - if err != nil { - t.Fatal(err) - } else if value != 0 { - t.Fatalf("Expected %d to equal %d", value, 0) - } - - // Not a float. - err = ioutil.WriteFile(tempFile, []byte("not-a-float"), 0755) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } - - // Unknown file. - err = os.Remove(tempFile) - if err != nil { - t.Fatal(err) - } - _, err = getCgroupParamUint(tempDir, cgroupFile) - if err == nil { - t.Fatal("Expecting error, got none") - } -}
  51. Download patch libcontainer/cgroups/fs/freezer_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/freezer_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/freezer_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -5,6 +5,7 @@ package fs import ( "testing" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -22,7 +23,7 @@ func TestFreezerSetState(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "freezer.state") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "freezer.state") if err != nil { t.Fatalf("Failed to parse freezer.state - %s", err) }
  52. Download patch libcontainer/cgroups/fs2/freezer.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/freezer.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/freezer.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,53 @@ +// +build linux + +package fs2 + +import ( + "strconv" + "strings" + + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" +) + +func setFreezer(dirPath string, state configs.FreezerState) error { + var desired int + switch state { + case configs.Undefined: + return nil + case configs.Frozen: + desired = 1 + case configs.Thawed: + desired = 0 + default: + return errors.Errorf("unknown freezer state %+v", state) + } + supportedErr := supportsFreezer(dirPath) + if supportedErr != nil && desired != 0 { + // can ignore error if desired == 1 + return errors.Wrap(supportedErr, "freezer not supported") + } + return freezeWithInt(dirPath, desired) +} + +func supportsFreezer(dirPath string) error { + _, err := fscommon.ReadFile(dirPath, "cgroup.freeze") + return err +} + +// freeze writes desired int to "cgroup.freeze". +func freezeWithInt(dirPath string, desired int) error { + desiredS := strconv.Itoa(desired) + if err := fscommon.WriteFile(dirPath, "cgroup.freeze", desiredS); err != nil { + return err + } + got, err := fscommon.ReadFile(dirPath, "cgroup.freeze") + if err != nil { + return err + } + if gotS := strings.TrimSpace(string(got)); gotS != desiredS { + return errors.Errorf("expected \"cgroup.freeze\" in %q to be %q, got %q", dirPath, desiredS, gotS) + } + return nil +}
  53. Download patch vendor/github.com/cilium/ebpf/asm/opcode_string.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/opcode_string.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/opcode_string.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,38 @@ +// Code generated by "stringer -output opcode_string.go -type=Class"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[LdClass-0] + _ = x[LdXClass-1] + _ = x[StClass-2] + _ = x[StXClass-3] + _ = x[ALUClass-4] + _ = x[JumpClass-5] + _ = x[ALU64Class-7] +} + +const ( + _Class_name_0 = "LdClassLdXClassStClassStXClassALUClassJumpClass" + _Class_name_1 = "ALU64Class" +) + +var ( + _Class_index_0 = [...]uint8{0, 7, 15, 22, 30, 38, 47} +) + +func (i Class) String() string { + switch { + case 0 <= i && i <= 5: + return _Class_name_0[_Class_index_0[i]:_Class_index_0[i+1]] + case i == 7: + return _Class_name_1 + default: + return "Class(" + strconv.FormatInt(int64(i), 10) + ")" + } +}
  54. Download patch libcontainer/cgroups/utils.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/utils.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/utils.go 2020-01-22 16:19:15.000000000 +0000 @@ -20,8 +20,9 @@ import ( ) const ( - CgroupNamePrefix = "name=" - CgroupProcesses = "cgroup.procs" + CgroupNamePrefix = "name=" + CgroupProcesses = "cgroup.procs" + unifiedMountpoint = "/sys/fs/cgroup" ) var ( @@ -40,7 +41,7 @@ var HugePageSizeUnitList = []string{"B", func IsCgroup2UnifiedMode() bool { isUnifiedOnce.Do(func() { var st syscall.Statfs_t - if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { + if err := syscall.Statfs(unifiedMountpoint, &st); err != nil { panic("cannot statfs cgroup root") } isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC @@ -50,6 +51,9 @@ func IsCgroup2UnifiedMode() bool { // https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) { + if IsCgroup2UnifiedMode() { + return unifiedMountpoint, nil + } mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem) return mnt, err } @@ -235,8 +239,8 @@ func GetCgroupMounts(all bool) ([]Mount, return nil, err } m := Mount{ - Mountpoint: "/sys/fs/cgroup", - Root: "/sys/fs/cgroup", + Mountpoint: unifiedMountpoint, + Root: unifiedMountpoint, Subsystems: availableControllers, } return []Mount{m}, nil @@ -262,6 +266,21 @@ func GetCgroupMounts(all bool) ([]Mount, // GetAllSubsystems returns all the cgroup subsystems supported by the kernel func GetAllSubsystems() ([]string, error) { + // /proc/cgroups is meaningless for v2 + // https://github.com/torvalds/linux/blob/v5.3/Documentation/admin-guide/cgroup-v2.rst#deprecated-v1-core-features + if IsCgroup2UnifiedMode() { + // "pseudo" controllers do not appear in /sys/fs/cgroup/cgroup.controllers. + // - devices: implemented in kernel 4.15 + // - freezer: implemented in kernel 5.2 + // We assume these are always available, as it is hard to detect availability. + pseudo := []string{"devices", "freezer"} + data, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers") + if err != nil { + return nil, err + } + subsystems := append(pseudo, strings.Fields(string(data))...) + return subsystems, nil + } f, err := os.Open("/proc/cgroups") if err != nil { return nil, err
  55. Download patch libcontainer/cgroups/fs2/devices.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/devices.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/devices.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,73 @@ +// +build linux + +package fs2 + +import ( + "github.com/opencontainers/runc/libcontainer/cgroups/ebpf" + "github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter" + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func isRWM(cgroupPermissions string) bool { + r := false + w := false + m := false + for _, rn := range cgroupPermissions { + switch rn { + case 'r': + r = true + case 'w': + w = true + case 'm': + m = true + } + } + return r && w && m +} + +// the logic is from crun +// https://github.com/containers/crun/blob/0.10.2/src/libcrun/cgroup.c#L1644-L1652 +func canSkipEBPFError(cgroup *configs.Cgroup) bool { + for _, dev := range cgroup.Resources.Devices { + if dev.Allow || !isRWM(dev.Permissions) { + return false + } + } + return true +} + +func setDevices(dirPath string, cgroup *configs.Cgroup) error { + devices := cgroup.Devices + if allowAllDevices := cgroup.Resources.AllowAllDevices; allowAllDevices != nil { + // never set by OCI specconv, but *allowAllDevices=false is still used by the integration test + if *allowAllDevices == true { + return errors.New("libcontainer AllowAllDevices is not supported, use Devices") + } + for _, ad := range cgroup.Resources.AllowedDevices { + d := *ad + d.Allow = true + devices = append(devices, &d) + } + } + if len(cgroup.Resources.DeniedDevices) != 0 { + // never set by OCI specconv + return errors.New("libcontainer DeniedDevices is not supported, use Devices") + } + insts, license, err := devicefilter.DeviceFilter(devices) + if err != nil { + return err + } + dirFD, err := unix.Open(dirPath, unix.O_DIRECTORY|unix.O_RDONLY, 0600) + if err != nil { + return errors.Errorf("cannot get dir FD for %s", dirPath) + } + defer unix.Close(dirFD) + if _, err := ebpf.LoadAttachCgroupDeviceFilter(insts, license, dirFD); err != nil { + if !canSkipEBPFError(cgroup) { + return err + } + } + return nil +}
  56. Download patch libcontainer/cgroups/systemd/apply_nosystemd.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/systemd/apply_nosystemd.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/systemd/apply_nosystemd.go 2020-01-22 16:19:15.000000000 +0000 @@ -1,4 +1,4 @@ -// +build !linux static_build +// +build !linux package systemd @@ -42,6 +42,10 @@ func (m *Manager) GetPaths() map[string] return nil } +func (m *Manager) GetUnifiedPath() (string, error) { + return "", fmt.Errorf("Systemd not supported") +} + func (m *Manager) GetStats() (*cgroups.Stats, error) { return nil, fmt.Errorf("Systemd not supported") } @@ -57,3 +61,7 @@ func (m *Manager) Freeze(state configs.F func Freeze(c *configs.Cgroup, state configs.FreezerState) error { return fmt.Errorf("Systemd not supported") } + +func (m *Manager) GetCgroups() (*configs.Cgroup, error) { + return nil, fmt.Errorf("Systemd not supported") +}
  57. Download patch SECURITY.md

    --- 1.0.0~rc9+dfsg1-1/SECURITY.md 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/SECURITY.md 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,3 @@ +# Security + +The reporting process and disclosure communications are outlined in [/org/security](https://github.com/opencontainers/org/blob/master/security/).
  58. Download patch libcontainer/stats.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/stats.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/stats.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -package libcontainer - -type NetworkInterface struct { - // Name is the name of the network interface. - Name string - - RxBytes uint64 - RxPackets uint64 - RxErrors uint64 - RxDropped uint64 - TxBytes uint64 - TxPackets uint64 - TxErrors uint64 - TxDropped uint64 -}
  59. Download patch vendor/github.com/cilium/ebpf/asm/jump.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/jump.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/jump.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,109 @@ +package asm + +//go:generate stringer -output jump_string.go -type=JumpOp + +// JumpOp affect control flow. +// +// msb lsb +// +----+-+---+ +// |OP |s|cls| +// +----+-+---+ +type JumpOp uint8 + +const jumpMask OpCode = aluMask + +const ( + // InvalidJumpOp is returned by getters when invoked + // on non branch OpCodes + InvalidJumpOp JumpOp = 0xff + // Ja jumps by offset unconditionally + Ja JumpOp = 0x00 + // JEq jumps by offset if r == imm + JEq JumpOp = 0x10 + // JGT jumps by offset if r > imm + JGT JumpOp = 0x20 + // JGE jumps by offset if r >= imm + JGE JumpOp = 0x30 + // JSet jumps by offset if r & imm + JSet JumpOp = 0x40 + // JNE jumps by offset if r != imm + JNE JumpOp = 0x50 + // JSGT jumps by offset if signed r > signed imm + JSGT JumpOp = 0x60 + // JSGE jumps by offset if signed r >= signed imm + JSGE JumpOp = 0x70 + // Call builtin or user defined function from imm + Call JumpOp = 0x80 + // Exit ends execution, with value in r0 + Exit JumpOp = 0x90 + // JLT jumps by offset if r < imm + JLT JumpOp = 0xa0 + // JLE jumps by offset if r <= imm + JLE JumpOp = 0xb0 + // JSLT jumps by offset if signed r < signed imm + JSLT JumpOp = 0xc0 + // JSLE jumps by offset if signed r <= signed imm + JSLE JumpOp = 0xd0 +) + +// Return emits an exit instruction. +// +// Requires a return value in R0. +func Return() Instruction { + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(Exit), + } +} + +// Op returns the OpCode for a given jump source. +func (op JumpOp) Op(source Source) OpCode { + return OpCode(JumpClass).SetJumpOp(op).SetSource(source) +} + +// Imm compares dst to value, and adjusts PC by offset if the condition is fulfilled. +func (op JumpOp) Imm(dst Register, value int32, label string) Instruction { + if op == Exit || op == Call || op == Ja { + return Instruction{OpCode: InvalidOpCode} + } + + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(op).SetSource(ImmSource), + Dst: dst, + Offset: -1, + Constant: int64(value), + Reference: label, + } +} + +// Reg compares dst to src, and adjusts PC by offset if the condition is fulfilled. +func (op JumpOp) Reg(dst, src Register, label string) Instruction { + if op == Exit || op == Call || op == Ja { + return Instruction{OpCode: InvalidOpCode} + } + + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(op).SetSource(RegSource), + Dst: dst, + Src: src, + Offset: -1, + Reference: label, + } +} + +// Label adjusts PC to the address of the label. +func (op JumpOp) Label(label string) Instruction { + if op == Call { + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(Call), + Src: R1, + Constant: -1, + Reference: label, + } + } + + return Instruction{ + OpCode: OpCode(JumpClass).SetJumpOp(op), + Offset: -1, + Reference: label, + } +}
  60. Download patch libcontainer/cgroups/fs/apply_raw.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/apply_raw.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/apply_raw.go 2020-01-22 16:19:15.000000000 +0000 @@ -5,7 +5,6 @@ package fs import ( "fmt" "io" - "io/ioutil" "os" "path/filepath" "sync" @@ -33,14 +32,6 @@ var ( &FreezerGroup{}, &NameGroup{GroupName: "name=systemd", Join: true}, } - subsystemsUnified = subsystemSet{ - &CpusetGroupV2{}, - &FreezerGroupV2{}, - &CpuGroupV2{}, - &MemoryGroupV2{}, - &IOGroupV2{}, - &PidsGroupV2{}, - } HugePageSizes, _ = cgroups.GetHugePageSize() ) @@ -138,9 +129,6 @@ func isIgnorableError(rootless bool, err } func (m *Manager) getSubsystems() subsystemSet { - if cgroups.IsCgroup2UnifiedMode() { - return subsystemsUnified - } return subsystemsLegacy } @@ -224,6 +212,10 @@ func (m *Manager) GetPaths() map[string] return paths } +func (m *Manager) GetUnifiedPath() (string, error) { + return "", errors.New("unified path is only supported when running in unified mode") +} + func (m *Manager) GetStats() (*cgroups.Stats, error) { m.mu.Lock() defer m.mu.Unlock() @@ -377,23 +369,6 @@ func (raw *cgroupData) join(subsystem st return path, nil } -func writeFile(dir, file, data string) error { - // Normally dir should not be empty, one case is that cgroup subsystem - // is not mounted, we will get empty dir, and we want it fail here. - if dir == "" { - return fmt.Errorf("no such directory for %s", file) - } - if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil { - return fmt.Errorf("failed to write %v to %v: %v", data, file, err) - } - return nil -} - -func readFile(dir, file string) (string, error) { - data, err := ioutil.ReadFile(filepath.Join(dir, file)) - return string(data), err -} - func removePath(p string, err error) error { if err != nil { return err @@ -430,3 +405,7 @@ func CheckCpushares(path string, c uint6 return nil } + +func (m *Manager) GetCgroups() (*configs.Cgroup, error) { + return m.Cgroups, nil +}
  61. Download patch libcontainer/container_linux_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/container_linux_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/container_linux_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -54,9 +54,16 @@ func (m *mockCgroupManager) GetPaths() m return m.paths } +func (m *mockCgroupManager) GetUnifiedPath() (string, error) { + return "", fmt.Errorf("unimplemented") +} + func (m *mockCgroupManager) Freeze(state configs.FreezerState) error { return nil } +func (m *mockCgroupManager) GetCgroups() (*configs.Cgroup, error) { + return nil, nil +} func (m *mockIntelRdtManager) Apply(pid int) error { return nil @@ -78,6 +85,10 @@ func (m *mockIntelRdtManager) Set(contai return nil } +func (m *mockIntelRdtManager) GetCgroups() (*configs.Cgroup, error) { + return nil, nil +} + type mockProcess struct { _pid int started uint64
  62. Download patch vendor/github.com/cilium/ebpf/asm/opcode.go
  63. Download patch libcontainer/cgroups/fs/net_cls_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/net_cls_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/net_cls_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -5,6 +5,8 @@ package fs import ( "strconv" "testing" + + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" ) const ( @@ -29,7 +31,7 @@ func TestNetClsSetClassid(t *testing.T) // As we are in mock environment, we can't get correct value of classid from // net_cls.classid. // So. we just judge if we successfully write classid into file - value, err := getCgroupParamUint(helper.CgroupPath, "net_cls.classid") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "net_cls.classid") if err != nil { t.Fatalf("Failed to parse net_cls.classid - %s", err) }
  64. Download patch libcontainer/cgroups/fs/cpuset_v2.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpuset_v2.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpuset_v2.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -// +build linux - -package fs - -import ( - "bytes" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/opencontainers/runc/libcontainer/configs" - libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" -) - -type CpusetGroupV2 struct { -} - -func (s *CpusetGroupV2) Name() string { - return "cpuset" -} - -func (s *CpusetGroupV2) Apply(d *cgroupData) error { - dir, err := d.path("cpuset") - if err != nil && !cgroups.IsNotFound(err) { - return err - } - return s.ApplyDir(dir, d.config, d.pid) -} - -func (s *CpusetGroupV2) Set(path string, cgroup *configs.Cgroup) error { - if cgroup.Resources.CpusetCpus != "" { - if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil { - return err - } - } - if cgroup.Resources.CpusetMems != "" { - if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil { - return err - } - } - return nil -} - -func (s *CpusetGroupV2) Remove(d *cgroupData) error { - return removePath(d.path("cpuset")) -} - -func (s *CpusetGroupV2) GetStats(path string, stats *cgroups.Stats) error { - return nil -} - -func (s *CpusetGroupV2) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error { - // This might happen if we have no cpuset cgroup mounted. - // Just do nothing and don't fail. - if dir == "" { - return nil - } - mountInfo, err := ioutil.ReadFile("/proc/self/mountinfo") - if err != nil { - return err - } - root := filepath.Dir(cgroups.GetClosestMountpointAncestor(dir, string(mountInfo))) - // 'ensureParent' start with parent because we don't want to - // explicitly inherit from parent, it could conflict with - // 'cpuset.cpu_exclusive'. - if err := s.ensureParent(filepath.Dir(dir), root); err != nil { - return err - } - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - // We didn't inherit cpuset configs from parent, but we have - // to ensure cpuset configs are set before moving task into the - // cgroup. - // The logic is, if user specified cpuset configs, use these - // specified configs, otherwise, inherit from parent. This makes - // cpuset configs work correctly with 'cpuset.cpu_exclusive', and - // keep backward compatibility. - if err := s.ensureCpusAndMems(dir, cgroup); err != nil { - return err - } - - // because we are not using d.join we need to place the pid into the procs file - // unlike the other subsystems - return cgroups.WriteCgroupProc(dir, pid) -} - -func (s *CpusetGroupV2) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) { - if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus.effective")); err != nil { - return - } - if mems, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.mems.effective")); err != nil { - return - } - return cpus, mems, nil -} - -// ensureParent makes sure that the parent directory of current is created -// and populated with the proper cpus and mems files copied from -// it's parent. -func (s *CpusetGroupV2) ensureParent(current, root string) error { - parent := filepath.Dir(current) - if libcontainerUtils.CleanPath(parent) == root { - return nil - } - // Avoid infinite recursion. - if parent == current { - return fmt.Errorf("cpuset: cgroup parent path outside cgroup root") - } - if err := s.ensureParent(parent, root); err != nil { - return err - } - if err := os.MkdirAll(current, 0755); err != nil { - return err - } - return s.copyIfNeeded(current, parent) -} - -// copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent -// directory to the current directory if the file's contents are 0 -func (s *CpusetGroupV2) copyIfNeeded(current, parent string) error { - var ( - err error - currentCpus, currentMems []byte - parentCpus, parentMems []byte - ) - - if currentCpus, currentMems, err = s.getSubsystemSettings(current); err != nil { - return err - } - if parentCpus, parentMems, err = s.getSubsystemSettings(parent); err != nil { - return err - } - - if s.isEmpty(currentCpus) { - if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil { - return err - } - } - if s.isEmpty(currentMems) { - if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil { - return err - } - } - return nil -} - -func (s *CpusetGroupV2) isEmpty(b []byte) bool { - return len(bytes.Trim(b, "\n")) == 0 -} - -func (s *CpusetGroupV2) ensureCpusAndMems(path string, cgroup *configs.Cgroup) error { - if err := s.Set(path, cgroup); err != nil { - return err - } - return s.copyIfNeeded(path, filepath.Dir(path)) -}
  65. Download patch libcontainer/cgroups/fs/pids_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/pids_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/pids_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -7,6 +7,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" ) const ( @@ -28,7 +29,7 @@ func TestPidsSetMax(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "pids.max") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "pids.max") if err != nil { t.Fatalf("Failed to parse pids.max - %s", err) } @@ -52,7 +53,7 @@ func TestPidsSetUnlimited(t *testing.T) t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "pids.max") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "pids.max") if err != nil { t.Fatalf("Failed to parse pids.max - %s", err) }
  66. Download patch libcontainer/cgroups/fs/pids.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/pids.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/pids.go 2020-01-22 16:19:15.000000000 +0000 @@ -8,6 +8,7 @@ import ( "strconv" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -35,7 +36,7 @@ func (s *PidsGroup) Set(path string, cgr limit = strconv.FormatInt(cgroup.Resources.PidsLimit, 10) } - if err := writeFile(path, "pids.max", limit); err != nil { + if err := fscommon.WriteFile(path, "pids.max", limit); err != nil { return err } } @@ -48,12 +49,12 @@ func (s *PidsGroup) Remove(d *cgroupData } func (s *PidsGroup) GetStats(path string, stats *cgroups.Stats) error { - current, err := getCgroupParamUint(path, "pids.current") + current, err := fscommon.GetCgroupParamUint(path, "pids.current") if err != nil { return fmt.Errorf("failed to parse pids.current - %s", err) } - maxString, err := getCgroupParamString(path, "pids.max") + maxString, err := fscommon.GetCgroupParamString(path, "pids.max") if err != nil { return fmt.Errorf("failed to parse pids.max - %s", err) } @@ -61,7 +62,7 @@ func (s *PidsGroup) GetStats(path string // Default if pids.max == "max" is 0 -- which represents "no limit". var max uint64 if maxString != "max" { - max, err = parseUint(maxString, 10, 64) + max, err = fscommon.ParseUint(maxString, 10, 64) if err != nil { return fmt.Errorf("failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q", maxString, filepath.Join(path, "pids.max")) }
  67. Download patch libcontainer/stats_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/stats_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/stats_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -1,10 +1,13 @@ package libcontainer -import "github.com/opencontainers/runc/libcontainer/cgroups" -import "github.com/opencontainers/runc/libcontainer/intelrdt" +import ( + "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/intelrdt" + "github.com/opencontainers/runc/types" +) type Stats struct { - Interfaces []*NetworkInterface + Interfaces []*types.NetworkInterface CgroupStats *cgroups.Stats IntelRdtStats *intelrdt.Stats }
  68. Download patch libcontainer/cgroups/fs/hugetlb_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/hugetlb_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/hugetlb_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -8,6 +8,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -54,7 +55,7 @@ func TestHugetlbSetHugetlb(t *testing.T) for _, pageSize := range HugePageSizes { limit := fmt.Sprintf(limit, pageSize) - value, err := getCgroupParamUint(helper.CgroupPath, limit) + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, limit) if err != nil { t.Fatalf("Failed to parse %s - %s", limit, err) }
  69. Download patch libcontainer/cgroups/fs/cpuacct.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpuacct.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpuacct.go 2020-01-22 16:19:15.000000000 +0000 @@ -10,6 +10,7 @@ import ( "strings" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" ) @@ -51,7 +52,7 @@ func (s *CpuacctGroup) GetStats(path str return err } - totalUsage, err := getCgroupParamUint(path, "cpuacct.usage") + totalUsage, err := fscommon.GetCgroupParamUint(path, "cpuacct.usage") if err != nil { return err } @@ -85,8 +86,8 @@ func getCpuUsageBreakdown(path string) ( return 0, 0, err } fields := strings.Fields(string(data)) - if len(fields) != 4 { - return 0, 0, fmt.Errorf("failure - %s is expected to have 4 fields", filepath.Join(path, cgroupCpuacctStat)) + if len(fields) < 4 { + return 0, 0, fmt.Errorf("failure - %s is expected to have at least 4 fields", filepath.Join(path, cgroupCpuacctStat)) } if fields[0] != userField { return 0, 0, fmt.Errorf("unexpected field %q in %q, expected %q", fields[0], cgroupCpuacctStat, userField)
  70. Download patch libcontainer/cgroups/ebpf/devicefilter/devicefilter.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/ebpf/devicefilter/devicefilter.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,180 @@ +// Package devicefilter containes eBPF device filter program +// +// The implementation is based on https://github.com/containers/crun/blob/0.10.2/src/libcrun/ebpf.c +// +// Although ebpf.c is originally licensed under LGPL-3.0-or-later, the author (Giuseppe Scrivano) +// agreed to relicense the file in Apache License 2.0: https://github.com/opencontainers/runc/issues/2144#issuecomment-543116397 +package devicefilter + +import ( + "fmt" + "math" + + "github.com/cilium/ebpf/asm" + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +const ( + // license string format is same as kernel MODULE_LICENSE macro + license = "Apache" +) + +// DeviceFilter returns eBPF device filter program and its license string +func DeviceFilter(devices []*configs.Device) (asm.Instructions, string, error) { + p := &program{} + p.init() + for i := len(devices) - 1; i >= 0; i-- { + if err := p.appendDevice(devices[i]); err != nil { + return nil, "", err + } + } + insts, err := p.finalize() + return insts, license, err +} + +type program struct { + insts asm.Instructions + hasWildCard bool + blockID int +} + +func (p *program) init() { + // struct bpf_cgroup_dev_ctx: https://elixir.bootlin.com/linux/v5.3.6/source/include/uapi/linux/bpf.h#L3423 + /* + u32 access_type + u32 major + u32 minor + */ + // R2 <- type (lower 16 bit of u32 access_type at R1[0]) + p.insts = append(p.insts, + asm.LoadMem(asm.R2, asm.R1, 0, asm.Half)) + + // R3 <- access (upper 16 bit of u32 access_type at R1[0]) + p.insts = append(p.insts, + asm.LoadMem(asm.R3, asm.R1, 0, asm.Word), + // RSh: bitwise shift right + asm.RSh.Imm32(asm.R3, 16)) + + // R4 <- major (u32 major at R1[4]) + p.insts = append(p.insts, + asm.LoadMem(asm.R4, asm.R1, 4, asm.Word)) + + // R5 <- minor (u32 minor at R1[8]) + p.insts = append(p.insts, + asm.LoadMem(asm.R5, asm.R1, 8, asm.Word)) +} + +// appendDevice needs to be called from the last element of OCI linux.resources.devices to the head element. +func (p *program) appendDevice(dev *configs.Device) error { + if p.blockID < 0 { + return errors.New("the program is finalized") + } + if p.hasWildCard { + // All entries after wildcard entry are ignored + return nil + } + + bpfType := int32(-1) + hasType := true + switch dev.Type { + case 'c': + bpfType = int32(unix.BPF_DEVCG_DEV_CHAR) + case 'b': + bpfType = int32(unix.BPF_DEVCG_DEV_BLOCK) + case 'a': + hasType = false + default: + // if not specified in OCI json, typ is set to DeviceTypeAll + return errors.Errorf("invalid DeviceType %q", string(dev.Type)) + } + if dev.Major > math.MaxUint32 { + return errors.Errorf("invalid major %d", dev.Major) + } + if dev.Minor > math.MaxUint32 { + return errors.Errorf("invalid minor %d", dev.Major) + } + hasMajor := dev.Major >= 0 // if not specified in OCI json, major is set to -1 + hasMinor := dev.Minor >= 0 + bpfAccess := int32(0) + for _, r := range dev.Permissions { + switch r { + case 'r': + bpfAccess |= unix.BPF_DEVCG_ACC_READ + case 'w': + bpfAccess |= unix.BPF_DEVCG_ACC_WRITE + case 'm': + bpfAccess |= unix.BPF_DEVCG_ACC_MKNOD + default: + return errors.Errorf("unknown device access %v", r) + } + } + // If the access is rwm, skip the check. + hasAccess := bpfAccess != (unix.BPF_DEVCG_ACC_READ | unix.BPF_DEVCG_ACC_WRITE | unix.BPF_DEVCG_ACC_MKNOD) + + blockSym := fmt.Sprintf("block-%d", p.blockID) + nextBlockSym := fmt.Sprintf("block-%d", p.blockID+1) + prevBlockLastIdx := len(p.insts) - 1 + if hasType { + p.insts = append(p.insts, + // if (R2 != bpfType) goto next + asm.JNE.Imm(asm.R2, bpfType, nextBlockSym), + ) + } + if hasAccess { + p.insts = append(p.insts, + // if (R3 & bpfAccess == 0 /* use R1 as a temp var */) goto next + asm.Mov.Reg32(asm.R1, asm.R3), + asm.And.Imm32(asm.R1, bpfAccess), + asm.JEq.Imm(asm.R1, 0, nextBlockSym), + ) + } + if hasMajor { + p.insts = append(p.insts, + // if (R4 != major) goto next + asm.JNE.Imm(asm.R4, int32(dev.Major), nextBlockSym), + ) + } + if hasMinor { + p.insts = append(p.insts, + // if (R5 != minor) goto next + asm.JNE.Imm(asm.R5, int32(dev.Minor), nextBlockSym), + ) + } + if !hasType && !hasAccess && !hasMajor && !hasMinor { + p.hasWildCard = true + } + p.insts = append(p.insts, acceptBlock(dev.Allow)...) + // set blockSym to the first instruction we added in this iteration + p.insts[prevBlockLastIdx+1] = p.insts[prevBlockLastIdx+1].Sym(blockSym) + p.blockID++ + return nil +} + +func (p *program) finalize() (asm.Instructions, error) { + if p.hasWildCard { + // acceptBlock with asm.Return() is already inserted + return p.insts, nil + } + blockSym := fmt.Sprintf("block-%d", p.blockID) + p.insts = append(p.insts, + // R0 <- 0 + asm.Mov.Imm32(asm.R0, 0).Sym(blockSym), + asm.Return(), + ) + p.blockID = -1 + return p.insts, nil +} + +func acceptBlock(accept bool) asm.Instructions { + v := int32(0) + if accept { + v = 1 + } + return []asm.Instruction{ + // R0 <- v + asm.Mov.Imm32(asm.R0, v), + asm.Return(), + } +}
  71. Download patch libcontainer/cgroups/cgroups_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/cgroups_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/cgroups_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -11,7 +11,9 @@ func TestParseCgroups(t *testing.T) { if err != nil { t.Fatal(err) } - + if IsCgroup2UnifiedMode() { + return + } if _, ok := cgroups["cpu"]; !ok { t.Fail() }
  72. Download patch libcontainer/cgroups/ebpf/ebpf.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/ebpf/ebpf.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/ebpf/ebpf.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,45 @@ +package ebpf + +import ( + "github.com/cilium/ebpf" + "github.com/cilium/ebpf/asm" + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +// LoadAttachCgroupDeviceFilter installs eBPF device filter program to /sys/fs/cgroup/<foo> directory. +// +// Requires the system to be running in cgroup2 unified-mode with kernel >= 4.15 . +// +// https://github.com/torvalds/linux/commit/ebc614f687369f9df99828572b1d85a7c2de3d92 +func LoadAttachCgroupDeviceFilter(insts asm.Instructions, license string, dirFD int) (func() error, error) { + nilCloser := func() error { + return nil + } + // Increase `ulimit -l` limit to avoid BPF_PROG_LOAD error (#2167). + // This limit is not inherited into the container. + memlockLimit := &unix.Rlimit{ + Cur: unix.RLIM_INFINITY, + Max: unix.RLIM_INFINITY, + } + _ = unix.Setrlimit(unix.RLIMIT_MEMLOCK, memlockLimit) + spec := &ebpf.ProgramSpec{ + Type: ebpf.CGroupDevice, + Instructions: insts, + License: license, + } + prog, err := ebpf.NewProgram(spec) + if err != nil { + return nilCloser, err + } + if err := prog.Attach(dirFD, ebpf.AttachCGroupDevice, unix.BPF_F_ALLOW_MULTI); err != nil { + return nilCloser, errors.Wrap(err, "failed to call BPF_PROG_ATTACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI)") + } + closer := func() error { + if err := prog.Detach(dirFD, ebpf.AttachCGroupDevice, unix.BPF_F_ALLOW_MULTI); err != nil { + return errors.Wrap(err, "failed to call BPF_PROG_DETACH (BPF_CGROUP_DEVICE, BPF_F_ALLOW_MULTI)") + } + return nil + } + return closer, nil +}
  73. Download patch vendor/github.com/cilium/ebpf/asm/doc.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/doc.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/doc.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,2 @@ +// Package asm is an assembler for eBPF bytecode. +package asm
  74. Download patch libcontainer/cgroups/fs2/memory.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/memory.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/memory.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,103 @@ +// +build linux + +package fs2 + +import ( + "bufio" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/pkg/errors" +) + +func setMemory(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.Resources.MemorySwap != 0 { + if err := fscommon.WriteFile(dirPath, "memory.swap.max", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { + return err + } + } + if cgroup.Resources.Memory != 0 { + if err := fscommon.WriteFile(dirPath, "memory.max", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { + return err + } + } + + // cgroup.Resources.KernelMemory is ignored + + if cgroup.Resources.MemoryReservation != 0 { + if err := fscommon.WriteFile(dirPath, "memory.low", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil { + return err + } + } + + return nil +} + +func statMemory(dirPath string, stats *cgroups.Stats) error { + // Set stats from memory.stat. + statsFile, err := os.Open(filepath.Join(dirPath, "memory.stat")) + if err != nil { + return err + } + defer statsFile.Close() + + sc := bufio.NewScanner(statsFile) + for sc.Scan() { + t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text()) + if err != nil { + return errors.Wrapf(err, "failed to parse memory.stat (%q)", sc.Text()) + } + stats.MemoryStats.Stats[t] = v + } + stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"] + + memoryUsage, err := getMemoryDataV2(dirPath, "") + if err != nil { + return err + } + stats.MemoryStats.Usage = memoryUsage + swapUsage, err := getMemoryDataV2(dirPath, "swap") + if err != nil { + return err + } + stats.MemoryStats.SwapUsage = swapUsage + + stats.MemoryStats.UseHierarchy = true + return nil +} + +func getMemoryDataV2(path, name string) (cgroups.MemoryData, error) { + memoryData := cgroups.MemoryData{} + + moduleName := "memory" + if name != "" { + moduleName = strings.Join([]string{"memory", name}, ".") + } + usage := strings.Join([]string{moduleName, "current"}, ".") + limit := strings.Join([]string{moduleName, "max"}, ".") + + value, err := fscommon.GetCgroupParamUint(path, usage) + if err != nil { + if moduleName != "memory" && os.IsNotExist(err) { + return cgroups.MemoryData{}, nil + } + return cgroups.MemoryData{}, errors.Wrapf(err, "failed to parse %s", usage) + } + memoryData.Usage = value + + value, err = fscommon.GetCgroupParamUint(path, limit) + if err != nil { + if moduleName != "memory" && os.IsNotExist(err) { + return cgroups.MemoryData{}, nil + } + return cgroups.MemoryData{}, errors.Wrapf(err, "failed to parse %s", limit) + } + memoryData.Limit = value + + return memoryData, nil +}
  75. Download patch libcontainer/cgroups/fs2/defaultpath_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/defaultpath_test.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/defaultpath_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,76 @@ +/* + 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 fs2 + +import ( + "strings" + "testing" +) + +func TestParseCgroupFromReader(t *testing.T) { + cases := map[string]string{ + "0::/user.slice/user-1001.slice/session-1.scope\n": "/user.slice/user-1001.slice/session-1.scope", + "2:cpuset:/foo\n1:name=systemd:/\n": "", + "2:cpuset:/foo\n1:name=systemd:/\n0::/user.slice/user-1001.slice/session-1.scope\n": "/user.slice/user-1001.slice/session-1.scope", + } + for s, expected := range cases { + g, err := parseCgroupFromReader(strings.NewReader(s)) + if expected != "" { + if string(g) != expected { + t.Errorf("expected %q, got %q", expected, string(g)) + } + if err != nil { + t.Error(err) + } + } else { + if err == nil { + t.Error("error is expected") + } + } + } +} + +func TestDefaultDirPath(t *testing.T) { + root := "/sys/fs/cgroup" + cases := []struct { + cgPath string + cgParent string + cgName string + ownCgroup string + expected string + }{ + { + cgPath: "/foo/bar", + ownCgroup: "/apple/banana", + expected: "/sys/fs/cgroup/foo/bar", + }, + { + cgPath: "foo/bar", + ownCgroup: "/apple/banana", + expected: "/sys/fs/cgroup/apple/banana/foo/bar", + }, + } + for _, c := range cases { + got, err := _defaultDirPath(root, c.cgPath, c.cgParent, c.cgName, c.ownCgroup) + if err != nil { + t.Fatal(err) + } + if got != c.expected { + t.Fatalf("expected %q, got %q", c.expected, got) + } + } +}
  76. Download patch libcontainer/cgroups/fscommon/utils.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fscommon/utils.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fscommon/utils.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,83 @@ +// +build linux + +package fscommon + +import ( + "errors" + "fmt" + "io/ioutil" + "math" + "path/filepath" + "strconv" + "strings" +) + +var ( + ErrNotValidFormat = errors.New("line is not a valid key value format") +) + +// Saturates negative values at zero and returns a uint64. +// Due to kernel bugs, some of the memory cgroup stats can be negative. +func ParseUint(s string, base, bitSize int) (uint64, error) { + value, err := strconv.ParseUint(s, base, bitSize) + if err != nil { + intValue, intErr := strconv.ParseInt(s, base, bitSize) + // 1. Handle negative values greater than MinInt64 (and) + // 2. Handle negative values lesser than MinInt64 + if intErr == nil && intValue < 0 { + return 0, nil + } else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 { + return 0, nil + } + + return value, err + } + + return value, nil +} + +// Parses a cgroup param and returns as name, value +// i.e. "io_service_bytes 1234" will return as io_service_bytes, 1234 +func GetCgroupParamKeyValue(t string) (string, uint64, error) { + parts := strings.Fields(t) + switch len(parts) { + case 2: + value, err := ParseUint(parts[1], 10, 64) + if err != nil { + return "", 0, fmt.Errorf("unable to convert param value (%q) to uint64: %v", parts[1], err) + } + + return parts[0], value, nil + default: + return "", 0, ErrNotValidFormat + } +} + +// Gets a single uint64 value from the specified cgroup file. +func GetCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) { + fileName := filepath.Join(cgroupPath, cgroupFile) + contents, err := ioutil.ReadFile(fileName) + if err != nil { + return 0, err + } + trimmed := strings.TrimSpace(string(contents)) + if trimmed == "max" { + return math.MaxUint64, nil + } + + res, err := ParseUint(trimmed, 10, 64) + if err != nil { + return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName) + } + return res, nil +} + +// Gets a string value from the specified cgroup file +func GetCgroupParamString(cgroupPath, cgroupFile string) (string, error) { + contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile)) + if err != nil { + return "", err + } + + return strings.TrimSpace(string(contents)), nil +}
  77. Download patch libcontainer/network_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/network_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/network_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -10,6 +10,7 @@ import ( "strings" "github.com/opencontainers/runc/libcontainer/configs" + "github.com/opencontainers/runc/types" "github.com/vishvananda/netlink" ) @@ -37,8 +38,8 @@ func getStrategy(tpe string) (networkStr } // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. -func getNetworkInterfaceStats(interfaceName string) (*NetworkInterface, error) { - out := &NetworkInterface{Name: interfaceName} +func getNetworkInterfaceStats(interfaceName string) (*types.NetworkInterface, error) { + out := &types.NetworkInterface{Name: interfaceName} // This can happen if the network runtime information is missing - possible if the // container was created by an old version of libcontainer. if interfaceName == "" {
  78. Download patch libcontainer/cgroups/systemd/apply_systemd.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/systemd/apply_systemd.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/systemd/apply_systemd.go 2020-01-22 16:19:15.000000000 +0000 @@ -1,4 +1,4 @@ -// +build linux,!static_build +// +build linux package systemd @@ -297,6 +297,10 @@ func (m *LegacyManager) GetPaths() map[s return paths } +func (m *LegacyManager) GetUnifiedPath() (string, error) { + return "", errors.New("unified path is only supported when running in unified mode") +} + func join(c *configs.Cgroup, subsystem string, pid int) (string, error) { path, err := getSubsystemPath(c, subsystem) if err != nil { @@ -524,3 +528,7 @@ func isUnitExists(err error) bool { } return false } + +func (m *LegacyManager) GetCgroups() (*configs.Cgroup, error) { + return m.Cgroups, nil +}
  79. Download patch libcontainer/cgroups/fs/devices_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/devices_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/devices_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -5,6 +5,7 @@ package fs import ( "testing" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -48,7 +49,7 @@ func TestDevicesSetAllow(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "devices.allow") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "devices.allow") if err != nil { t.Fatalf("Failed to parse devices.allow - %s", err) } @@ -62,7 +63,7 @@ func TestDevicesSetAllow(t *testing.T) { if err := devices.Set(helper.CgroupPath, helper.CgroupData.config); err != nil { t.Fatal(err) } - value, err = getCgroupParamString(helper.CgroupPath, "devices.allow") + value, err = fscommon.GetCgroupParamString(helper.CgroupPath, "devices.allow") if err != nil { t.Fatalf("Failed to parse devices.allow - %s", err) } @@ -87,7 +88,7 @@ func TestDevicesSetDeny(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "devices.deny") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "devices.deny") if err != nil { t.Fatalf("Failed to parse devices.deny - %s", err) }
  80. Download patch Makefile

    --- 1.0.0~rc9+dfsg1-1/Makefile 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/Makefile 2020-01-22 16:19:15.000000000 +0000 @@ -3,6 +3,7 @@ test unittest integration \ cross localcross +CONTAINER_ENGINE := docker GO := go SOURCES := $(shell find . 2>&1 | grep -E '.*\.(c|h|go)$$') @@ -40,14 +41,14 @@ contrib/cmd/recvtty/recvtty: $(SOURCES) $(GO) build -buildmode=pie $(EXTRA_FLAGS) -ldflags "-X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -tags "$(BUILDTAGS)" -o contrib/cmd/recvtty/recvtty ./contrib/cmd/recvtty static: $(SOURCES) - CGO_ENABLED=1 $(GO) build $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo static_build" -installsuffix netgo -ldflags "-w -extldflags -static -X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -o runc . - CGO_ENABLED=1 $(GO) build $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo static_build" -installsuffix netgo -ldflags "-w -extldflags -static -X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -o contrib/cmd/recvtty/recvtty ./contrib/cmd/recvtty + CGO_ENABLED=1 $(GO) build $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo" -installsuffix netgo -ldflags "-w -extldflags -static -X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -o runc . + CGO_ENABLED=1 $(GO) build $(EXTRA_FLAGS) -tags "$(BUILDTAGS) netgo osusergo" -installsuffix netgo -ldflags "-w -extldflags -static -X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -o contrib/cmd/recvtty/recvtty ./contrib/cmd/recvtty release: script/release.sh -r release/$(VERSION) -v $(VERSION) dbuild: runcimage - docker run ${DOCKER_RUN_PROXY} --rm -v $(CURDIR):/go/src/$(PROJECT) --privileged $(RUNC_IMAGE) make clean all + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} --rm -v $(CURDIR):/go/src/$(PROJECT) --privileged $(RUNC_IMAGE) make clean all lint: $(GO) vet $(allpackages) @@ -57,7 +58,7 @@ man: man/md2man-all.sh runcimage: - docker build ${DOCKER_BUILD_PROXY} -t $(RUNC_IMAGE) . + $(CONTAINER_ENGINE) build ${CONTAINER_ENGINE_BUILD_FLAGS} -t $(RUNC_IMAGE) . test: make unittest integration rootlessintegration @@ -66,25 +67,25 @@ localtest: make localunittest localintegration localrootlessintegration unittest: runcimage - docker run ${DOCKER_RUN_PROXY} -t --privileged --rm -v /lib/modules:/lib/modules:ro -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localunittest TESTFLAGS=${TESTFLAGS} + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} -t --privileged --rm -v /lib/modules:/lib/modules:ro -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localunittest TESTFLAGS=${TESTFLAGS} localunittest: all $(GO) test -timeout 3m -tags "$(BUILDTAGS)" ${TESTFLAGS} -v $(allpackages) integration: runcimage - docker run ${DOCKER_RUN_PROXY} -t --privileged --rm -v /lib/modules:/lib/modules:ro -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localintegration TESTPATH=${TESTPATH} + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} -t --privileged --rm -v /lib/modules:/lib/modules:ro -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localintegration TESTPATH=${TESTPATH} localintegration: all bats -t tests/integration${TESTPATH} rootlessintegration: runcimage - docker run ${DOCKER_RUN_PROXY} -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localrootlessintegration + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localrootlessintegration localrootlessintegration: all tests/rootless.sh shell: runcimage - docker run ${DOCKER_RUN_PROXY} -ti --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) bash + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} -ti --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) bash install: install -D -m0755 runc $(BINDIR)/runc @@ -119,7 +120,7 @@ validate: ci: validate test release cross: runcimage - docker run ${DOCKER_RUN_PROXY} -e BUILDTAGS="$(BUILDTAGS)" --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localcross + $(CONTAINER_ENGINE) run ${CONTAINER_ENGINE_RUN_FLAGS} -e BUILDTAGS="$(BUILDTAGS)" --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localcross localcross: CGO_ENABLED=1 GOARCH=arm GOARM=6 CC=arm-linux-gnueabi-gcc $(GO) build -buildmode=pie $(EXTRA_FLAGS) -ldflags "-X main.gitCommit=${COMMIT} -X main.version=${VERSION} $(EXTRA_LDFLAGS)" -tags "$(BUILDTAGS)" -o runc-armel .
  81. Download patch libcontainer/rootfs_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/rootfs_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/rootfs_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -279,8 +279,14 @@ func mountCgroupV2(m *configs.Mount, roo if err := os.MkdirAll(cgroupPath, 0755); err != nil { return err } - - return unix.Mount(m.Source, cgroupPath, "cgroup2", uintptr(m.Flags), m.Data) + if err := unix.Mount(m.Source, cgroupPath, "cgroup2", uintptr(m.Flags), m.Data); err != nil { + // when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158) + if err == unix.EPERM || err == unix.EBUSY { + return unix.Mount("/sys/fs/cgroup", cgroupPath, "", uintptr(m.Flags)|unix.MS_BIND, "") + } + return err + } + return nil } func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error { @@ -293,6 +299,18 @@ func mountToRootfs(m *configs.Mount, roo switch m.Device { case "proc", "sysfs": + // If the destination already exists and is not a directory, we bail + // out This is to avoid mounting through a symlink or similar -- which + // has been a "fun" attack scenario in the past. + // TODO: This won't be necessary once we switch to libpathrs and we can + // stop all of these symlink-exchange attacks. + if fi, err := os.Lstat(dest); err != nil { + if !os.IsNotExist(err) { + return err + } + } else if fi.Mode()&os.ModeDir == 0 { + return fmt.Errorf("filesystem %q must be mounted on ordinary directory", m.Device) + } if err := os.MkdirAll(dest, 0755); err != nil { return err }
  82. Download patch libcontainer/factory_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/factory_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/factory_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -14,12 +14,14 @@ import ( "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/fs" + "github.com/opencontainers/runc/libcontainer/cgroups/fs2" "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs/validate" "github.com/opencontainers/runc/libcontainer/intelrdt" "github.com/opencontainers/runc/libcontainer/mount" "github.com/opencontainers/runc/libcontainer/utils" + "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -59,10 +61,37 @@ func SystemdCgroups(l *LinuxFactory) err return nil } +func getUnifiedPath(paths map[string]string) string { + unifiedPath := "" + for k, v := range paths { + if unifiedPath == "" { + unifiedPath = v + } else if v != unifiedPath { + panic(errors.Errorf("expected %q path to be unified path %q, got %q", k, unifiedPath, v)) + } + } + // can be empty + return unifiedPath +} + +func cgroupfs2(l *LinuxFactory, rootless bool) error { + l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager { + m, err := fs2.NewManager(config, getUnifiedPath(paths), rootless) + if err != nil { + panic(err) + } + return m + } + return nil +} + // Cgroupfs is an options func to configure a LinuxFactory to return containers // that use the native cgroups filesystem implementation to create and manage // cgroups. func Cgroupfs(l *LinuxFactory) error { + if cgroups.IsCgroup2UnifiedMode() { + return cgroupfs2(l, false) + } l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager { return &fs.Manager{ Cgroups: config, @@ -79,6 +108,9 @@ func Cgroupfs(l *LinuxFactory) error { // during rootless container (including euid=0 in userns) setup (while still allowing cgroup usage if // they've been set up properly). func RootlessCgroupfs(l *LinuxFactory) error { + if cgroups.IsCgroup2UnifiedMode() { + return cgroupfs2(l, true) + } l.NewCgroupsManager = func(config *configs.Cgroup, paths map[string]string) cgroups.Manager { return &fs.Manager{ Cgroups: config,
  83. Download patch vendor/github.com/cilium/ebpf/asm/func_string.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/func_string.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/func_string.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,133 @@ +// Code generated by "stringer -output func_string.go -type=BuiltinFunc"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[FnUnspec-0] + _ = x[FnMapLookupElem-1] + _ = x[FnMapUpdateElem-2] + _ = x[FnMapDeleteElem-3] + _ = x[FnProbeRead-4] + _ = x[FnKtimeGetNs-5] + _ = x[FnTracePrintk-6] + _ = x[FnGetPrandomU32-7] + _ = x[FnGetSmpProcessorId-8] + _ = x[FnSkbStoreBytes-9] + _ = x[FnL3CsumReplace-10] + _ = x[FnL4CsumReplace-11] + _ = x[FnTailCall-12] + _ = x[FnCloneRedirect-13] + _ = x[FnGetCurrentPidTgid-14] + _ = x[FnGetCurrentUidGid-15] + _ = x[FnGetCurrentComm-16] + _ = x[FnGetCgroupClassid-17] + _ = x[FnSkbVlanPush-18] + _ = x[FnSkbVlanPop-19] + _ = x[FnSkbGetTunnelKey-20] + _ = x[FnSkbSetTunnelKey-21] + _ = x[FnPerfEventRead-22] + _ = x[FnRedirect-23] + _ = x[FnGetRouteRealm-24] + _ = x[FnPerfEventOutput-25] + _ = x[FnSkbLoadBytes-26] + _ = x[FnGetStackid-27] + _ = x[FnCsumDiff-28] + _ = x[FnSkbGetTunnelOpt-29] + _ = x[FnSkbSetTunnelOpt-30] + _ = x[FnSkbChangeProto-31] + _ = x[FnSkbChangeType-32] + _ = x[FnSkbUnderCgroup-33] + _ = x[FnGetHashRecalc-34] + _ = x[FnGetCurrentTask-35] + _ = x[FnProbeWriteUser-36] + _ = x[FnCurrentTaskUnderCgroup-37] + _ = x[FnSkbChangeTail-38] + _ = x[FnSkbPullData-39] + _ = x[FnCsumUpdate-40] + _ = x[FnSetHashInvalid-41] + _ = x[FnGetNumaNodeId-42] + _ = x[FnSkbChangeHead-43] + _ = x[FnXdpAdjustHead-44] + _ = x[FnProbeReadStr-45] + _ = x[FnGetSocketCookie-46] + _ = x[FnGetSocketUid-47] + _ = x[FnSetHash-48] + _ = x[FnSetsockopt-49] + _ = x[FnSkbAdjustRoom-50] + _ = x[FnRedirectMap-51] + _ = x[FnSkRedirectMap-52] + _ = x[FnSockMapUpdate-53] + _ = x[FnXdpAdjustMeta-54] + _ = x[FnPerfEventReadValue-55] + _ = x[FnPerfProgReadValue-56] + _ = x[FnGetsockopt-57] + _ = x[FnOverrideReturn-58] + _ = x[FnSockOpsCbFlagsSet-59] + _ = x[FnMsgRedirectMap-60] + _ = x[FnMsgApplyBytes-61] + _ = x[FnMsgCorkBytes-62] + _ = x[FnMsgPullData-63] + _ = x[FnBind-64] + _ = x[FnXdpAdjustTail-65] + _ = x[FnSkbGetXfrmState-66] + _ = x[FnGetStack-67] + _ = x[FnSkbLoadBytesRelative-68] + _ = x[FnFibLookup-69] + _ = x[FnSockHashUpdate-70] + _ = x[FnMsgRedirectHash-71] + _ = x[FnSkRedirectHash-72] + _ = x[FnLwtPushEncap-73] + _ = x[FnLwtSeg6StoreBytes-74] + _ = x[FnLwtSeg6AdjustSrh-75] + _ = x[FnLwtSeg6Action-76] + _ = x[FnRcRepeat-77] + _ = x[FnRcKeydown-78] + _ = x[FnSkbCgroupId-79] + _ = x[FnGetCurrentCgroupId-80] + _ = x[FnGetLocalStorage-81] + _ = x[FnSkSelectReuseport-82] + _ = x[FnSkbAncestorCgroupId-83] + _ = x[FnSkLookupTcp-84] + _ = x[FnSkLookupUdp-85] + _ = x[FnSkRelease-86] + _ = x[FnMapPushElem-87] + _ = x[FnMapPopElem-88] + _ = x[FnMapPeekElem-89] + _ = x[FnMsgPushData-90] + _ = x[FnMsgPopData-91] + _ = x[FnRcPointerRel-92] + _ = x[FnSpinLock-93] + _ = x[FnSpinUnlock-94] + _ = x[FnSkFullsock-95] + _ = x[FnTcpSock-96] + _ = x[FnSkbEcnSetCe-97] + _ = x[FnGetListenerSock-98] + _ = x[FnSkcLookupTcp-99] + _ = x[FnTcpCheckSyncookie-100] + _ = x[FnSysctlGetName-101] + _ = x[FnSysctlGetCurrentValue-102] + _ = x[FnSysctlGetNewValue-103] + _ = x[FnSysctlSetNewValue-104] + _ = x[FnStrtol-105] + _ = x[FnStrtoul-106] + _ = x[FnSkStorageGet-107] + _ = x[FnSkStorageDelete-108] + _ = x[FnSendSignal-109] + _ = x[FnTcpGenSyncookie-110] +} + +const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookie" + +var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632} + +func (i BuiltinFunc) String() string { + if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) { + return "BuiltinFunc(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _BuiltinFunc_name[_BuiltinFunc_index[i]:_BuiltinFunc_index[i+1]] +}
  84. Download patch libcontainer/cgroups/fs/blkio_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/blkio_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/blkio_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -7,6 +7,7 @@ import ( "testing" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -95,7 +96,7 @@ func TestBlkioSetWeight(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamUint(helper.CgroupPath, "blkio.weight") + value, err := fscommon.GetCgroupParamUint(helper.CgroupPath, "blkio.weight") if err != nil { t.Fatalf("Failed to parse blkio.weight - %s", err) } @@ -126,7 +127,7 @@ func TestBlkioSetWeightDevice(t *testing t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.weight_device") if err != nil { t.Fatalf("Failed to parse blkio.weight_device - %s", err) } @@ -163,7 +164,7 @@ func TestBlkioSetMultipleWeightDevice(t t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.weight_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.weight_device") if err != nil { t.Fatalf("Failed to parse blkio.weight_device - %s", err) } @@ -535,7 +536,7 @@ func TestBlkioSetThrottleReadBpsDevice(t t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_bps_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.throttle.read_bps_device") if err != nil { t.Fatalf("Failed to parse blkio.throttle.read_bps_device - %s", err) } @@ -565,7 +566,7 @@ func TestBlkioSetThrottleWriteBpsDevice( t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_bps_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.throttle.write_bps_device") if err != nil { t.Fatalf("Failed to parse blkio.throttle.write_bps_device - %s", err) } @@ -595,7 +596,7 @@ func TestBlkioSetThrottleReadIOpsDevice( t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.read_iops_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.throttle.read_iops_device") if err != nil { t.Fatalf("Failed to parse blkio.throttle.read_iops_device - %s", err) } @@ -625,7 +626,7 @@ func TestBlkioSetThrottleWriteIOpsDevice t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "blkio.throttle.write_iops_device") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "blkio.throttle.write_iops_device") if err != nil { t.Fatalf("Failed to parse blkio.throttle.write_iops_device - %s", err) }
  85. Download patch vendor/github.com/cilium/ebpf/asm/load_store_string.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/load_store_string.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/load_store_string.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,80 @@ +// Code generated by "stringer -output load_store_string.go -type=Mode,Size"; DO NOT EDIT. + +package asm + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidMode-255] + _ = x[ImmMode-0] + _ = x[AbsMode-32] + _ = x[IndMode-64] + _ = x[MemMode-96] + _ = x[XAddMode-192] +} + +const ( + _Mode_name_0 = "ImmMode" + _Mode_name_1 = "AbsMode" + _Mode_name_2 = "IndMode" + _Mode_name_3 = "MemMode" + _Mode_name_4 = "XAddMode" + _Mode_name_5 = "InvalidMode" +) + +func (i Mode) String() string { + switch { + case i == 0: + return _Mode_name_0 + case i == 32: + return _Mode_name_1 + case i == 64: + return _Mode_name_2 + case i == 96: + return _Mode_name_3 + case i == 192: + return _Mode_name_4 + case i == 255: + return _Mode_name_5 + default: + return "Mode(" + strconv.FormatInt(int64(i), 10) + ")" + } +} +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[InvalidSize-255] + _ = x[DWord-24] + _ = x[Word-0] + _ = x[Half-8] + _ = x[Byte-16] +} + +const ( + _Size_name_0 = "Word" + _Size_name_1 = "Half" + _Size_name_2 = "Byte" + _Size_name_3 = "DWord" + _Size_name_4 = "InvalidSize" +) + +func (i Size) String() string { + switch { + case i == 0: + return _Size_name_0 + case i == 8: + return _Size_name_1 + case i == 16: + return _Size_name_2 + case i == 24: + return _Size_name_3 + case i == 255: + return _Size_name_4 + default: + return "Size(" + strconv.FormatInt(int64(i), 10) + ")" + } +}
  86. Download patch libcontainer/cgroups/fs/utils.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/utils.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/utils.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -// +build linux - -package fs - -import ( - "errors" - "fmt" - "io/ioutil" - "math" - "path/filepath" - "strconv" - "strings" -) - -var ( - ErrNotValidFormat = errors.New("line is not a valid key value format") -) - -// Saturates negative values at zero and returns a uint64. -// Due to kernel bugs, some of the memory cgroup stats can be negative. -func parseUint(s string, base, bitSize int) (uint64, error) { - value, err := strconv.ParseUint(s, base, bitSize) - if err != nil { - intValue, intErr := strconv.ParseInt(s, base, bitSize) - // 1. Handle negative values greater than MinInt64 (and) - // 2. Handle negative values lesser than MinInt64 - if intErr == nil && intValue < 0 { - return 0, nil - } else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 { - return 0, nil - } - - return value, err - } - - return value, nil -} - -// Parses a cgroup param and returns as name, value -// i.e. "io_service_bytes 1234" will return as io_service_bytes, 1234 -func getCgroupParamKeyValue(t string) (string, uint64, error) { - parts := strings.Fields(t) - switch len(parts) { - case 2: - value, err := parseUint(parts[1], 10, 64) - if err != nil { - return "", 0, fmt.Errorf("unable to convert param value (%q) to uint64: %v", parts[1], err) - } - - return parts[0], value, nil - default: - return "", 0, ErrNotValidFormat - } -} - -// Gets a single uint64 value from the specified cgroup file. -func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) { - fileName := filepath.Join(cgroupPath, cgroupFile) - contents, err := ioutil.ReadFile(fileName) - if err != nil { - return 0, err - } - trimmed := strings.TrimSpace(string(contents)) - if trimmed == "max" { - return math.MaxUint64, nil - } - - res, err := parseUint(trimmed, 10, 64) - if err != nil { - return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName) - } - return res, nil -} - -// Gets a string value from the specified cgroup file -func getCgroupParamString(cgroupPath, cgroupFile string) (string, error) { - contents, err := ioutil.ReadFile(filepath.Join(cgroupPath, cgroupFile)) - if err != nil { - return "", err - } - - return strings.TrimSpace(string(contents)), nil -}
  87. Download patch libcontainer/cgroups/fs/apply_raw_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/apply_raw_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/apply_raw_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -7,10 +7,14 @@ import ( "strings" "testing" + "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" ) func TestInvalidCgroupPath(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -42,6 +46,9 @@ func TestInvalidCgroupPath(t *testing.T) } func TestInvalidAbsoluteCgroupPath(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -74,6 +81,9 @@ func TestInvalidAbsoluteCgroupPath(t *te // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidCgroupParent(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -107,6 +117,9 @@ func TestInvalidCgroupParent(t *testing. // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidAbsoluteCgroupParent(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -140,6 +153,9 @@ func TestInvalidAbsoluteCgroupParent(t * // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidCgroupName(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -174,6 +190,9 @@ func TestInvalidCgroupName(t *testing.T) // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidAbsoluteCgroupName(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -207,6 +226,9 @@ func TestInvalidAbsoluteCgroupName(t *te // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidCgroupNameAndParent(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err) @@ -240,6 +262,9 @@ func TestInvalidCgroupNameAndParent(t *t // XXX: Remove me after we get rid of configs.Cgroup.Name and configs.Cgroup.Parent. func TestInvalidAbsoluteCgroupNameAndParent(t *testing.T) { + if cgroups.IsCgroup2UnifiedMode() { + t.Skip("cgroup v1 is not supported") + } root, err := getCgroupRoot() if err != nil { t.Errorf("couldn't get cgroup root: %v", err)
  88. Download patch libcontainer/init_linux.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/init_linux.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/init_linux.go 2020-01-22 16:19:15.000000000 +0000 @@ -127,6 +127,12 @@ func finalizeNamespace(config *initConfi return errors.Wrap(err, "close exec fds") } + if config.Cwd != "" { + if err := unix.Chdir(config.Cwd); err != nil { + return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err) + } + } + capabilities := &configs.Capabilities{} if config.Capabilities != nil { capabilities = config.Capabilities @@ -154,11 +160,6 @@ func finalizeNamespace(config *initConfi if err := w.ApplyCaps(); err != nil { return errors.Wrap(err, "apply caps") } - if config.Cwd != "" { - if err := unix.Chdir(config.Cwd); err != nil { - return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err) - } - } return nil }
  89. Download patch libcontainer/cgroups/fs2/defaultpath.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/defaultpath.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/defaultpath.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,99 @@ +/* + 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 fs2 + +import ( + "bufio" + "io" + "os" + "path/filepath" + "strings" + + "github.com/opencontainers/runc/libcontainer/configs" + libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils" + "github.com/pkg/errors" +) + +const UnifiedMountpoint = "/sys/fs/cgroup" + +func defaultDirPath(c *configs.Cgroup) (string, error) { + if (c.Name != "" || c.Parent != "") && c.Path != "" { + return "", errors.Errorf("cgroup: either Path or Name and Parent should be used, got %+v", c) + } + if len(c.Paths) != 0 { + // never set by specconv + return "", errors.Errorf("cgroup: Paths is unsupported, use Path, got %+v", c) + } + + // XXX: Do not remove this code. Path safety is important! -- cyphar + cgPath := libcontainerUtils.CleanPath(c.Path) + cgParent := libcontainerUtils.CleanPath(c.Parent) + cgName := libcontainerUtils.CleanPath(c.Name) + + ownCgroup, err := parseCgroupFile("/proc/self/cgroup") + if err != nil { + return "", err + } + return _defaultDirPath(UnifiedMountpoint, cgPath, cgParent, cgName, ownCgroup) +} + +func _defaultDirPath(root, cgPath, cgParent, cgName, ownCgroup string) (string, error) { + if (cgName != "" || cgParent != "") && cgPath != "" { + return "", errors.New("cgroup: either Path or Name and Parent should be used") + } + innerPath := cgPath + if innerPath == "" { + innerPath = filepath.Join(cgParent, cgName) + } + if filepath.IsAbs(innerPath) { + return filepath.Join(root, innerPath), nil + } + return filepath.Join(root, ownCgroup, innerPath), nil +} + +// parseCgroupFile parses /proc/PID/cgroup file and return string +func parseCgroupFile(path string) (string, error) { + f, err := os.Open(path) + if err != nil { + return "", err + } + defer f.Close() + return parseCgroupFromReader(f) +} + +func parseCgroupFromReader(r io.Reader) (string, error) { + var ( + s = bufio.NewScanner(r) + ) + for s.Scan() { + if err := s.Err(); err != nil { + return "", err + } + var ( + text = s.Text() + parts = strings.SplitN(text, ":", 3) + ) + if len(parts) < 3 { + return "", errors.Errorf("invalid cgroup entry: %q", text) + } + // text is like "0::/user.slice/user-1001.slice/session-1.scope" + if parts[0] == "0" && parts[1] == "" { + return parts[2], nil + } + } + return "", errors.New("cgroup path not found") +}
  90. Download patch vendor/github.com/cilium/ebpf/asm/register.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/register.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/register.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,42 @@ +package asm + +import ( + "fmt" +) + +// Register is the source or destination of most operations. +type Register uint8 + +// R0 contains return values. +const R0 Register = 0 + +// Registers for function arguments. +const ( + R1 Register = R0 + 1 + iota + R2 + R3 + R4 + R5 +) + +// Callee saved registers preserved by function calls. +const ( + R6 Register = R5 + 1 + iota + R7 + R8 + R9 +) + +// Read-only frame pointer to access stack. +const ( + R10 Register = R9 + 1 + RFP = R10 +) + +func (r Register) String() string { + v := uint8(r) + if v == 10 { + return "rfp" + } + return fmt.Sprintf("r%d", v) +}
  91. Download patch vendor/github.com/cilium/ebpf/asm/load_store.go

    --- 1.0.0~rc9+dfsg1-1/vendor/github.com/cilium/ebpf/asm/load_store.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/vendor/github.com/cilium/ebpf/asm/load_store.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,189 @@ +package asm + +//go:generate stringer -output load_store_string.go -type=Mode,Size + +// Mode for load and store operations +// +// msb lsb +// +---+--+---+ +// |MDE|sz|cls| +// +---+--+---+ +type Mode uint8 + +const modeMask OpCode = 0xe0 + +const ( + // InvalidMode is returned by getters when invoked + // on non load / store OpCodes + InvalidMode Mode = 0xff + // ImmMode - immediate value + ImmMode Mode = 0x00 + // AbsMode - immediate value + offset + AbsMode Mode = 0x20 + // IndMode - indirect (imm+src) + IndMode Mode = 0x40 + // MemMode - load from memory + MemMode Mode = 0x60 + // XAddMode - add atomically across processors. + XAddMode Mode = 0xc0 +) + +// Size of load and store operations +// +// msb lsb +// +---+--+---+ +// |mde|SZ|cls| +// +---+--+---+ +type Size uint8 + +const sizeMask OpCode = 0x18 + +const ( + // InvalidSize is returned by getters when invoked + // on non load / store OpCodes + InvalidSize Size = 0xff + // DWord - double word; 64 bits + DWord Size = 0x18 + // Word - word; 32 bits + Word Size = 0x00 + // Half - half-word; 16 bits + Half Size = 0x08 + // Byte - byte; 8 bits + Byte Size = 0x10 +) + +// Sizeof returns the size in bytes. +func (s Size) Sizeof() int { + switch s { + case DWord: + return 8 + case Word: + return 4 + case Half: + return 2 + case Byte: + return 1 + default: + return -1 + } +} + +// LoadMemOp returns the OpCode to load a value of given size from memory. +func LoadMemOp(size Size) OpCode { + return OpCode(LdXClass).SetMode(MemMode).SetSize(size) +} + +// LoadMem emits `dst = *(size *)(src + offset)`. +func LoadMem(dst, src Register, offset int16, size Size) Instruction { + return Instruction{ + OpCode: LoadMemOp(size), + Dst: dst, + Src: src, + Offset: offset, + } +} + +// LoadImmOp returns the OpCode to load an immediate of given size. +// +// As of kernel 4.20, only DWord size is accepted. +func LoadImmOp(size Size) OpCode { + return OpCode(LdClass).SetMode(ImmMode).SetSize(size) +} + +// LoadImm emits `dst = (size)value`. +// +// As of kernel 4.20, only DWord size is accepted. +func LoadImm(dst Register, value int64, size Size) Instruction { + return Instruction{ + OpCode: LoadImmOp(size), + Dst: dst, + Constant: value, + } +} + +// LoadMapPtr stores a pointer to a map in dst. +func LoadMapPtr(dst Register, fd int) Instruction { + if fd < 0 { + return Instruction{OpCode: InvalidOpCode} + } + + return Instruction{ + OpCode: LoadImmOp(DWord), + Dst: dst, + Src: R1, + Constant: int64(fd), + } +} + +// LoadIndOp returns the OpCode for loading a value of given size from an sk_buff. +func LoadIndOp(size Size) OpCode { + return OpCode(LdClass).SetMode(IndMode).SetSize(size) +} + +// LoadInd emits `dst = ntoh(*(size *)(((sk_buff *)R6)->data + src + offset))`. +func LoadInd(dst, src Register, offset int32, size Size) Instruction { + return Instruction{ + OpCode: LoadIndOp(size), + Dst: dst, + Src: src, + Constant: int64(offset), + } +} + +// LoadAbsOp returns the OpCode for loading a value of given size from an sk_buff. +func LoadAbsOp(size Size) OpCode { + return OpCode(LdClass).SetMode(AbsMode).SetSize(size) +} + +// LoadAbs emits `r0 = ntoh(*(size *)(((sk_buff *)R6)->data + offset))`. +func LoadAbs(offset int32, size Size) Instruction { + return Instruction{ + OpCode: LoadAbsOp(size), + Dst: R0, + Constant: int64(offset), + } +} + +// StoreMemOp returns the OpCode for storing a register of given size in memory. +func StoreMemOp(size Size) OpCode { + return OpCode(StXClass).SetMode(MemMode).SetSize(size) +} + +// StoreMem emits `*(size *)(dst + offset) = src` +func StoreMem(dst Register, offset int16, src Register, size Size) Instruction { + return Instruction{ + OpCode: StoreMemOp(size), + Dst: dst, + Src: src, + Offset: offset, + } +} + +// StoreImmOp returns the OpCode for storing an immediate of given size in memory. +func StoreImmOp(size Size) OpCode { + return OpCode(StClass).SetMode(MemMode).SetSize(size) +} + +// StoreImm emits `*(size *)(dst + offset) = value`. +func StoreImm(dst Register, offset int16, value int64, size Size) Instruction { + return Instruction{ + OpCode: StoreImmOp(size), + Dst: dst, + Offset: offset, + Constant: value, + } +} + +// StoreXAddOp returns the OpCode to atomically add a register to a value in memory. +func StoreXAddOp(size Size) OpCode { + return OpCode(StXClass).SetMode(XAddMode).SetSize(size) +} + +// StoreXAdd atomically adds src to *dst. +func StoreXAdd(dst, src Register, size Size) Instruction { + return Instruction{ + OpCode: StoreXAddOp(size), + Dst: dst, + Src: src, + } +}
  92. Download patch tests/integration/helpers.bash

    --- 1.0.0~rc9+dfsg1-1/tests/integration/helpers.bash 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/tests/integration/helpers.bash 2020-01-22 16:19:15.000000000 +0000 @@ -218,12 +218,16 @@ function wait_for_container() { local attempts=$1 local delay=$2 local cid=$3 + # optionally wait for a specific status + local wait_for_status="${4:-}" local i for ((i = 0; i < attempts; i++)); do runc state $cid if [[ "$status" -eq 0 ]]; then - return 0 + if [[ "${output}" == *"${wait_for_status}"* ]]; then + return 0 + fi fi sleep $delay done @@ -237,12 +241,16 @@ function wait_for_container_inroot() { local attempts=$1 local delay=$2 local cid=$3 + # optionally wait for a specific status + local wait_for_status="${4:-}" local i for ((i = 0; i < attempts; i++)); do ROOT=$4 runc state $cid if [[ "$status" -eq 0 ]]; then - return 0 + if [[ "${output}" == *"${wait_for_status}"* ]]; then + return 0 + fi fi sleep $delay done
  93. Download patch libcontainer/cgroups/fs2/fs2.go
  94. Download patch libcontainer/cgroups/fs2/cpuset.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs2/cpuset.go 1970-01-01 00:00:00.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs2/cpuset.go 2020-01-22 16:19:15.000000000 +0000 @@ -0,0 +1,22 @@ +// +build linux + +package fs2 + +import ( + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" + "github.com/opencontainers/runc/libcontainer/configs" +) + +func setCpuset(dirPath string, cgroup *configs.Cgroup) error { + if cgroup.Resources.CpusetCpus != "" { + if err := fscommon.WriteFile(dirPath, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil { + return err + } + } + if cgroup.Resources.CpusetMems != "" { + if err := fscommon.WriteFile(dirPath, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil { + return err + } + } + return nil +}
  95. Download patch libcontainer/cgroups/fs/memory.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/memory.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/memory.go 2020-01-22 16:19:15.000000000 +0000 @@ -11,6 +11,7 @@ import ( "strings" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -84,28 +85,28 @@ func setMemoryAndSwap(path string, cgrou // for memory and swap memory, so it won't fail because the new // value and the old value don't fit kernel's validation. if cgroup.Resources.MemorySwap == -1 || memoryUsage.Limit < uint64(cgroup.Resources.MemorySwap) { - if err := writeFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { return err } - if err := writeFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { return err } } else { - if err := writeFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { return err } - if err := writeFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { return err } } } else { if cgroup.Resources.Memory != 0 { - if err := writeFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil { return err } } if cgroup.Resources.MemorySwap != 0 { - if err := writeFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { + if err := fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil { return err } } @@ -126,25 +127,25 @@ func (s *MemoryGroup) Set(path string, c } if cgroup.Resources.MemoryReservation != 0 { - if err := writeFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil { + if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil { return err } } if cgroup.Resources.KernelMemoryTCP != 0 { - if err := writeFile(path, "memory.kmem.tcp.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemoryTCP, 10)); err != nil { + if err := fscommon.WriteFile(path, "memory.kmem.tcp.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemoryTCP, 10)); err != nil { return err } } if cgroup.Resources.OomKillDisable { - if err := writeFile(path, "memory.oom_control", "1"); err != nil { + if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil { return err } } if cgroup.Resources.MemorySwappiness == nil || int64(*cgroup.Resources.MemorySwappiness) == -1 { return nil } else if *cgroup.Resources.MemorySwappiness <= 100 { - if err := writeFile(path, "memory.swappiness", strconv.FormatUint(*cgroup.Resources.MemorySwappiness, 10)); err != nil { + if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*cgroup.Resources.MemorySwappiness, 10)); err != nil { return err } } else { @@ -171,7 +172,7 @@ func (s *MemoryGroup) GetStats(path stri sc := bufio.NewScanner(statsFile) for sc.Scan() { - t, v, err := getCgroupParamKeyValue(sc.Text()) + t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text()) if err != nil { return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err) } @@ -201,7 +202,7 @@ func (s *MemoryGroup) GetStats(path stri stats.MemoryStats.KernelTCPUsage = kernelTCPUsage useHierarchy := strings.Join([]string{"memory", "use_hierarchy"}, ".") - value, err := getCgroupParamUint(path, useHierarchy) + value, err := fscommon.GetCgroupParamUint(path, useHierarchy) if err != nil { return err } @@ -233,7 +234,7 @@ func getMemoryData(path, name string) (c failcnt := strings.Join([]string{moduleName, "failcnt"}, ".") limit := strings.Join([]string{moduleName, "limit_in_bytes"}, ".") - value, err := getCgroupParamUint(path, usage) + value, err := fscommon.GetCgroupParamUint(path, usage) if err != nil { if moduleName != "memory" && os.IsNotExist(err) { return cgroups.MemoryData{}, nil @@ -241,7 +242,7 @@ func getMemoryData(path, name string) (c return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err) } memoryData.Usage = value - value, err = getCgroupParamUint(path, maxUsage) + value, err = fscommon.GetCgroupParamUint(path, maxUsage) if err != nil { if moduleName != "memory" && os.IsNotExist(err) { return cgroups.MemoryData{}, nil @@ -249,7 +250,7 @@ func getMemoryData(path, name string) (c return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", maxUsage, err) } memoryData.MaxUsage = value - value, err = getCgroupParamUint(path, failcnt) + value, err = fscommon.GetCgroupParamUint(path, failcnt) if err != nil { if moduleName != "memory" && os.IsNotExist(err) { return cgroups.MemoryData{}, nil @@ -257,7 +258,7 @@ func getMemoryData(path, name string) (c return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", failcnt, err) } memoryData.Failcnt = value - value, err = getCgroupParamUint(path, limit) + value, err = fscommon.GetCgroupParamUint(path, limit) if err != nil { if moduleName != "memory" && os.IsNotExist(err) { return cgroups.MemoryData{}, nil
  96. Download patch events.go
  97. Download patch debian/copyright
  98. Download patch libcontainer/cgroups/fs/cpuset_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/cpuset_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/cpuset_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -4,6 +4,8 @@ package fs import ( "testing" + + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" ) func TestCpusetSetCpus(t *testing.T) { @@ -25,7 +27,7 @@ func TestCpusetSetCpus(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.cpus") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "cpuset.cpus") if err != nil { t.Fatalf("Failed to parse cpuset.cpus - %s", err) } @@ -54,7 +56,7 @@ func TestCpusetSetMems(t *testing.T) { t.Fatal(err) } - value, err := getCgroupParamString(helper.CgroupPath, "cpuset.mems") + value, err := fscommon.GetCgroupParamString(helper.CgroupPath, "cpuset.mems") if err != nil { t.Fatalf("Failed to parse cpuset.mems - %s", err) }
  99. Download patch libcontainer/cgroups/fs/net_cls.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/cgroups/fs/net_cls.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/cgroups/fs/net_cls.go 2020-01-22 16:19:15.000000000 +0000 @@ -6,6 +6,7 @@ import ( "strconv" "github.com/opencontainers/runc/libcontainer/cgroups" + "github.com/opencontainers/runc/libcontainer/cgroups/fscommon" "github.com/opencontainers/runc/libcontainer/configs" ) @@ -26,7 +27,7 @@ func (s *NetClsGroup) Apply(d *cgroupDat func (s *NetClsGroup) Set(path string, cgroup *configs.Cgroup) error { if cgroup.Resources.NetClsClassid != 0 { - if err := writeFile(path, "net_cls.classid", strconv.FormatUint(uint64(cgroup.Resources.NetClsClassid), 10)); err != nil { + if err := fscommon.WriteFile(path, "net_cls.classid", strconv.FormatUint(uint64(cgroup.Resources.NetClsClassid), 10)); err != nil { return err } }
  100. Download patch libcontainer/specconv/spec_linux_test.go

    --- 1.0.0~rc9+dfsg1-1/libcontainer/specconv/spec_linux_test.go 2019-09-30 16:36:09.000000000 +0000 +++ 1.0.0~rc10-0ubuntu1/libcontainer/specconv/spec_linux_test.go 2020-01-22 16:19:15.000000000 +0000 @@ -213,7 +213,7 @@ func TestLinuxCgroupWithMemoryResource(t Spec: spec, } - cgroup, err := createCgroupConfig(opts) + cgroup, err := CreateCgroupConfig(opts) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) } @@ -257,7 +257,7 @@ func TestLinuxCgroupSystemd(t *testing.T Spec: spec, } - cgroup, err := createCgroupConfig(opts) + cgroup, err := CreateCgroupConfig(opts) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) @@ -293,7 +293,7 @@ func TestLinuxCgroupSystemdWithEmptyPath Spec: spec, } - cgroup, err := createCgroupConfig(opts) + cgroup, err := CreateCgroupConfig(opts) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) @@ -328,7 +328,7 @@ func TestLinuxCgroupSystemdWithInvalidPa Spec: spec, } - _, err := createCgroupConfig(opts) + _, err := CreateCgroupConfig(opts) if err == nil { t.Error("Expected to produce an error if not using the correct format for cgroup paths belonging to systemd") } @@ -347,7 +347,7 @@ func TestLinuxCgroupsPathSpecified(t *te Spec: spec, } - cgroup, err := createCgroupConfig(opts) + cgroup, err := CreateCgroupConfig(opts) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) } @@ -365,7 +365,7 @@ func TestLinuxCgroupsPathNotSpecified(t Spec: spec, } - cgroup, err := createCgroupConfig(opts) + cgroup, err := CreateCgroupConfig(opts) if err != nil { t.Errorf("Couldn't create Cgroup config: %v", err) }
  101. ...

Debian ( Changelog | PTS | Bugs ) Ubuntu ( Changelog | txt | LP | Bugs ) | Diff from Ubuntu

Source: syncthing

syncthing (1.1.4~ds1-4ubuntu1) focal; urgency=medium * debian/patches/workaround-bad-test.patch: - Behavior of AuditService was racy (and always fail with golang 1.13). There is a time.Sleep in the tests that enabled to avoid it in golang 1.12, but this now always fail with golang 1.13. New syncthing is refactored to avoid this, once we get a new release in sync from Debian. -- Didier Roche <didrocks@ubuntu.com> Wed, 11 Dec 2019 08:00:36 +0100

Modifications :
  1. Download patch debian/control

    --- 1.1.4~ds1-4/debian/control 2019-08-28 18:04:55.000000000 +0000 +++ 1.1.4~ds1-4ubuntu1/debian/control 2019-12-11 07:00:36.000000000 +0000 @@ -1,7 +1,8 @@ Source: syncthing Section: utils Priority: optional -Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> +Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> +XSBC-Original-Maintainer: Debian Go Packaging Team <pkg-go-maintainers@lists.alioth.debian.org> Uploaders: Alexandre Viau <aviau@debian.org> Build-Depends: debhelper (>= 10), dh-exec,
  2. Download patch debian/patches/series

    --- 1.1.4~ds1-4/debian/patches/series 2019-08-28 19:08:23.000000000 +0000 +++ 1.1.4~ds1-4ubuntu1/debian/patches/series 2019-12-11 06:56:17.000000000 +0000 @@ -5,3 +5,4 @@ use-debian-proto.patch raleway.patch tests-wait-longer.patch skip-failing-test.patch +workaround-bad-test.patch
  3. Download patch debian/patches/workaround-bad-test.patch

    --- 1.1.4~ds1-4/debian/patches/workaround-bad-test.patch 1970-01-01 00:00:00.000000000 +0000 +++ 1.1.4~ds1-4ubuntu1/debian/patches/workaround-bad-test.patch 2019-12-11 07:00:36.000000000 +0000 @@ -0,0 +1,24 @@ +Index: syncthing-1.1.4~ds1/cmd/syncthing/auditservice_test.go +=================================================================== +--- syncthing-1.1.4~ds1.orig/cmd/syncthing/auditservice_test.go ++++ syncthing-1.1.4~ds1/cmd/syncthing/auditservice_test.go +@@ -40,9 +40,16 @@ func TestAuditService(t *testing.T) { + result := buf.String() + t.Log(result) + +- if strings.Contains(result, "first event") { +- t.Error("Unexpected first event") +- } ++ /* ++ Behavior of AuditService was racy (and always fail with golang 1.13). ++ There is a time.Sleep in the tests that enabled to avoid it in golang ++ 1.12, but this now always fail with golang 1.13. ++ New syncthing is refactored to avoid this, once we get a new release ++ in sync from Debian. ++ */ ++ //if strings.Contains(result, "first event") { ++ // t.Error("Unexpected first event") ++ //} + + if !strings.Contains(result, "second event") { + t.Error("Missing second event")
  1. golang-github-go-ldap-ldap
  2. golang-go.uber-zap
  3. influxdb
  4. runc
  5. syncthing