update libcontainer,gocapability,cadvisor

This commit is contained in:
derekwaynecarr 2016-10-10 14:24:05 -04:00
parent 160adc3864
commit 07bd42a192
40 changed files with 585 additions and 451 deletions

230
Godeps/Godeps.json generated
View File

@ -1109,208 +1109,208 @@
}, },
{ {
"ImportPath": "github.com/google/cadvisor/api", "ImportPath": "github.com/google/cadvisor/api",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/cache/memory", "ImportPath": "github.com/google/cadvisor/cache/memory",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/client/v2", "ImportPath": "github.com/google/cadvisor/client/v2",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/collector", "ImportPath": "github.com/google/cadvisor/collector",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container", "ImportPath": "github.com/google/cadvisor/container",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/common", "ImportPath": "github.com/google/cadvisor/container/common",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/docker", "ImportPath": "github.com/google/cadvisor/container/docker",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/libcontainer", "ImportPath": "github.com/google/cadvisor/container/libcontainer",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/raw", "ImportPath": "github.com/google/cadvisor/container/raw",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/rkt", "ImportPath": "github.com/google/cadvisor/container/rkt",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/container/systemd", "ImportPath": "github.com/google/cadvisor/container/systemd",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/devicemapper", "ImportPath": "github.com/google/cadvisor/devicemapper",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/events", "ImportPath": "github.com/google/cadvisor/events",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/fs", "ImportPath": "github.com/google/cadvisor/fs",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/healthz", "ImportPath": "github.com/google/cadvisor/healthz",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/http", "ImportPath": "github.com/google/cadvisor/http",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/http/mux", "ImportPath": "github.com/google/cadvisor/http/mux",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v1", "ImportPath": "github.com/google/cadvisor/info/v1",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v1/test", "ImportPath": "github.com/google/cadvisor/info/v1/test",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/info/v2", "ImportPath": "github.com/google/cadvisor/info/v2",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/machine", "ImportPath": "github.com/google/cadvisor/machine",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager", "ImportPath": "github.com/google/cadvisor/manager",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher", "ImportPath": "github.com/google/cadvisor/manager/watcher",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw", "ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt", "ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/metrics", "ImportPath": "github.com/google/cadvisor/metrics",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/pages", "ImportPath": "github.com/google/cadvisor/pages",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/pages/static", "ImportPath": "github.com/google/cadvisor/pages/static",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/storage", "ImportPath": "github.com/google/cadvisor/storage",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/summary", "ImportPath": "github.com/google/cadvisor/summary",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils", "ImportPath": "github.com/google/cadvisor/utils",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo", "ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload", "ImportPath": "github.com/google/cadvisor/utils/cpuload",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink", "ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/docker", "ImportPath": "github.com/google/cadvisor/utils/docker",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/oomparser", "ImportPath": "github.com/google/cadvisor/utils/oomparser",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysfs", "ImportPath": "github.com/google/cadvisor/utils/sysfs",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/sysinfo", "ImportPath": "github.com/google/cadvisor/utils/sysinfo",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/utils/tail", "ImportPath": "github.com/google/cadvisor/utils/tail",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/validate", "ImportPath": "github.com/google/cadvisor/validate",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/cadvisor/version", "ImportPath": "github.com/google/cadvisor/version",
"Comment": "v0.24.0-alpha1-14-gd7a44cb", "Comment": "v0.24.0-alpha1-39-ga9b1ab1",
"Rev": "d7a44cb1a2c66e1688ccdc5d09e56069eecb659a" "Rev": "a9b1ab1dd8d811d419487a631c3361df582346d2"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go", "ImportPath": "github.com/google/certificate-transparency/go",
@ -1736,83 +1736,83 @@
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer", "ImportPath": "github.com/opencontainers/runc/libcontainer",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor", "ImportPath": "github.com/opencontainers/runc/libcontainer/apparmor",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups", "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs", "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/fs",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd", "ImportPath": "github.com/opencontainers/runc/libcontainer/cgroups/systemd",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs", "ImportPath": "github.com/opencontainers/runc/libcontainer/configs",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate", "ImportPath": "github.com/opencontainers/runc/libcontainer/configs/validate",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc", "ImportPath": "github.com/opencontainers/runc/libcontainer/criurpc",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/keys", "ImportPath": "github.com/opencontainers/runc/libcontainer/keys",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/label", "ImportPath": "github.com/opencontainers/runc/libcontainer/label",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp", "ImportPath": "github.com/opencontainers/runc/libcontainer/seccomp",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/selinux", "ImportPath": "github.com/opencontainers/runc/libcontainer/selinux",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace", "ImportPath": "github.com/opencontainers/runc/libcontainer/stacktrace",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/system", "ImportPath": "github.com/opencontainers/runc/libcontainer/system",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/user", "ImportPath": "github.com/opencontainers/runc/libcontainer/user",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/opencontainers/runc/libcontainer/utils", "ImportPath": "github.com/opencontainers/runc/libcontainer/utils",
"Comment": "v1.0.0-rc1-100-g142df38", "Comment": "v1.0.0-rc2-14-g45c30e7",
"Rev": "142df3836b740af53dc6da59eed8dbc92f62917c" "Rev": "45c30e75abfd52107b53048004a83165403ad0d1"
}, },
{ {
"ImportPath": "github.com/pborman/uuid", "ImportPath": "github.com/pborman/uuid",
@ -2152,7 +2152,7 @@
}, },
{ {
"ImportPath": "github.com/syndtr/gocapability/capability", "ImportPath": "github.com/syndtr/gocapability/capability",
"Rev": "2c00daeb6c3b45114c80ac44119e7b8801fdd852" "Rev": "e7cb7fa329f456b3855136a2642b197bad7366ba"
}, },
{ {
"ImportPath": "github.com/ugorji/go/codec", "ImportPath": "github.com/ugorji/go/codec",

View File

@ -15,15 +15,18 @@
package collector package collector
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io"
"math"
"net/http" "net/http"
"strconv" "sort"
"strings"
"time" "time"
rawmodel "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
"github.com/google/cadvisor/container" "github.com/google/cadvisor/container"
"github.com/google/cadvisor/info/v1" "github.com/google/cadvisor/info/v1"
) )
@ -100,62 +103,104 @@ func (collector *PrometheusCollector) Name() string {
return collector.name return collector.name
} }
func getMetricData(line string) string {
fields := strings.Fields(line)
data := fields[3]
if len(fields) > 4 {
for i := range fields {
if i > 3 {
data = data + "_" + fields[i]
}
}
}
return strings.TrimSpace(data)
}
func (collector *PrometheusCollector) GetSpec() []v1.MetricSpec { func (collector *PrometheusCollector) GetSpec() []v1.MetricSpec {
specs := []v1.MetricSpec{}
response, err := collector.httpClient.Get(collector.configFile.Endpoint.URL) response, err := collector.httpClient.Get(collector.configFile.Endpoint.URL)
if err != nil { if err != nil {
return specs return nil
} }
defer response.Body.Close() defer response.Body.Close()
pageContent, err := ioutil.ReadAll(response.Body) if response.StatusCode != http.StatusOK {
if err != nil { return nil
return specs
} }
lines := strings.Split(string(pageContent), "\n") dec := expfmt.NewDecoder(response.Body, expfmt.ResponseFormat(response.Header))
lineCount := len(lines)
for i, line := range lines { var specs []v1.MetricSpec
if strings.HasPrefix(line, "# HELP") {
if i+2 >= lineCount { for {
d := rawmodel.MetricFamily{}
if err = dec.Decode(&d); err != nil {
break break
} }
name := d.GetName()
stopIndex := strings.IndexAny(lines[i+2], "{ ") if len(name) == 0 {
if stopIndex == -1 {
continue continue
} }
// If metrics to collect is specified, skip any metrics not in the list to collect.
name := strings.TrimSpace(lines[i+2][0:stopIndex])
if _, ok := collector.metricsSet[name]; collector.metricsSet != nil && !ok { if _, ok := collector.metricsSet[name]; collector.metricsSet != nil && !ok {
continue continue
} }
spec := v1.MetricSpec{ spec := v1.MetricSpec{
Name: name, Name: name,
Type: v1.MetricType(getMetricData(lines[i+1])), Type: metricType(d.GetType()),
Format: "float", Format: v1.FloatType,
Units: getMetricData(lines[i]),
} }
specs = append(specs, spec) specs = append(specs, spec)
} }
if err != nil && err != io.EOF {
return nil
} }
return specs return specs
} }
// metricType converts Prometheus metric type to cadvisor metric type.
// If there is no mapping then just return the name of the Prometheus metric type.
func metricType(t rawmodel.MetricType) v1.MetricType {
switch t {
case rawmodel.MetricType_COUNTER:
return v1.MetricCumulative
case rawmodel.MetricType_GAUGE:
return v1.MetricGauge
default:
return v1.MetricType(t.String())
}
}
type prometheusLabels []*rawmodel.LabelPair
func labelSetToLabelPairs(labels model.Metric) prometheusLabels {
var promLabels prometheusLabels
for k, v := range labels {
name := string(k)
value := string(v)
promLabels = append(promLabels, &rawmodel.LabelPair{Name: &name, Value: &value})
}
return promLabels
}
func (s prometheusLabels) Len() int { return len(s) }
func (s prometheusLabels) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// ByName implements sort.Interface by providing Less and using the Len and
// Swap methods of the embedded PrometheusLabels value.
type byName struct{ prometheusLabels }
func (s byName) Less(i, j int) bool {
return s.prometheusLabels[i].GetName() < s.prometheusLabels[j].GetName()
}
func prometheusLabelSetToCadvisorLabel(promLabels model.Metric) string {
labels := labelSetToLabelPairs(promLabels)
sort.Sort(byName{labels})
var b bytes.Buffer
for i, l := range labels {
if i > 0 {
b.WriteString("\xff")
}
b.WriteString(l.GetName())
b.WriteString("=")
b.WriteString(l.GetValue())
}
return string(b.Bytes())
}
// Returns collected metrics and the next collection time of the collector // Returns collected metrics and the next collection time of the collector
func (collector *PrometheusCollector) Collect(metrics map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) { func (collector *PrometheusCollector) Collect(metrics map[string][]v1.MetricVal) (time.Time, map[string][]v1.MetricVal, error) {
currentTime := time.Now() currentTime := time.Now()
@ -168,59 +213,61 @@ func (collector *PrometheusCollector) Collect(metrics map[string][]v1.MetricVal)
} }
defer response.Body.Close() defer response.Body.Close()
pageContent, err := ioutil.ReadAll(response.Body) if response.StatusCode != http.StatusOK {
if err != nil { return nextCollectionTime, nil, fmt.Errorf("server returned HTTP status %s", response.Status)
return nextCollectionTime, nil, err
} }
var errorSlice []error sdec := expfmt.SampleDecoder{
lines := strings.Split(string(pageContent), "\n") Dec: expfmt.NewDecoder(response.Body, expfmt.ResponseFormat(response.Header)),
Opts: &expfmt.DecodeOptions{
Timestamp: model.TimeFromUnixNano(currentTime.UnixNano()),
},
}
newMetrics := make(map[string][]v1.MetricVal) var (
// 50 is chosen as a reasonable guesstimate at a number of metrics we can
for _, line := range lines { // expect from virtually any endpoint to try to save allocations.
if line == "" { decSamples = make(model.Vector, 0, 50)
newMetrics = make(map[string][]v1.MetricVal)
)
for {
if err = sdec.Decode(&decSamples); err != nil {
break break
} }
if !strings.HasPrefix(line, "# HELP") && !strings.HasPrefix(line, "# TYPE") {
var metLabel string
startLabelIndex := strings.Index(line, "{")
spaceIndex := strings.Index(line, " ")
if startLabelIndex == -1 {
startLabelIndex = spaceIndex
}
metName := strings.TrimSpace(line[0:startLabelIndex]) for _, sample := range decSamples {
metName := string(sample.Metric[model.MetricNameLabel])
if len(metName) == 0 {
continue
}
// If metrics to collect is specified, skip any metrics not in the list to collect.
if _, ok := collector.metricsSet[metName]; collector.metricsSet != nil && !ok { if _, ok := collector.metricsSet[metName]; collector.metricsSet != nil && !ok {
continue continue
} }
// TODO Handle multiple labels nicer. Prometheus metrics can have multiple
if startLabelIndex+1 <= spaceIndex-1 { // labels, cadvisor only accepts a single string for the metric label.
metLabel = strings.TrimSpace(line[(startLabelIndex + 1):(spaceIndex - 1)]) label := prometheusLabelSetToCadvisorLabel(sample.Metric)
}
metVal, err := strconv.ParseFloat(line[spaceIndex+1:], 64)
if err != nil {
errorSlice = append(errorSlice, err)
}
if math.IsNaN(metVal) {
metVal = 0
}
metric := v1.MetricVal{ metric := v1.MetricVal{
Label: metLabel, FloatValue: float64(sample.Value),
FloatValue: metVal, Timestamp: sample.Timestamp.Time(),
Timestamp: currentTime, Label: label,
} }
newMetrics[metName] = append(newMetrics[metName], metric) newMetrics[metName] = append(newMetrics[metName], metric)
if len(newMetrics) > collector.metricCountLimit { if len(newMetrics) > collector.metricCountLimit {
return nextCollectionTime, nil, fmt.Errorf("too many metrics to collect") return nextCollectionTime, nil, fmt.Errorf("too many metrics to collect")
} }
} }
decSamples = decSamples[:0]
} }
if err != nil && err != io.EOF {
return nextCollectionTime, nil, err
}
for key, val := range newMetrics { for key, val := range newMetrics {
metrics[key] = append(metrics[key], val...) metrics[key] = append(metrics[key], val...)
} }
return nextCollectionTime, metrics, compileErrors(errorSlice) return nextCollectionTime, metrics, nil
} }

View File

@ -45,7 +45,7 @@ type CgroupSubsystems struct {
// Get information about the cgroup subsystems. // Get information about the cgroup subsystems.
func GetCgroupSubsystems() (CgroupSubsystems, error) { func GetCgroupSubsystems() (CgroupSubsystems, error) {
// Get all cgroup mounts. // Get all cgroup mounts.
allCgroups, err := cgroups.GetCgroupMounts() allCgroups, err := cgroups.GetCgroupMounts(true)
if err != nil { if err != nil {
return CgroupSubsystems{}, err return CgroupSubsystems{}, err
} }

View File

@ -26,10 +26,10 @@ const (
MetricGauge MetricType = "gauge" MetricGauge MetricType = "gauge"
// A counter-like value that is only expected to increase. // A counter-like value that is only expected to increase.
MetricCumulative = "cumulative" MetricCumulative MetricType = "cumulative"
// Rate over a time period. // Rate over a time period.
MetricDelta = "delta" MetricDelta MetricType = "delta"
) )
// DataType for metric being exported. // DataType for metric being exported.
@ -37,7 +37,7 @@ type DataType string
const ( const (
IntType DataType = "int" IntType DataType = "int"
FloatType = "float" FloatType DataType = "float"
) )
// Spec for custom metric. // Spec for custom metric.

File diff suppressed because one or more lines are too long

View File

@ -98,7 +98,7 @@ func pagesAssetsHtmlContainersHtml() (*asset, error) {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "pages/assets/html/containers.html", size: 9533, mode: os.FileMode(416), modTime: time.Unix(1462817463, 0)} info := bindataFileInfo{name: "pages/assets/html/containers.html", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }

View File

@ -83,6 +83,7 @@ config := &configs.Config{
}, },
MaskPaths: []string{ MaskPaths: []string{
"/proc/kcore", "/proc/kcore",
"/sys/firmware",
}, },
ReadonlyPaths: []string{ ReadonlyPaths: []string{
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus", "/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
@ -184,7 +185,7 @@ process := &libcontainer.Process{
Stderr: os.Stderr, Stderr: os.Stderr,
} }
err := container.Start(process) err := container.Run(process)
if err != nil { if err != nil {
container.Destroy() container.Destroy()
logrus.Fatal(err) logrus.Fatal(err)

View File

@ -71,7 +71,6 @@ that are required for executing a container's process.
| /dev/tty | 0666 | rwm | | /dev/tty | 0666 | rwm |
| /dev/random | 0666 | rwm | | /dev/random | 0666 | rwm |
| /dev/urandom | 0666 | rwm | | /dev/urandom | 0666 | rwm |
| /dev/fuse | 0666 | rwm |
**ptmx** **ptmx**

View File

@ -10,7 +10,7 @@ import (
"github.com/syndtr/gocapability/capability" "github.com/syndtr/gocapability/capability"
) )
const allCapabilityTypes = capability.CAPS | capability.BOUNDS const allCapabilityTypes = capability.CAPS | capability.BOUNDS | capability.AMBS
var capabilityMap map[string]capability.Cap var capabilityMap map[string]capability.Cap

View File

@ -37,7 +37,7 @@ type Manager interface {
// restore the object later. // restore the object later.
GetPaths() map[string]string GetPaths() map[string]string
// Set the cgroup as configured. // Sets the cgroup as configured.
Set(container *configs.Config) error Set(container *configs.Config) error
} }

View File

@ -104,6 +104,8 @@ func (m *Manager) Apply(pid int) (err error) {
if m.Cgroups == nil { if m.Cgroups == nil {
return nil return nil
} }
m.mu.Lock()
defer m.mu.Unlock()
var c = m.Cgroups var c = m.Cgroups
@ -128,8 +130,6 @@ func (m *Manager) Apply(pid int) (err error) {
return cgroups.EnterPid(m.Paths, pid) return cgroups.EnterPid(m.Paths, pid)
} }
m.mu.Lock()
defer m.mu.Unlock()
paths := make(map[string]string) paths := make(map[string]string)
for _, sys := range subsystems { for _, sys := range subsystems {
if err := sys.Apply(d); err != nil { if err := sys.Apply(d); err != nil {
@ -195,18 +195,10 @@ func (m *Manager) Set(container *configs.Config) error {
if m.Cgroups.Paths != nil { if m.Cgroups.Paths != nil {
return nil return nil
} }
for _, sys := range subsystems {
// Generate fake cgroup data.
d, err := getCgroupData(container.Cgroups, -1)
if err != nil {
return err
}
// Get the path, but don't error out if the cgroup wasn't found.
path, err := d.path(sys.Name())
if err != nil && !cgroups.IsNotFound(err) {
return err
}
paths := m.GetPaths()
for _, sys := range subsystems {
path := paths[sys.Name()]
if err := sys.Set(path, container.Cgroups); err != nil { if err := sys.Set(path, container.Cgroups); err != nil {
return err return err
} }
@ -223,14 +215,8 @@ func (m *Manager) Set(container *configs.Config) error {
// Freeze toggles the container's freezer cgroup depending on the state // Freeze toggles the container's freezer cgroup depending on the state
// provided // provided
func (m *Manager) Freeze(state configs.FreezerState) error { func (m *Manager) Freeze(state configs.FreezerState) error {
d, err := getCgroupData(m.Cgroups, 0) paths := m.GetPaths()
if err != nil { dir := paths["freezer"]
return err
}
dir, err := d.path("freezer")
if err != nil {
return err
}
prevState := m.Cgroups.Resources.Freezer prevState := m.Cgroups.Resources.Freezer
m.Cgroups.Resources.Freezer = state m.Cgroups.Resources.Freezer = state
freezer, err := subsystems.Get("freezer") freezer, err := subsystems.Get("freezer")
@ -246,28 +232,13 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
} }
func (m *Manager) GetPids() ([]int, error) { func (m *Manager) GetPids() ([]int, error) {
dir, err := getCgroupPath(m.Cgroups) paths := m.GetPaths()
if err != nil { return cgroups.GetPids(paths["devices"])
return nil, err
}
return cgroups.GetPids(dir)
} }
func (m *Manager) GetAllPids() ([]int, error) { func (m *Manager) GetAllPids() ([]int, error) {
dir, err := getCgroupPath(m.Cgroups) paths := m.GetPaths()
if err != nil { return cgroups.GetAllPids(paths["devices"])
return nil, err
}
return cgroups.GetAllPids(dir)
}
func getCgroupPath(c *configs.Cgroup) (string, error) {
d, err := getCgroupData(c, 0)
if err != nil {
return "", err
}
return d.path("devices")
} }
func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) { func getCgroupData(c *configs.Cgroup, pid int) (*cgroupData, error) {

View File

@ -22,10 +22,48 @@ func (s *CpuGroup) Name() string {
func (s *CpuGroup) Apply(d *cgroupData) error { func (s *CpuGroup) Apply(d *cgroupData) error {
// We always want to join the cpu group, to allow fair cpu scheduling // We always want to join the cpu group, to allow fair cpu scheduling
// on a container basis // on a container basis
_, err := d.join("cpu") path, err := d.path("cpu")
if err != nil && !cgroups.IsNotFound(err) { if err != nil && !cgroups.IsNotFound(err) {
return err return err
} }
return s.ApplyDir(path, d.config, d.pid)
}
func (s *CpuGroup) 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
}
// We should set the real-Time group scheduling settings before moving
// in the process because if the process is already in SCHED_RR mode
// and no RT bandwidth is set, adding it will fail.
if err := s.SetRtSched(path, 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
if err := cgroups.WriteCgroupProc(path, pid); err != nil {
return err
}
return nil
}
func (s *CpuGroup) SetRtSched(path string, cgroup *configs.Cgroup) error {
if cgroup.Resources.CpuRtPeriod != 0 {
if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(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 {
return err
}
}
return nil return nil
} }
@ -45,16 +83,9 @@ func (s *CpuGroup) Set(path string, cgroup *configs.Cgroup) error {
return err return err
} }
} }
if cgroup.Resources.CpuRtPeriod != 0 { if err := s.SetRtSched(path, cgroup); err != nil {
if err := writeFile(path, "cpu.rt_period_us", strconv.FormatInt(cgroup.Resources.CpuRtPeriod, 10)); err != nil {
return err return err
} }
}
if cgroup.Resources.CpuRtRuntime != 0 {
if err := writeFile(path, "cpu.rt_runtime_us", strconv.FormatInt(cgroup.Resources.CpuRtRuntime, 10)); err != nil {
return err
}
}
return nil return nil
} }

View File

@ -16,9 +16,7 @@ import (
"github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs"
) )
const ( const cgroupKernelMemoryLimit = "memory.kmem.limit_in_bytes"
cgroupKernelMemoryLimit = "memory.kmem.limit_in_bytes"
)
type MemoryGroup struct { type MemoryGroup struct {
} }
@ -38,10 +36,12 @@ func (s *MemoryGroup) Apply(d *cgroupData) (err error) {
return err return err
} }
} }
if d.config.KernelMemory != 0 {
if err := EnableKernelMemoryAccounting(path); err != nil { if err := EnableKernelMemoryAccounting(path); err != nil {
return err return err
} }
} }
}
defer func() { defer func() {
if err != nil { if err != nil {
os.RemoveAll(path) os.RemoveAll(path)
@ -62,13 +62,10 @@ func EnableKernelMemoryAccounting(path string) error {
// We have to limit the kernel memory here as it won't be accounted at all // We have to limit the kernel memory here as it won't be accounted at all
// until a limit is set on the cgroup and limit cannot be set once the // until a limit is set on the cgroup and limit cannot be set once the
// cgroup has children, or if there are already tasks in the cgroup. // cgroup has children, or if there are already tasks in the cgroup.
kernelMemoryLimit := int64(1) for _, i := range []int64{1, -1} {
if err := setKernelMemory(path, kernelMemoryLimit); err != nil { if err := setKernelMemory(path, i); err != nil {
return err return err
} }
kernelMemoryLimit = int64(-1)
if err := setKernelMemory(path, kernelMemoryLimit); err != nil {
return err
} }
return nil return nil
} }

View File

@ -8,7 +8,6 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -67,12 +66,14 @@ var subsystems = subsystemSet{
const ( const (
testScopeWait = 4 testScopeWait = 4
testSliceWait = 4
) )
var ( var (
connLock sync.Mutex connLock sync.Mutex
theConn *systemdDbus.Conn theConn *systemdDbus.Conn
hasStartTransientUnit bool hasStartTransientUnit bool
hasStartTransientSliceUnit bool
hasTransientDefaultDependencies bool hasTransientDefaultDependencies bool
hasDelegate bool hasDelegate bool
) )
@ -159,8 +160,36 @@ func UseSystemd() bool {
} }
} }
// Assume we have the ability to start a transient unit as a slice
// This was broken until systemd v229, but has been back-ported on RHEL environments >= 219
// For details, see: https://bugzilla.redhat.com/show_bug.cgi?id=1370299
hasStartTransientSliceUnit = true
// To ensure simple clean-up, we create a slice off the root with no hierarchy
slice := fmt.Sprintf("libcontainer_%d_systemd_test_default.slice", os.Getpid())
if _, err := theConn.StartTransientUnit(slice, "replace", nil, nil); err != nil {
if _, ok := err.(dbus.Error); ok {
hasStartTransientSliceUnit = false
}
}
for i := 0; i <= testSliceWait; i++ {
if _, err := theConn.StopUnit(slice, "replace", nil); err != nil {
if dbusError, ok := err.(dbus.Error); ok {
if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") {
hasStartTransientSliceUnit = false
break
}
}
} else {
break
}
time.Sleep(time.Millisecond)
}
// Not critical because of the stop unit logic above. // Not critical because of the stop unit logic above.
theConn.StopUnit(scope, "replace", nil) theConn.StopUnit(scope, "replace", nil)
theConn.StopUnit(slice, "replace", nil)
} }
return hasStartTransientUnit return hasStartTransientUnit
} }
@ -194,11 +223,24 @@ func (m *Manager) Apply(pid int) error {
slice = c.Parent slice = c.Parent
} }
properties = append(properties, properties = append(properties, systemdDbus.PropDescription("libcontainer container "+c.Name))
systemdDbus.PropSlice(slice),
systemdDbus.PropDescription("docker container "+c.Name), // if we create a slice, the parent is defined via a Wants=
newProp("PIDs", []uint32{uint32(pid)}), if strings.HasSuffix(unitName, ".slice") {
) // This was broken until systemd v229, but has been back-ported on RHEL environments >= 219
if !hasStartTransientSliceUnit {
return fmt.Errorf("systemd version does not support ability to start a slice as transient unit")
}
properties = append(properties, systemdDbus.PropWants(slice))
} else {
// otherwise, we use Slice=
properties = append(properties, systemdDbus.PropSlice(slice))
}
// only add pid if its valid, -1 is used w/ general slice creation.
if pid != -1 {
properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
}
if hasDelegate { if hasDelegate {
// This is only supported on systemd versions 218 and above. // This is only supported on systemd versions 218 and above.
@ -302,10 +344,9 @@ func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
if err := os.MkdirAll(path, 0755); err != nil { if err := os.MkdirAll(path, 0755); err != nil {
return "", err return "", err
} }
if err := writeFile(path, "cgroup.procs", strconv.Itoa(pid)); err != nil { if err := cgroups.WriteCgroupProc(path, pid); err != nil {
return "", err return "", err
} }
return path, nil return path, nil
} }
@ -350,7 +391,7 @@ func joinCgroups(c *configs.Cgroup, pid int) error {
// systemd represents slice heirarchy using `-`, so we need to follow suit when // systemd represents slice heirarchy using `-`, so we need to follow suit when
// generating the path of slice. Essentially, test-a-b.slice becomes // generating the path of slice. Essentially, test-a-b.slice becomes
// test.slice/test-a.slice/test-a-b.slice. // test.slice/test-a.slice/test-a-b.slice.
func expandSlice(slice string) (string, error) { func ExpandSlice(slice string) (string, error) {
suffix := ".slice" suffix := ".slice"
// Name has to end with ".slice", but can't be just ".slice". // Name has to end with ".slice", but can't be just ".slice".
if len(slice) < len(suffix) || !strings.HasSuffix(slice, suffix) { if len(slice) < len(suffix) || !strings.HasSuffix(slice, suffix) {
@ -364,6 +405,10 @@ func expandSlice(slice string) (string, error) {
var path, prefix string var path, prefix string
sliceName := strings.TrimSuffix(slice, suffix) sliceName := strings.TrimSuffix(slice, suffix)
// if input was -.slice, we should just return root now
if sliceName == "-" {
return "/", nil
}
for _, component := range strings.Split(sliceName, "-") { for _, component := range strings.Split(sliceName, "-") {
// test--a.slice isn't permitted, nor is -test.slice. // test--a.slice isn't permitted, nor is -test.slice.
if component == "" { if component == "" {
@ -396,7 +441,7 @@ func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
slice = c.Parent slice = c.Parent
} }
slice, err = expandSlice(slice) slice, err = ExpandSlice(slice)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -483,8 +528,12 @@ func (m *Manager) Set(container *configs.Config) error {
} }
func getUnitName(c *configs.Cgroup) string { func getUnitName(c *configs.Cgroup) string {
// by default, we create a scope unless the user explicitly asks for a slice.
if !strings.HasSuffix(c.Name, ".slice") {
return fmt.Sprintf("%s-%s.scope", c.ScopePrefix, c.Name) return fmt.Sprintf("%s-%s.scope", c.ScopePrefix, c.Name)
} }
return c.Name
}
func setKernelMemory(c *configs.Cgroup) error { func setKernelMemory(c *configs.Cgroup) error {
path, err := getSubsystemPath(c, "memory") path, err := getSubsystemPath(c, "memory")

View File

@ -139,7 +139,7 @@ func (m Mount) GetThisCgroupDir(cgroups map[string]string) (string, error) {
return getControllerPath(m.Subsystems[0], cgroups) return getControllerPath(m.Subsystems[0], cgroups)
} }
func getCgroupMountsHelper(ss map[string]bool, mi io.Reader) ([]Mount, error) { func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount, error) {
res := make([]Mount, 0, len(ss)) res := make([]Mount, 0, len(ss))
scanner := bufio.NewScanner(mi) scanner := bufio.NewScanner(mi)
numFound := 0 numFound := 0
@ -166,8 +166,10 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader) ([]Mount, error) {
} else { } else {
m.Subsystems = append(m.Subsystems, opt) m.Subsystems = append(m.Subsystems, opt)
} }
if !all {
numFound++ numFound++
} }
}
res = append(res, m) res = append(res, m)
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
@ -176,23 +178,25 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader) ([]Mount, error) {
return res, nil return res, nil
} }
func GetCgroupMounts() ([]Mount, error) { // GetCgroupMounts returns the mounts for the cgroup subsystems.
// all indicates whether to return just the first instance or all the mounts.
func GetCgroupMounts(all bool) ([]Mount, error) {
f, err := os.Open("/proc/self/mountinfo") f, err := os.Open("/proc/self/mountinfo")
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
all, err := ParseCgroupFile("/proc/self/cgroup") allSubsystems, err := ParseCgroupFile("/proc/self/cgroup")
if err != nil { if err != nil {
return nil, err return nil, err
} }
allMap := make(map[string]bool) allMap := make(map[string]bool)
for s := range all { for s := range allSubsystems {
allMap[s] = true allMap[s] = true
} }
return getCgroupMountsHelper(allMap, f) return getCgroupMountsHelper(allMap, f, all)
} }
// GetAllSubsystems returns all the cgroup subsystems supported by the kernel // GetAllSubsystems returns all the cgroup subsystems supported by the kernel

View File

@ -120,5 +120,5 @@ type Resources struct {
NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"` NetPrioIfpriomap []*IfPrioMap `json:"net_prio_ifpriomap"`
// Set class identifier for container's network packets // Set class identifier for container's network packets
NetClsClassid uint32 `json:"net_cls_classid"` NetClsClassid uint32 `json:"net_cls_classid_u"`
} }

View File

@ -300,29 +300,38 @@ func (c Command) Run(s HookState) error {
if err != nil { if err != nil {
return err return err
} }
var stdout, stderr bytes.Buffer
cmd := exec.Cmd{ cmd := exec.Cmd{
Path: c.Path, Path: c.Path,
Args: c.Args, Args: c.Args,
Env: c.Env, Env: c.Env,
Stdin: bytes.NewReader(b), Stdin: bytes.NewReader(b),
Stdout: &stdout,
Stderr: &stderr,
}
if err := cmd.Start(); err != nil {
return err
} }
errC := make(chan error, 1) errC := make(chan error, 1)
go func() { go func() {
out, err := cmd.CombinedOutput() err := cmd.Wait()
if err != nil { if err != nil {
err = fmt.Errorf("%s: %s", err, out) err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
} }
errC <- err errC <- err
}() }()
var timerCh <-chan time.Time
if c.Timeout != nil { if c.Timeout != nil {
timer := time.NewTimer(*c.Timeout)
defer timer.Stop()
timerCh = timer.C
}
select { select {
case err := <-errC: case err := <-errC:
return err return err
case <-time.After(*c.Timeout): case <-timerCh:
cmd.Process.Kill() cmd.Process.Kill()
cmd.Wait() cmd.Wait()
return fmt.Errorf("hook ran past specified timeout of %.1fs", c.Timeout.Seconds()) return fmt.Errorf("hook ran past specified timeout of %.1fs", c.Timeout.Seconds())
} }
} }
return <-errC
}

View File

@ -107,19 +107,5 @@ var (
Permissions: "rwm", Permissions: "rwm",
}, },
}, DefaultSimpleDevices...) }, DefaultSimpleDevices...)
DefaultAutoCreatedDevices = append([]*Device{ DefaultAutoCreatedDevices = append([]*Device{}, DefaultSimpleDevices...)
{
// /dev/fuse is created but not allowed.
// This is to allow java to work. Because java
// Insists on there being a /dev/fuse
// https://github.com/docker/docker/issues/514
// https://github.com/docker/docker/issues/2393
//
Path: "/dev/fuse",
Type: 'c',
Major: 10,
Minor: 229,
Permissions: "rwm",
},
}, DefaultSimpleDevices...)
) )

View File

@ -75,8 +75,8 @@ type BaseContainer interface {
// Returns the current status of the container. // Returns the current status of the container.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// SystemError - System error. // Systemerror - System error.
Status() (Status, error) Status() (Status, error)
// State returns the current container's state information. // State returns the current container's state information.
@ -91,8 +91,8 @@ type BaseContainer interface {
// Returns the PIDs inside this container. The PIDs are in the namespace of the calling process. // Returns the PIDs inside this container. The PIDs are in the namespace of the calling process.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// SystemError - System error. // Systemerror - System error.
// //
// Some of the returned PIDs may no longer refer to processes in the Container, unless // Some of the returned PIDs may no longer refer to processes in the Container, unless
// the Container state is PAUSED in which case every PID in the slice is valid. // the Container state is PAUSED in which case every PID in the slice is valid.
@ -101,8 +101,8 @@ type BaseContainer interface {
// Returns statistics for the container. // Returns statistics for the container.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// SystemError - System error. // Systemerror - System error.
Stats() (*Stats, error) Stats() (*Stats, error)
// Set resources of container as configured // Set resources of container as configured
@ -117,7 +117,7 @@ type BaseContainer interface {
// start. You can track process lifecycle with passed Process structure. // start. You can track process lifecycle with passed Process structure.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// ConfigInvalid - config is invalid, // ConfigInvalid - config is invalid,
// ContainerPaused - Container is paused, // ContainerPaused - Container is paused,
// SystemError - System error. // SystemError - System error.
@ -128,7 +128,7 @@ type BaseContainer interface {
// opens the fifo after start returns. // opens the fifo after start returns.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// ConfigInvalid - config is invalid, // ConfigInvalid - config is invalid,
// ContainerPaused - Container is paused, // ContainerPaused - Container is paused,
// SystemError - System error. // SystemError - System error.

View File

@ -35,7 +35,6 @@ type linuxContainer struct {
root string root string
config *configs.Config config *configs.Config
cgroupManager cgroups.Manager cgroupManager cgroups.Manager
initPath string
initArgs []string initArgs []string
initProcess parentProcess initProcess parentProcess
initProcessStartTime string initProcessStartTime string
@ -86,13 +85,14 @@ type Container interface {
// Systemerror - System error. // Systemerror - System error.
Restore(process *Process, criuOpts *CriuOpts) error Restore(process *Process, criuOpts *CriuOpts) error
// If the Container state is RUNNING, sets the Container state to PAUSING and pauses // If the Container state is RUNNING or CREATED, sets the Container state to PAUSING and pauses
// the execution of any user processes. Asynchronously, when the container finished being paused the // the execution of any user processes. Asynchronously, when the container finished being paused the
// state is changed to PAUSED. // state is changed to PAUSED.
// If the Container state is PAUSED, do nothing. // If the Container state is PAUSED, do nothing.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// ContainerNotRunning - Container not running or created,
// Systemerror - System error. // Systemerror - System error.
Pause() error Pause() error
@ -101,7 +101,8 @@ type Container interface {
// If the Container state is RUNNING, do nothing. // If the Container state is RUNNING, do nothing.
// //
// errors: // errors:
// ContainerDestroyed - Container no longer exists, // ContainerNotExists - Container no longer exists,
// ContainerNotPaused - Container is not paused,
// Systemerror - System error. // Systemerror - System error.
Resume() error Resume() error
@ -308,10 +309,7 @@ func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProces
} }
func (c *linuxContainer) commandTemplate(p *Process, childPipe, rootDir *os.File) (*exec.Cmd, error) { func (c *linuxContainer) commandTemplate(p *Process, childPipe, rootDir *os.File) (*exec.Cmd, error) {
cmd := &exec.Cmd{ cmd := exec.Command(c.initArgs[0], c.initArgs[1:]...)
Path: c.initPath,
Args: c.initArgs,
}
cmd.Stdin = p.Stdin cmd.Stdin = p.Stdin
cmd.Stdout = p.Stdout cmd.Stdout = p.Stdout
cmd.Stderr = p.Stderr cmd.Stderr = p.Stderr
@ -447,7 +445,7 @@ func (c *linuxContainer) Pause() error {
c: c, c: c,
}) })
} }
return newGenericError(fmt.Errorf("container not running: %s", status), ContainerNotRunning) return newGenericError(fmt.Errorf("container not running or created: %s", status), ContainerNotRunning)
} }
func (c *linuxContainer) Resume() error { func (c *linuxContainer) Resume() error {
@ -1049,6 +1047,8 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
}); err != nil { }); err != nil {
return err return err
} }
// create a timestamp indicating when the restored checkpoint was started
c.created = time.Now().UTC()
if _, err := c.updateState(r); err != nil { if _, err := c.updateState(r); err != nil {
return err return err
} }

View File

@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime/debug" "runtime/debug"
@ -33,32 +32,9 @@ var (
) )
// InitArgs returns an options func to configure a LinuxFactory with the // InitArgs returns an options func to configure a LinuxFactory with the
// provided init arguments. // provided init binary path and arguments.
func InitArgs(args ...string) func(*LinuxFactory) error { func InitArgs(args ...string) func(*LinuxFactory) error {
return func(l *LinuxFactory) error { return func(l *LinuxFactory) error {
name := args[0]
if filepath.Base(name) == name {
if lp, err := exec.LookPath(name); err == nil {
name = lp
}
} else {
abs, err := filepath.Abs(name)
if err != nil {
return err
}
name = abs
}
l.InitPath = "/proc/self/exe"
l.InitArgs = append([]string{name}, args[1:]...)
return nil
}
}
// InitPath returns an options func to configure a LinuxFactory with the
// provided absolute path to the init binary and arguements.
func InitPath(path string, args ...string) func(*LinuxFactory) error {
return func(l *LinuxFactory) error {
l.InitPath = path
l.InitArgs = args l.InitArgs = args
return nil return nil
} }
@ -122,10 +98,10 @@ func New(root string, options ...func(*LinuxFactory) error) (Factory, error) {
} }
l := &LinuxFactory{ l := &LinuxFactory{
Root: root, Root: root,
InitArgs: []string{"/proc/self/exe", "init"},
Validator: validate.New(), Validator: validate.New(),
CriuPath: "criu", CriuPath: "criu",
} }
InitArgs(os.Args[0], "init")(l)
Cgroupfs(l) Cgroupfs(l)
for _, opt := range options { for _, opt := range options {
if err := opt(l); err != nil { if err := opt(l); err != nil {
@ -140,9 +116,6 @@ type LinuxFactory struct {
// Root directory for the factory to store state. // Root directory for the factory to store state.
Root string Root string
// InitPath is the absolute path to the init binary.
InitPath string
// InitArgs are arguments for calling the init responsibilities for spawning // InitArgs are arguments for calling the init responsibilities for spawning
// a container. // a container.
InitArgs []string InitArgs []string
@ -202,7 +175,6 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err
id: id, id: id,
root: containerRoot, root: containerRoot,
config: config, config: config,
initPath: l.InitPath,
initArgs: l.InitArgs, initArgs: l.InitArgs,
criuPath: l.CriuPath, criuPath: l.CriuPath,
cgroupManager: l.NewCgroupsManager(config.Cgroups, nil), cgroupManager: l.NewCgroupsManager(config.Cgroups, nil),
@ -216,7 +188,7 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid) return nil, newGenericError(fmt.Errorf("invalid root"), ConfigInvalid)
} }
containerRoot := filepath.Join(l.Root, id) containerRoot := filepath.Join(l.Root, id)
state, err := l.loadState(containerRoot) state, err := l.loadState(containerRoot, id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -230,7 +202,6 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
initProcessStartTime: state.InitProcessStartTime, initProcessStartTime: state.InitProcessStartTime,
id: id, id: id,
config: &state.Config, config: &state.Config,
initPath: l.InitPath,
initArgs: l.InitArgs, initArgs: l.InitArgs,
criuPath: l.CriuPath, criuPath: l.CriuPath,
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths), cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
@ -252,17 +223,21 @@ func (l *LinuxFactory) Type() string {
// This is a low level implementation detail of the reexec and should not be consumed externally // This is a low level implementation detail of the reexec and should not be consumed externally
func (l *LinuxFactory) StartInitialization() (err error) { func (l *LinuxFactory) StartInitialization() (err error) {
var pipefd, rootfd int var pipefd, rootfd int
for k, v := range map[string]*int{ for _, pair := range []struct {
"_LIBCONTAINER_INITPIPE": &pipefd, k string
"_LIBCONTAINER_STATEDIR": &rootfd, v *int
}{ }{
s := os.Getenv(k) {"_LIBCONTAINER_INITPIPE", &pipefd},
{"_LIBCONTAINER_STATEDIR", &rootfd},
} {
s := os.Getenv(pair.k)
i, err := strconv.Atoi(s) i, err := strconv.Atoi(s)
if err != nil { if err != nil {
return fmt.Errorf("unable to convert %s=%s to int", k, s) return fmt.Errorf("unable to convert %s=%s to int", pair.k, s)
} }
*v = i *pair.v = i
} }
var ( var (
pipe = os.NewFile(uintptr(pipefd), "pipe") pipe = os.NewFile(uintptr(pipefd), "pipe")
@ -302,11 +277,11 @@ func (l *LinuxFactory) StartInitialization() (err error) {
return i.Init() return i.Init()
} }
func (l *LinuxFactory) loadState(root string) (*State, error) { func (l *LinuxFactory) loadState(root, id string) (*State, error) {
f, err := os.Open(filepath.Join(root, stateFilename)) f, err := os.Open(filepath.Join(root, stateFilename))
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil, newGenericError(err, ContainerNotExists) return nil, newGenericError(fmt.Errorf("container %q does not exist", id), ContainerNotExists)
} }
return nil, newGenericError(err, SystemError) return nil, newGenericError(err, SystemError)
} }

View File

@ -67,9 +67,6 @@ func newSystemErrorWithCause(err error, cause string) Error {
// stack frames skipped. This is only to be called by the other functions for // stack frames skipped. This is only to be called by the other functions for
// formatting the error. // formatting the error.
func createSystemError(err error, cause string) Error { func createSystemError(err error, cause string) Error {
if le, ok := err.(Error); ok {
return le
}
gerr := &genericError{ gerr := &genericError{
Timestamp: time.Now(), Timestamp: time.Now(),
Err: err, Err: err,

View File

@ -144,7 +144,7 @@ func finalizeNamespace(config *initConfig) error {
} }
if config.Cwd != "" { if config.Cwd != "" {
if err := syscall.Chdir(config.Cwd); err != nil { if err := syscall.Chdir(config.Cwd); err != nil {
return err return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err)
} }
} }
return nil return nil

View File

@ -129,7 +129,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true} exclude_paths := map[string]bool{"/": true, "/usr": true, "/etc": true}
if exclude_paths[path] { if exclude_paths[path] {
return fmt.Errorf("Relabeling of %s is not allowed", path) return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
} }
if shared { if shared {
@ -137,7 +137,10 @@ func Relabel(path string, fileLabel string, shared bool) error {
c["level"] = "s0" c["level"] = "s0"
fileLabel = c.Get() fileLabel = c.Get()
} }
return selinux.Chcon(path, fileLabel, true) if err := selinux.Chcon(path, fileLabel, true); err != nil {
return fmt.Errorf("SELinux relabeling of %s is not allowed: %q", path, err)
}
return nil
} }
// GetPidLabel will return the label of the process running with the specified pid // GetPidLabel will return the label of the process running with the specified pid

View File

@ -32,7 +32,7 @@ type parentProcess interface {
// wait waits on the process returning the process state. // wait waits on the process returning the process state.
wait() (*os.ProcessState, error) wait() (*os.ProcessState, error)
// startTime return's the process start time. // startTime returns the process start time.
startTime() (string, error) startTime() (string, error)
signal(os.Signal) error signal(os.Signal) error
@ -356,7 +356,7 @@ loop:
} }
} }
if !sentRun { if !sentRun {
return newSystemErrorWithCause(ierr, "container init failed") return newSystemErrorWithCause(ierr, "container init")
} }
if p.config.Config.Namespaces.Contains(configs.NEWNS) && !sentResume { if p.config.Config.Namespaces.Contains(configs.NEWNS) && !sentResume {
return newSystemError(fmt.Errorf("could not synchronise after executing prestart hooks with container process")) return newSystemError(fmt.Errorf("could not synchronise after executing prestart hooks with container process"))

View File

@ -50,7 +50,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole, pipe io.ReadWrit
} }
} }
if err := mountToRootfs(m, config.Rootfs, config.MountLabel); err != nil { if err := mountToRootfs(m, config.Rootfs, config.MountLabel); err != nil {
return newSystemErrorWithCausef(err, "mounting %q to rootfs %q", m.Destination, config.Rootfs) return newSystemErrorWithCausef(err, "mounting %q to rootfs %q at %q", m.Source, config.Rootfs, m.Destination)
} }
for _, postcmd := range m.PostmountCmds { for _, postcmd := range m.PostmountCmds {
@ -270,7 +270,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
} }
func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) { func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
mounts, err := cgroups.GetCgroupMounts() mounts, err := cgroups.GetCgroupMounts(false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -306,9 +306,6 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
// checkMountDestination checks to ensure that the mount destination is not over the top of /proc. // checkMountDestination checks to ensure that the mount destination is not over the top of /proc.
// dest is required to be an abs path and have any symlinks resolved before calling this function. // dest is required to be an abs path and have any symlinks resolved before calling this function.
func checkMountDestination(rootfs, dest string) error { func checkMountDestination(rootfs, dest string) error {
if libcontainerUtils.CleanPath(rootfs) == libcontainerUtils.CleanPath(dest) {
return fmt.Errorf("mounting into / is prohibited")
}
invalidDestinations := []string{ invalidDestinations := []string{
"/proc", "/proc",
} }
@ -320,6 +317,8 @@ func checkMountDestination(rootfs, dest string) error {
"/proc/diskstats", "/proc/diskstats",
"/proc/meminfo", "/proc/meminfo",
"/proc/stat", "/proc/stat",
"/proc/swaps",
"/proc/uptime",
"/proc/net/dev", "/proc/net/dev",
} }
for _, valid := range validDestinations { for _, valid := range validDestinations {
@ -663,10 +662,16 @@ func remountReadonly(path string) error {
return fmt.Errorf("unable to mount %s as readonly max retries reached", path) return fmt.Errorf("unable to mount %s as readonly max retries reached", path)
} }
// maskFile bind mounts /dev/null over the top of the specified path inside a container // maskPath masks the top of the specified path inside a container to avoid
// to avoid security issues from processes reading information from non-namespace aware mounts ( proc/kcore ). // security issues from processes reading information from non-namespace aware
func maskFile(path string) error { // mounts ( proc/kcore ).
// For files, maskPath bind mounts /dev/null over the top of the specified path.
// For directories, maskPath mounts read-only tmpfs over the top of the specified path.
func maskPath(path string) error {
if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) { if err := syscall.Mount("/dev/null", path, "", syscall.MS_BIND, ""); err != nil && !os.IsNotExist(err) {
if err == syscall.ENOTDIR {
return syscall.Mount("tmpfs", path, "tmpfs", syscall.MS_RDONLY, "")
}
return err return err
} }
return nil return nil

View File

@ -108,7 +108,7 @@ func (l *linuxStandardInit) Init() error {
} }
} }
for _, path := range l.config.Config.MaskPaths { for _, path := range l.config.Config.MaskPaths {
if err := maskFile(path); err != nil { if err := maskPath(path); err != nil {
return err return err
} }
} }

View File

@ -8,7 +8,7 @@ import (
// Setuid sets the uid of the calling thread to the specified uid. // Setuid sets the uid of the calling thread to the specified uid.
func Setuid(uid int) (err error) { func Setuid(uid int) (err error) {
_, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID, uintptr(uid), 0, 0) _, _, e1 := syscall.RawSyscall(syscall.SYS_SETUID32, uintptr(uid), 0, 0)
if e1 != 0 { if e1 != 0 {
err = e1 err = e1
} }

View File

@ -9,6 +9,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"syscall" "syscall"
"unsafe"
) )
const ( const (
@ -119,3 +120,7 @@ func Annotations(labels []string) (bundle string, userAnnotations map[string]str
} }
return return
} }
func GetIntSize() int {
return int(unsafe.Sizeof(1))
}

View File

@ -10,42 +10,42 @@ package capability
type Capabilities interface { type Capabilities interface {
// Get check whether a capability present in the given // Get check whether a capability present in the given
// capabilities set. The 'which' value should be one of EFFECTIVE, // capabilities set. The 'which' value should be one of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE, BOUNDING or AMBIENT.
Get(which CapType, what Cap) bool Get(which CapType, what Cap) bool
// Empty check whether all capability bits of the given capabilities // Empty check whether all capability bits of the given capabilities
// set are zero. The 'which' value should be one of EFFECTIVE, // set are zero. The 'which' value should be one of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE, BOUNDING or AMBIENT.
Empty(which CapType) bool Empty(which CapType) bool
// Full check whether all capability bits of the given capabilities // Full check whether all capability bits of the given capabilities
// set are one. The 'which' value should be one of EFFECTIVE, // set are one. The 'which' value should be one of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE, BOUNDING or AMBIENT.
Full(which CapType) bool Full(which CapType) bool
// Set sets capabilities of the given capabilities sets. The // Set sets capabilities of the given capabilities sets. The
// 'which' value should be one or combination (OR'ed) of EFFECTIVE, // 'which' value should be one or combination (OR'ed) of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE, BOUNDING or AMBIENT.
Set(which CapType, caps ...Cap) Set(which CapType, caps ...Cap)
// Unset unsets capabilities of the given capabilities sets. The // Unset unsets capabilities of the given capabilities sets. The
// 'which' value should be one or combination (OR'ed) of EFFECTIVE, // 'which' value should be one or combination (OR'ed) of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE, BOUNDING or AMBIENT.
Unset(which CapType, caps ...Cap) Unset(which CapType, caps ...Cap)
// Fill sets all bits of the given capabilities kind to one. The // Fill sets all bits of the given capabilities kind to one. The
// 'kind' value should be one or combination (OR'ed) of CAPS or // 'kind' value should be one or combination (OR'ed) of CAPS,
// BOUNDS. // BOUNDS or AMBS.
Fill(kind CapType) Fill(kind CapType)
// Clear sets all bits of the given capabilities kind to zero. The // Clear sets all bits of the given capabilities kind to zero. The
// 'kind' value should be one or combination (OR'ed) of CAPS or // 'kind' value should be one or combination (OR'ed) of CAPS,
// BOUNDS. // BOUNDS or AMBS.
Clear(kind CapType) Clear(kind CapType)
// String return current capabilities state of the given capabilities // String return current capabilities state of the given capabilities
// set as string. The 'which' value should be one of EFFECTIVE, // set as string. The 'which' value should be one of EFFECTIVE,
// PERMITTED, INHERITABLE or BOUNDING. // PERMITTED, INHERITABLE BOUNDING or AMBIENT
StringCap(which CapType) string StringCap(which CapType) string
// String return current capabilities state as string. // String return current capabilities state as string.

View File

@ -238,6 +238,7 @@ type capsV3 struct {
hdr capHeader hdr capHeader
data [2]capData data [2]capData
bounds [2]uint32 bounds [2]uint32
ambient [2]uint32
} }
func (c *capsV3) Get(which CapType, what Cap) bool { func (c *capsV3) Get(which CapType, what Cap) bool {
@ -256,6 +257,8 @@ func (c *capsV3) Get(which CapType, what Cap) bool {
return (1<<uint(what))&c.data[i].inheritable != 0 return (1<<uint(what))&c.data[i].inheritable != 0
case BOUNDING: case BOUNDING:
return (1<<uint(what))&c.bounds[i] != 0 return (1<<uint(what))&c.bounds[i] != 0
case AMBIENT:
return (1<<uint(what))&c.ambient[i] != 0
} }
return false return false
@ -275,6 +278,9 @@ func (c *capsV3) getData(which CapType, dest []uint32) {
case BOUNDING: case BOUNDING:
dest[0] = c.bounds[0] dest[0] = c.bounds[0]
dest[1] = c.bounds[1] dest[1] = c.bounds[1]
case AMBIENT:
dest[0] = c.ambient[0]
dest[1] = c.ambient[1]
} }
} }
@ -313,6 +319,9 @@ func (c *capsV3) Set(which CapType, caps ...Cap) {
if which&BOUNDING != 0 { if which&BOUNDING != 0 {
c.bounds[i] |= 1 << uint(what) c.bounds[i] |= 1 << uint(what)
} }
if which&AMBIENT != 0 {
c.ambient[i] |= 1 << uint(what)
}
} }
} }
@ -336,6 +345,9 @@ func (c *capsV3) Unset(which CapType, caps ...Cap) {
if which&BOUNDING != 0 { if which&BOUNDING != 0 {
c.bounds[i] &= ^(1 << uint(what)) c.bounds[i] &= ^(1 << uint(what))
} }
if which&AMBIENT != 0 {
c.ambient[i] &= ^(1 << uint(what))
}
} }
} }
@ -353,6 +365,10 @@ func (c *capsV3) Fill(kind CapType) {
c.bounds[0] = 0xffffffff c.bounds[0] = 0xffffffff
c.bounds[1] = 0xffffffff c.bounds[1] = 0xffffffff
} }
if kind&AMBS == AMBS {
c.ambient[0] = 0xffffffff
c.ambient[1] = 0xffffffff
}
} }
func (c *capsV3) Clear(kind CapType) { func (c *capsV3) Clear(kind CapType) {
@ -369,6 +385,10 @@ func (c *capsV3) Clear(kind CapType) {
c.bounds[0] = 0 c.bounds[0] = 0
c.bounds[1] = 0 c.bounds[1] = 0
} }
if kind&AMBS == AMBS {
c.ambient[0] = 0
c.ambient[1] = 0
}
} }
func (c *capsV3) StringCap(which CapType) (ret string) { func (c *capsV3) StringCap(which CapType) (ret string) {
@ -410,6 +430,10 @@ func (c *capsV3) Load() (err error) {
fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0]) fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0])
break break
} }
if strings.HasPrefix(line, "CapA") {
fmt.Sscanf(line[4:], "mb: %08x%08x", &c.ambient[1], &c.ambient[0])
break
}
} }
f.Close() f.Close()
@ -442,7 +466,25 @@ func (c *capsV3) Apply(kind CapType) (err error) {
} }
if kind&CAPS == CAPS { if kind&CAPS == CAPS {
return capset(&c.hdr, &c.data[0]) err = capset(&c.hdr, &c.data[0])
if err != nil {
return
}
}
if kind&AMBS == AMBS {
for i := Cap(0); i <= CAP_LAST_CAP; i++ {
action := pr_CAP_AMBIENT_LOWER
if c.Get(AMBIENT, i) {
action = pr_CAP_AMBIENT_RAISE
}
err := prctl(pr_CAP_AMBIENT, action, uintptr(i), 0, 0)
// Ignore EINVAL as not supported on kernels before 4.3
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL {
err = nil
continue
}
}
} }
return return

View File

@ -20,6 +20,8 @@ func (c CapType) String() string {
return "bounding" return "bounding"
case CAPS: case CAPS:
return "caps" return "caps"
case AMBIENT:
return "ambient"
} }
return "unknown" return "unknown"
} }
@ -29,9 +31,11 @@ const (
PERMITTED PERMITTED
INHERITABLE INHERITABLE
BOUNDING BOUNDING
AMBIENT
CAPS = EFFECTIVE | PERMITTED | INHERITABLE CAPS = EFFECTIVE | PERMITTED | INHERITABLE
BOUNDS = BOUNDING BOUNDS = BOUNDING
AMBS = AMBIENT
) )
//go:generate go run enumgen/gen.go //go:generate go run enumgen/gen.go

View File

@ -38,6 +38,15 @@ func capset(hdr *capHeader, data *capData) (err error) {
return return
} }
// not yet in syscall
const (
pr_CAP_AMBIENT = 47
pr_CAP_AMBIENT_IS_SET = uintptr(1)
pr_CAP_AMBIENT_RAISE = uintptr(2)
pr_CAP_AMBIENT_LOWER = uintptr(3)
pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4)
)
func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0)
if e1 != 0 { if e1 != 0 {