Merge pull request #437 from containers/dependabot/go_modules/github.com/opencontainers/runc-1.0.0-rc93
Bump github.com/opencontainers/runc from 1.0.0-rc91 to 1.0.0-rc93
This commit is contained in:
commit
16608cd263
|
|
@ -11,13 +11,12 @@ require (
|
||||||
github.com/docker/docker v17.12.0-ce-rc1.0.20201020191947-73dc6a680cdd+incompatible
|
github.com/docker/docker v17.12.0-ce-rc1.0.20201020191947-73dc6a680cdd+incompatible
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/google/go-cmp v0.5.2 // indirect
|
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.0
|
github.com/hashicorp/go-multierror v1.1.0
|
||||||
github.com/onsi/ginkgo v1.15.0
|
github.com/onsi/ginkgo v1.15.0
|
||||||
github.com/onsi/gomega v1.10.5
|
github.com/onsi/gomega v1.10.5
|
||||||
github.com/opencontainers/runc v1.0.0-rc91
|
github.com/opencontainers/runc v1.0.0-rc93
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200710190001-3e4195d92445
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
|
||||||
github.com/opencontainers/runtime-tools v0.9.0
|
github.com/opencontainers/runtime-tools v0.9.0
|
||||||
github.com/opencontainers/selinux v1.8.0
|
github.com/opencontainers/selinux v1.8.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
|
@ -27,7 +26,7 @@ require (
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/spf13/cobra v1.1.1
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,19 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
github.com/checkpoint-restore/go-criu/v4 v4.0.2/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||||
|
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
|
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
|
||||||
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
|
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
|
||||||
|
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
|
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
|
||||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||||
github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
||||||
|
github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
|
||||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
|
|
@ -71,9 +74,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
|
github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
|
||||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
|
@ -129,6 +135,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
|
@ -240,6 +248,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
|
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
|
||||||
|
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||||
github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI=
|
github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||||
|
|
@ -263,11 +272,13 @@ github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod
|
||||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
github.com/opencontainers/runc v1.0.0-rc91 h1:Tp8LWs5G8rFpzTsbRjAtQkPVexhCu0bnANE5IfIhJ6g=
|
github.com/opencontainers/runc v1.0.0-rc91 h1:Tp8LWs5G8rFpzTsbRjAtQkPVexhCu0bnANE5IfIhJ6g=
|
||||||
github.com/opencontainers/runc v1.0.0-rc91/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8=
|
github.com/opencontainers/runc v1.0.0-rc91/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8=
|
||||||
|
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
|
||||||
|
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2 h1:9mv9SC7GWmRWE0J/+oD8w3GsN2KYGKtg6uwLN7hfP5E=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200710190001-3e4195d92445 h1:y8cfsJRmn8g3VkM4IDpusKSgMUZEXhudm/BuYANLozE=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d h1:pNa8metDkwZjb9g4T8s+krQ+HRgZAkqnXml+wNir/+s=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200710190001-3e4195d92445/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=
|
github.com/opencontainers/runtime-tools v0.9.0 h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=
|
||||||
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||||
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g=
|
||||||
|
|
@ -348,6 +359,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
|
github.com/tchap/go-patricia v2.3.0+incompatible h1:GkY4dP3cEfEASBPPkWd+AmjYxhmDkqO9/zg7R0lSQRs=
|
||||||
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
|
@ -431,6 +444,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
||||||
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
|
@ -472,14 +487,17 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 h1:+CBz4km/0KPU3RGTwARGh/noP3bEwtHcq+0YcBQM2JQ=
|
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 h1:+CBz4km/0KPU3RGTwARGh/noP3bEwtHcq+0YcBQM2JQ=
|
||||||
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package chown
|
package chown
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package chown
|
package chown
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package chown
|
||||||
|
|
||||||
|
// DangerousHostPath validates if a host path is dangerous and should not be modified
|
||||||
|
func DangerousHostPath(path string) (bool, error) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeHostPathOwnership changes the uid and gid ownership of a directory or file within the host.
|
||||||
|
// This is used by the volume U flag to change source volumes ownership
|
||||||
|
func ChangeHostPathOwnership(path string, recursive bool, uid, gid int) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -7,13 +7,12 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containers/storage/pkg/unshare"
|
"github.com/containers/storage/pkg/unshare"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
|
||||||
"github.com/opencontainers/runc/libcontainer/devices"
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DeviceFromPath(device string) ([]configs.Device, error) {
|
func DeviceFromPath(device string) ([]devices.Device, error) {
|
||||||
var devs []configs.Device
|
var devs []devices.Device
|
||||||
src, dst, permissions, err := Device(device)
|
src, dst, permissions, err := Device(device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -44,7 +43,7 @@ func DeviceFromPath(device string) ([]configs.Device, error) {
|
||||||
}
|
}
|
||||||
for _, d := range srcDevices {
|
for _, d := range srcDevices {
|
||||||
d.Path = filepath.Join(dst, filepath.Base(d.Path))
|
d.Path = filepath.Join(dst, filepath.Base(d.Path))
|
||||||
d.Permissions = configs.DevicePermissions(permissions)
|
d.Permissions = devices.Permissions(permissions)
|
||||||
devs = append(devs, *d)
|
devs = append(devs, *d)
|
||||||
}
|
}
|
||||||
return devs, nil
|
return devs, nil
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Copyright (C) 2017 SUSE LLC. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -cover -v ./...
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
|
||||||
|
Copyright (C) 2017 SUSE LLC. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
|
in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
## `filepath-securejoin` ##
|
||||||
|
|
||||||
|
[](https://travis-ci.org/cyphar/filepath-securejoin)
|
||||||
|
|
||||||
|
An implementation of `SecureJoin`, a [candidate for inclusion in the Go
|
||||||
|
standard library][go#20126]. The purpose of this function is to be a "secure"
|
||||||
|
alternative to `filepath.Join`, and in particular it provides certain
|
||||||
|
guarantees that are not provided by `filepath.Join`.
|
||||||
|
|
||||||
|
This is the function prototype:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func SecureJoin(root, unsafePath string) (string, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
This library **guarantees** the following:
|
||||||
|
|
||||||
|
* If no error is set, the resulting string **must** be a child path of
|
||||||
|
`SecureJoin` and will not contain any symlink path components (they will all
|
||||||
|
be expanded).
|
||||||
|
|
||||||
|
* When expanding symlinks, all symlink path components **must** be resolved
|
||||||
|
relative to the provided root. In particular, this can be considered a
|
||||||
|
userspace implementation of how `chroot(2)` operates on file paths. Note that
|
||||||
|
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
|
||||||
|
called on the input before processing).
|
||||||
|
|
||||||
|
* Non-existant path components are unaffected by `SecureJoin` (similar to
|
||||||
|
`filepath.EvalSymlinks`'s semantics).
|
||||||
|
|
||||||
|
* The returned path will always be `filepath.Clean`ed and thus not contain any
|
||||||
|
`..` components.
|
||||||
|
|
||||||
|
A (trivial) implementation of this function on GNU/Linux systems could be done
|
||||||
|
with the following (note that this requires root privileges and is far more
|
||||||
|
opaque than the implementation in this library, and also requires that
|
||||||
|
`readlink` is inside the `root` path):
|
||||||
|
|
||||||
|
```go
|
||||||
|
package securejoin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SecureJoin(root, unsafePath string) (string, error) {
|
||||||
|
unsafePath = string(filepath.Separator) + unsafePath
|
||||||
|
cmd := exec.Command("chroot", root,
|
||||||
|
"readlink", "--canonicalize-missing", "--no-newline", unsafePath)
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
expanded := string(output)
|
||||||
|
return filepath.Join(root, expanded), nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[go#20126]: https://github.com/golang/go/issues/20126
|
||||||
|
|
||||||
|
### License ###
|
||||||
|
|
||||||
|
The license of this project is the same as Go, which is a BSD 3-clause license
|
||||||
|
available in the `LICENSE` file.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.2.2
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
|
||||||
|
// Copyright (C) 2017 SUSE LLC. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package securejoin is an implementation of the hopefully-soon-to-be-included
|
||||||
|
// SecureJoin helper that is meant to be part of the "path/filepath" package.
|
||||||
|
// The purpose of this project is to provide a PoC implementation to make the
|
||||||
|
// SecureJoin proposal (https://github.com/golang/go/issues/20126) more
|
||||||
|
// tangible.
|
||||||
|
package securejoin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been
|
||||||
|
// evaluated in attempting to securely join the two given paths.
|
||||||
|
var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join")
|
||||||
|
|
||||||
|
// IsNotExist tells you if err is an error that implies that either the path
|
||||||
|
// accessed does not exist (or path components don't exist). This is
|
||||||
|
// effectively a more broad version of os.IsNotExist.
|
||||||
|
func IsNotExist(err error) bool {
|
||||||
|
// If it's a bone-fide ENOENT just bail.
|
||||||
|
if os.IsNotExist(errors.Cause(err)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that it's not actually an ENOTDIR, which in some cases is a more
|
||||||
|
// convoluted case of ENOENT (usually involving weird paths).
|
||||||
|
var errno error
|
||||||
|
switch err := errors.Cause(err).(type) {
|
||||||
|
case *os.PathError:
|
||||||
|
errno = err.Err
|
||||||
|
case *os.LinkError:
|
||||||
|
errno = err.Err
|
||||||
|
case *os.SyscallError:
|
||||||
|
errno = err.Err
|
||||||
|
}
|
||||||
|
return errno == syscall.ENOTDIR || errno == syscall.ENOENT
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecureJoinVFS joins the two given path components (similar to Join) except
|
||||||
|
// that the returned path is guaranteed to be scoped inside the provided root
|
||||||
|
// path (when evaluated). Any symbolic links in the path are evaluated with the
|
||||||
|
// given root treated as the root of the filesystem, similar to a chroot. The
|
||||||
|
// filesystem state is evaluated through the given VFS interface (if nil, the
|
||||||
|
// standard os.* family of functions are used).
|
||||||
|
//
|
||||||
|
// Note that the guarantees provided by this function only apply if the path
|
||||||
|
// components in the returned string are not modified (in other words are not
|
||||||
|
// replaced with symlinks on the filesystem) after this function has returned.
|
||||||
|
// Such a symlink race is necessarily out-of-scope of SecureJoin.
|
||||||
|
func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
|
||||||
|
// Use the os.* VFS implementation if none was specified.
|
||||||
|
if vfs == nil {
|
||||||
|
vfs = osVFS{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var path bytes.Buffer
|
||||||
|
n := 0
|
||||||
|
for unsafePath != "" {
|
||||||
|
if n > 255 {
|
||||||
|
return "", ErrSymlinkLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next path component, p.
|
||||||
|
i := strings.IndexRune(unsafePath, filepath.Separator)
|
||||||
|
var p string
|
||||||
|
if i == -1 {
|
||||||
|
p, unsafePath = unsafePath, ""
|
||||||
|
} else {
|
||||||
|
p, unsafePath = unsafePath[:i], unsafePath[i+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cleaned path, using the lexical semantics of /../a, to
|
||||||
|
// create a "scoped" path component which can safely be joined to fullP
|
||||||
|
// for evaluation. At this point, path.String() doesn't contain any
|
||||||
|
// symlink components.
|
||||||
|
cleanP := filepath.Clean(string(filepath.Separator) + path.String() + p)
|
||||||
|
if cleanP == string(filepath.Separator) {
|
||||||
|
path.Reset()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fullP := filepath.Clean(root + cleanP)
|
||||||
|
|
||||||
|
// Figure out whether the path is a symlink.
|
||||||
|
fi, err := vfs.Lstat(fullP)
|
||||||
|
if err != nil && !IsNotExist(err) {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Treat non-existent path components the same as non-symlinks (we
|
||||||
|
// can't do any better here).
|
||||||
|
if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 {
|
||||||
|
path.WriteString(p)
|
||||||
|
path.WriteRune(filepath.Separator)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only increment when we actually dereference a link.
|
||||||
|
n++
|
||||||
|
|
||||||
|
// It's a symlink, expand it by prepending it to the yet-unparsed path.
|
||||||
|
dest, err := vfs.Readlink(fullP)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Absolute symlinks reset any work we've already done.
|
||||||
|
if filepath.IsAbs(dest) {
|
||||||
|
path.Reset()
|
||||||
|
}
|
||||||
|
unsafePath = dest + string(filepath.Separator) + unsafePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have to clean path.String() here because it may contain '..'
|
||||||
|
// components that are entirely lexical, but would be misleading otherwise.
|
||||||
|
// And finally do a final clean to ensure that root is also lexically
|
||||||
|
// clean.
|
||||||
|
fullP := filepath.Clean(string(filepath.Separator) + path.String())
|
||||||
|
return filepath.Clean(root + fullP), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library
|
||||||
|
// of functions as the VFS. If in doubt, use this function over SecureJoinVFS.
|
||||||
|
func SecureJoin(root, unsafePath string) (string, error) {
|
||||||
|
return SecureJoinVFS(root, unsafePath, nil)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
github.com/pkg/errors v0.8.0
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright (C) 2017 SUSE LLC. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package securejoin
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// In future this should be moved into a separate package, because now there
|
||||||
|
// are several projects (umoci and go-mtree) that are using this sort of
|
||||||
|
// interface.
|
||||||
|
|
||||||
|
// VFS is the minimal interface necessary to use SecureJoinVFS. A nil VFS is
|
||||||
|
// equivalent to using the standard os.* family of functions. This is mainly
|
||||||
|
// used for the purposes of mock testing, but also can be used to otherwise use
|
||||||
|
// SecureJoin with VFS-like system.
|
||||||
|
type VFS interface {
|
||||||
|
// Lstat returns a FileInfo describing the named file. If the file is a
|
||||||
|
// symbolic link, the returned FileInfo describes the symbolic link. Lstat
|
||||||
|
// makes no attempt to follow the link. These semantics are identical to
|
||||||
|
// os.Lstat.
|
||||||
|
Lstat(name string) (os.FileInfo, error)
|
||||||
|
|
||||||
|
// Readlink returns the destination of the named symbolic link. These
|
||||||
|
// semantics are identical to os.Readlink.
|
||||||
|
Readlink(name string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// osVFS is the "nil" VFS, in that it just passes everything through to the os
|
||||||
|
// module.
|
||||||
|
type osVFS struct{}
|
||||||
|
|
||||||
|
// Lstat returns a FileInfo describing the named file. If the file is a
|
||||||
|
// symbolic link, the returned FileInfo describes the symbolic link. Lstat
|
||||||
|
// makes no attempt to follow the link. These semantics are identical to
|
||||||
|
// os.Lstat.
|
||||||
|
func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) }
|
||||||
|
|
||||||
|
// Readlink returns the destination of the named symbolic link. These
|
||||||
|
// semantics are identical to os.Readlink.
|
||||||
|
func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) }
|
||||||
|
|
@ -765,7 +765,7 @@ func unescape(s string) (ch string, tail string, err error) {
|
||||||
if i > utf8.MaxRune {
|
if i > utf8.MaxRune {
|
||||||
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
||||||
}
|
}
|
||||||
return string(i), s, nil
|
return string(rune(i)), s, nil
|
||||||
}
|
}
|
||||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
// +build apparmor,linux
|
|
||||||
|
|
||||||
package apparmor
|
package apparmor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -12,11 +11,9 @@ import (
|
||||||
|
|
||||||
// IsEnabled returns true if apparmor is enabled for the host.
|
// IsEnabled returns true if apparmor is enabled for the host.
|
||||||
func IsEnabled() bool {
|
func IsEnabled() bool {
|
||||||
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil && os.Getenv("container") == "" {
|
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
|
||||||
if _, err = os.Stat("/sbin/apparmor_parser"); err == nil {
|
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
||||||
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
return err == nil && bytes.HasPrefix(buf, []byte("Y"))
|
||||||
return err == nil && len(buf) > 1 && buf[0] == 'Y'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -24,9 +21,7 @@ func IsEnabled() bool {
|
||||||
func setProcAttr(attr, value string) error {
|
func setProcAttr(attr, value string) error {
|
||||||
// Under AppArmor you can only change your own attr, so use /proc/self/
|
// Under AppArmor you can only change your own attr, so use /proc/self/
|
||||||
// instead of /proc/<tid>/ like libapparmor does
|
// instead of /proc/<tid>/ like libapparmor does
|
||||||
path := fmt.Sprintf("/proc/self/attr/%s", attr)
|
f, err := os.OpenFile("/proc/self/attr/"+attr, os.O_WRONLY, 0)
|
||||||
|
|
||||||
f, err := os.OpenFile(path, os.O_WRONLY, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -36,14 +31,13 @@ func setProcAttr(attr, value string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fmt.Fprintf(f, "%s", value)
|
_, err = f.WriteString(value)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
|
||||||
func changeOnExec(name string) error {
|
func changeOnExec(name string) error {
|
||||||
value := "exec " + name
|
if err := setProcAttr("exec", "exec "+name); err != nil {
|
||||||
if err := setProcAttr("exec", value); err != nil {
|
|
||||||
return fmt.Errorf("apparmor failed to apply profile: %s", err)
|
return fmt.Errorf("apparmor failed to apply profile: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !apparmor !linux
|
// +build !linux
|
||||||
|
|
||||||
package apparmor
|
package apparmor
|
||||||
|
|
||||||
51
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go
generated
vendored
Normal file
51
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go
generated
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package fscommon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WriteFile writes data to a cgroup file in dir.
|
||||||
|
// It is supposed to be used for cgroup files only.
|
||||||
|
func WriteFile(dir, file, data string) error {
|
||||||
|
fd, err := OpenFile(dir, file, unix.O_WRONLY)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
if err := retryingWriteFile(fd, data); err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to write %q", data)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFile reads data from a cgroup file in dir.
|
||||||
|
// It is supposed to be used for cgroup files only.
|
||||||
|
func ReadFile(dir, file string) (string, error) {
|
||||||
|
fd, err := OpenFile(dir, file, unix.O_RDONLY)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
_, err = buf.ReadFrom(fd)
|
||||||
|
return buf.String(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func retryingWriteFile(fd *os.File, data string) error {
|
||||||
|
for {
|
||||||
|
_, err := fd.Write([]byte(data))
|
||||||
|
if errors.Is(err, unix.EINTR) {
|
||||||
|
logrus.Infof("interrupted while writing %s to %s", data, fd.Name())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
103
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/open.go
generated
vendored
Normal file
103
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/open.go
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
package fscommon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
securejoin "github.com/cyphar/filepath-securejoin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cgroupfsDir = "/sys/fs/cgroup"
|
||||||
|
cgroupfsPrefix = cgroupfsDir + "/"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Set to true by fs unit tests
|
||||||
|
TestMode bool
|
||||||
|
|
||||||
|
cgroupFd int = -1
|
||||||
|
prepOnce sync.Once
|
||||||
|
prepErr error
|
||||||
|
resolveFlags uint64
|
||||||
|
)
|
||||||
|
|
||||||
|
func prepareOpenat2() error {
|
||||||
|
prepOnce.Do(func() {
|
||||||
|
fd, err := unix.Openat2(-1, cgroupfsDir, &unix.OpenHow{
|
||||||
|
Flags: unix.O_DIRECTORY | unix.O_PATH})
|
||||||
|
if err != nil {
|
||||||
|
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
|
||||||
|
if err != unix.ENOSYS {
|
||||||
|
logrus.Warnf("falling back to securejoin: %s", prepErr)
|
||||||
|
} else {
|
||||||
|
logrus.Debug("openat2 not available, falling back to securejoin")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var st unix.Statfs_t
|
||||||
|
if err = unix.Fstatfs(fd, &st); err != nil {
|
||||||
|
prepErr = &os.PathError{Op: "statfs", Path: cgroupfsDir, Err: err}
|
||||||
|
logrus.Warnf("falling back to securejoin: %s", prepErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroupFd = fd
|
||||||
|
|
||||||
|
resolveFlags = unix.RESOLVE_BENEATH | unix.RESOLVE_NO_MAGICLINKS
|
||||||
|
if st.Type == unix.CGROUP2_SUPER_MAGIC {
|
||||||
|
// cgroupv2 has a single mountpoint and no "cpu,cpuacct" symlinks
|
||||||
|
resolveFlags |= unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_SYMLINKS
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return prepErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenFile opens a cgroup file in a given dir with given flags.
|
||||||
|
// It is supposed to be used for cgroup files only.
|
||||||
|
func OpenFile(dir, file string, flags int) (*os.File, error) {
|
||||||
|
if dir == "" {
|
||||||
|
return nil, errors.Errorf("no directory specified for %s", file)
|
||||||
|
}
|
||||||
|
mode := os.FileMode(0)
|
||||||
|
if TestMode && flags&os.O_WRONLY != 0 {
|
||||||
|
// "emulate" cgroup fs for unit tests
|
||||||
|
flags |= os.O_TRUNC | os.O_CREATE
|
||||||
|
mode = 0o600
|
||||||
|
}
|
||||||
|
reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
|
||||||
|
if len(reldir) == len(dir) { // non-standard path, old system?
|
||||||
|
return openWithSecureJoin(dir, file, flags, mode)
|
||||||
|
}
|
||||||
|
if prepareOpenat2() != nil {
|
||||||
|
return openWithSecureJoin(dir, file, flags, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
relname := reldir + "/" + file
|
||||||
|
fd, err := unix.Openat2(cgroupFd, relname,
|
||||||
|
&unix.OpenHow{
|
||||||
|
Resolve: resolveFlags,
|
||||||
|
Flags: uint64(flags) | unix.O_CLOEXEC,
|
||||||
|
Mode: uint64(mode),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, &os.PathError{Op: "openat2", Path: dir + "/" + file, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func openWithSecureJoin(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
|
||||||
|
path, err := securejoin.SecureJoin(dir, file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.OpenFile(path, flags, mode)
|
||||||
|
}
|
||||||
102
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
generated
vendored
Normal file
102
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package fscommon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotValidFormat = errors.New("line is not a valid key value format")
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseUint converts a string to an uint64 integer.
|
||||||
|
// Negative values are returned at zero as, 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCgroupParamKeyValue parses a space-separated "name value" kind of cgroup
|
||||||
|
// parameter and returns its components. For example, "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 to uint64: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[0], value, nil
|
||||||
|
default:
|
||||||
|
return "", 0, ErrNotValidFormat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCgroupParamUint reads a single uint64 value from the specified cgroup file.
|
||||||
|
// If the value read is "max", the math.MaxUint64 is returned.
|
||||||
|
func GetCgroupParamUint(path, file string) (uint64, error) {
|
||||||
|
contents, err := GetCgroupParamString(path, file)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
contents = strings.TrimSpace(contents)
|
||||||
|
if contents == "max" {
|
||||||
|
return math.MaxUint64, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := ParseUint(contents, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return res, fmt.Errorf("unable to parse file %q", path+"/"+file)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCgroupParamInt reads a single int64 value from specified cgroup file.
|
||||||
|
// If the value read is "max", the math.MaxInt64 is returned.
|
||||||
|
func GetCgroupParamInt(path, file string) (int64, error) {
|
||||||
|
contents, err := ReadFile(path, file)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
contents = strings.TrimSpace(contents)
|
||||||
|
if contents == "max" {
|
||||||
|
return math.MaxInt64, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := strconv.ParseInt(contents, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return res, fmt.Errorf("unable to parse %q as a int from Cgroup file %q", contents, path+"/"+file)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCgroupParamString reads a string from the specified cgroup file.
|
||||||
|
func GetCgroupParamString(path, file string) (string, error) {
|
||||||
|
contents, err := ReadFile(path, file)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(contents), nil
|
||||||
|
}
|
||||||
|
|
@ -39,6 +39,33 @@ type CpuStats struct {
|
||||||
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
|
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CPUSetStats struct {
|
||||||
|
// List of the physical numbers of the CPUs on which processes
|
||||||
|
// in that cpuset are allowed to execute
|
||||||
|
CPUs []uint16 `json:"cpus,omitempty"`
|
||||||
|
// cpu_exclusive flag
|
||||||
|
CPUExclusive uint64 `json:"cpu_exclusive"`
|
||||||
|
// List of memory nodes on which processes in that cpuset
|
||||||
|
// are allowed to allocate memory
|
||||||
|
Mems []uint16 `json:"mems,omitempty"`
|
||||||
|
// mem_hardwall flag
|
||||||
|
MemHardwall uint64 `json:"mem_hardwall"`
|
||||||
|
// mem_exclusive flag
|
||||||
|
MemExclusive uint64 `json:"mem_exclusive"`
|
||||||
|
// memory_migrate flag
|
||||||
|
MemoryMigrate uint64 `json:"memory_migrate"`
|
||||||
|
// memory_spread page flag
|
||||||
|
MemorySpreadPage uint64 `json:"memory_spread_page"`
|
||||||
|
// memory_spread slab flag
|
||||||
|
MemorySpreadSlab uint64 `json:"memory_spread_slab"`
|
||||||
|
// memory_pressure
|
||||||
|
MemoryPressure uint64 `json:"memory_pressure"`
|
||||||
|
// sched_load balance flag
|
||||||
|
SchedLoadBalance uint64 `json:"sched_load_balance"`
|
||||||
|
// sched_relax_domain_level
|
||||||
|
SchedRelaxDomainLevel int64 `json:"sched_relax_domain_level"`
|
||||||
|
}
|
||||||
|
|
||||||
type MemoryData struct {
|
type MemoryData struct {
|
||||||
Usage uint64 `json:"usage,omitempty"`
|
Usage uint64 `json:"usage,omitempty"`
|
||||||
MaxUsage uint64 `json:"max_usage,omitempty"`
|
MaxUsage uint64 `json:"max_usage,omitempty"`
|
||||||
|
|
@ -121,6 +148,7 @@ type HugetlbStats struct {
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
CpuStats CpuStats `json:"cpu_stats,omitempty"`
|
||||||
|
CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
|
||||||
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
|
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
|
||||||
PidsStats PidsStats `json:"pids_stats,omitempty"`
|
PidsStats PidsStats `json:"pids_stats,omitempty"`
|
||||||
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
units "github.com/docker/go-units"
|
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,19 +31,19 @@ var (
|
||||||
isUnified bool
|
isUnified bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// HugePageSizeUnitList is a list of the units used by the linux kernel when
|
|
||||||
// naming the HugePage control files.
|
|
||||||
// https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt
|
|
||||||
// TODO Since the kernel only use KB, MB and GB; TB and PB should be removed,
|
|
||||||
// depends on https://github.com/docker/go-units/commit/a09cd47f892041a4fac473133d181f5aea6fa393
|
|
||||||
var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
|
|
||||||
|
|
||||||
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
|
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
|
||||||
func IsCgroup2UnifiedMode() bool {
|
func IsCgroup2UnifiedMode() bool {
|
||||||
isUnifiedOnce.Do(func() {
|
isUnifiedOnce.Do(func() {
|
||||||
var st unix.Statfs_t
|
var st unix.Statfs_t
|
||||||
if err := unix.Statfs(unifiedMountpoint, &st); err != nil {
|
err := unix.Statfs(unifiedMountpoint, &st)
|
||||||
panic("cannot statfs cgroup root")
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) && system.RunningInUserNS() {
|
||||||
|
// ignore the "not found" error if running in userns
|
||||||
|
logrus.WithError(err).Debugf("%s missing, assuming cgroup v1", unifiedMountpoint)
|
||||||
|
isUnified = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("cannot statfs cgroup root: %s", err))
|
||||||
}
|
}
|
||||||
isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC
|
isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC
|
||||||
})
|
})
|
||||||
|
|
@ -86,11 +88,11 @@ func GetAllSubsystems() ([]string, error) {
|
||||||
// - freezer: implemented in kernel 5.2
|
// - freezer: implemented in kernel 5.2
|
||||||
// We assume these are always available, as it is hard to detect availability.
|
// We assume these are always available, as it is hard to detect availability.
|
||||||
pseudo := []string{"devices", "freezer"}
|
pseudo := []string{"devices", "freezer"}
|
||||||
data, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
|
data, err := fscommon.ReadFile("/sys/fs/cgroup", "cgroup.controllers")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
subsystems := append(pseudo, strings.Fields(string(data))...)
|
subsystems := append(pseudo, strings.Fields(data)...)
|
||||||
return subsystems, nil
|
return subsystems, nil
|
||||||
}
|
}
|
||||||
f, err := os.Open("/proc/cgroups")
|
f, err := os.Open("/proc/cgroups")
|
||||||
|
|
@ -207,20 +209,66 @@ func EnterPid(cgroupPaths map[string]string, pid int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rmdir(path string) error {
|
||||||
|
err := unix.Rmdir(path)
|
||||||
|
if err == nil || err == unix.ENOENT {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &os.PathError{Op: "rmdir", Path: path, Err: err}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePath aims to remove cgroup path. It does so recursively,
|
||||||
|
// by removing any subdirectories (sub-cgroups) first.
|
||||||
|
func RemovePath(path string) error {
|
||||||
|
// try the fast path first
|
||||||
|
if err := rmdir(path); err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
infos, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, info := range infos {
|
||||||
|
if info.IsDir() {
|
||||||
|
// We should remove subcgroups dir first
|
||||||
|
if err = RemovePath(filepath.Join(path, info.Name())); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
err = rmdir(path)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// RemovePaths iterates over the provided paths removing them.
|
// RemovePaths iterates over the provided paths removing them.
|
||||||
// We trying to remove all paths five times with increasing delay between tries.
|
// We trying to remove all paths five times with increasing delay between tries.
|
||||||
// If after all there are not removed cgroups - appropriate error will be
|
// If after all there are not removed cgroups - appropriate error will be
|
||||||
// returned.
|
// returned.
|
||||||
func RemovePaths(paths map[string]string) (err error) {
|
func RemovePaths(paths map[string]string) (err error) {
|
||||||
|
const retries = 5
|
||||||
delay := 10 * time.Millisecond
|
delay := 10 * time.Millisecond
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < retries; i++ {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
delay *= 2
|
delay *= 2
|
||||||
}
|
}
|
||||||
for s, p := range paths {
|
for s, p := range paths {
|
||||||
os.RemoveAll(p)
|
if err := RemovePath(p); err != nil {
|
||||||
// TODO: here probably should be logging
|
// do not log intermediate iterations
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
logrus.WithError(err).Warnf("Failed to remove cgroup (will retry)")
|
||||||
|
case retries - 1:
|
||||||
|
logrus.WithError(err).Error("Failed to remove cgroup")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
_, err := os.Stat(p)
|
_, err := os.Stat(p)
|
||||||
// We need this strange way of checking cgroups existence because
|
// We need this strange way of checking cgroups existence because
|
||||||
// RemoveAll almost always returns error, even on already removed
|
// RemoveAll almost always returns error, even on already removed
|
||||||
|
|
@ -230,6 +278,8 @@ func RemovePaths(paths map[string]string) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
|
//nolint:ineffassign,staticcheck // done to help garbage collecting: opencontainers/runc#2506
|
||||||
|
paths = make(map[string]string)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,27 +287,50 @@ func RemovePaths(paths map[string]string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHugePageSize() ([]string, error) {
|
func GetHugePageSize() ([]string, error) {
|
||||||
files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
|
dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []string{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var fileNames []string
|
files, err := dir.Readdirnames(0)
|
||||||
for _, st := range files {
|
dir.Close()
|
||||||
fileNames = append(fileNames, st.Name())
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return getHugePageSizeFromFilenames(fileNames)
|
|
||||||
|
return getHugePageSizeFromFilenames(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
|
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
|
||||||
var pageSizes []string
|
pageSizes := make([]string, 0, len(fileNames))
|
||||||
for _, fileName := range fileNames {
|
|
||||||
nameArray := strings.Split(fileName, "-")
|
for _, file := range fileNames {
|
||||||
pageSize, err := units.RAMInBytes(nameArray[1])
|
// example: hugepages-1048576kB
|
||||||
if err != nil {
|
val := strings.TrimPrefix(file, "hugepages-")
|
||||||
return []string{}, err
|
if len(val) == len(file) {
|
||||||
|
// unexpected file name: no prefix found
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
sizeString := units.CustomSize("%g%s", float64(pageSize), 1024.0, HugePageSizeUnitList)
|
// The suffix is always "kB" (as of Linux 5.9)
|
||||||
pageSizes = append(pageSizes, sizeString)
|
eLen := len(val) - 2
|
||||||
|
val = strings.TrimSuffix(val, "kB")
|
||||||
|
if len(val) != eLen {
|
||||||
|
logrus.Warnf("GetHugePageSize: %s: invalid filename suffix (expected \"kB\")", file)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
size, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
|
||||||
|
// but in our case the size is in KB already.
|
||||||
|
if size >= (1 << 20) {
|
||||||
|
val = strconv.Itoa(size>>20) + "GB"
|
||||||
|
} else if size >= (1 << 10) {
|
||||||
|
val = strconv.Itoa(size>>10) + "MB"
|
||||||
|
} else {
|
||||||
|
val += "KB"
|
||||||
|
}
|
||||||
|
pageSizes = append(pageSizes, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageSizes, nil
|
return pageSizes, nil
|
||||||
|
|
@ -303,14 +376,14 @@ func WriteCgroupProc(dir string, pid int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cgroupProcessesFile, err := os.OpenFile(filepath.Join(dir, CgroupProcesses), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
|
file, err := fscommon.OpenFile(dir, CgroupProcesses, os.O_WRONLY)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
|
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
|
||||||
}
|
}
|
||||||
defer cgroupProcessesFile.Close()
|
defer file.Close()
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
_, err = cgroupProcessesFile.WriteString(strconv.Itoa(pid))
|
_, err = file.WriteString(strconv.Itoa(pid))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
155
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
generated
vendored
155
common/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
generated
vendored
|
|
@ -1,13 +1,17 @@
|
||||||
package cgroups
|
package cgroups
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
securejoin "github.com/cyphar/filepath-securejoin"
|
||||||
|
"github.com/moby/sys/mountinfo"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Code in this source file are specific to cgroup v1,
|
// Code in this source file are specific to cgroup v1,
|
||||||
|
|
@ -15,10 +19,16 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CgroupNamePrefix = "name="
|
CgroupNamePrefix = "name="
|
||||||
|
defaultPrefix = "/sys/fs/cgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errUnified = errors.New("not implemented for cgroup v2 unified hierarchy")
|
errUnified = errors.New("not implemented for cgroup v2 unified hierarchy")
|
||||||
|
ErrV1NoUnified = errors.New("invalid configuration: cannot use unified on cgroup v1")
|
||||||
|
|
||||||
|
readMountinfoOnce sync.Once
|
||||||
|
readMountinfoErr error
|
||||||
|
cgroupMountinfo []*mountinfo.Info
|
||||||
)
|
)
|
||||||
|
|
||||||
type NotFoundError struct {
|
type NotFoundError struct {
|
||||||
|
|
@ -43,11 +53,74 @@ func IsNotFound(err error) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tryDefaultPath(cgroupPath, subsystem string) string {
|
||||||
|
if !strings.HasPrefix(defaultPrefix, cgroupPath) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove possible prefix
|
||||||
|
subsystem = strings.TrimPrefix(subsystem, CgroupNamePrefix)
|
||||||
|
|
||||||
|
// Make sure we're still under defaultPrefix, and resolve
|
||||||
|
// a possible symlink (like cpu -> cpu,cpuacct).
|
||||||
|
path, err := securejoin.SecureJoin(defaultPrefix, subsystem)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// (1) path should be a directory.
|
||||||
|
st, err := os.Lstat(path)
|
||||||
|
if err != nil || !st.IsDir() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// (2) path should be a mount point.
|
||||||
|
pst, err := os.Lstat(filepath.Dir(path))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if st.Sys().(*syscall.Stat_t).Dev == pst.Sys().(*syscall.Stat_t).Dev {
|
||||||
|
// parent dir has the same dev -- path is not a mount point
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// (3) path should have 'cgroup' fs type.
|
||||||
|
fst := unix.Statfs_t{}
|
||||||
|
err = unix.Statfs(path, &fst)
|
||||||
|
if err != nil || fst.Type != unix.CGROUP_SUPER_MAGIC {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// readCgroupMountinfo returns a list of cgroup v1 mounts (i.e. the ones
|
||||||
|
// with fstype of "cgroup") for the current running process.
|
||||||
|
//
|
||||||
|
// The results are cached (to avoid re-reading mountinfo which is relatively
|
||||||
|
// expensive), so it is assumed that cgroup mounts are not being changed.
|
||||||
|
func readCgroupMountinfo() ([]*mountinfo.Info, error) {
|
||||||
|
readMountinfoOnce.Do(func() {
|
||||||
|
cgroupMountinfo, readMountinfoErr = mountinfo.GetMounts(
|
||||||
|
mountinfo.FSTypeFilter("cgroup"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return cgroupMountinfo, readMountinfoErr
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
|
// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
|
||||||
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
|
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
|
||||||
if IsCgroup2UnifiedMode() {
|
if IsCgroup2UnifiedMode() {
|
||||||
return "", errUnified
|
return "", errUnified
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Avoid parsing mountinfo by trying the default path first, if possible.
|
||||||
|
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
|
mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
|
||||||
return mnt, err
|
return mnt, err
|
||||||
}
|
}
|
||||||
|
|
@ -57,58 +130,28 @@ func FindCgroupMountpointAndRoot(cgroupPath, subsystem string) (string, string,
|
||||||
return "", "", errUnified
|
return "", "", errUnified
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are not using mount.GetMounts() because it's super-inefficient,
|
mi, err := readCgroupMountinfo()
|
||||||
// parsing it directly sped up x10 times because of not using Sscanf.
|
|
||||||
// It was one of two major performance drawbacks in container start.
|
|
||||||
if !isSubsystemAvailable(subsystem) {
|
|
||||||
return "", "", NewNotFoundError(subsystem)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open("/proc/self/mountinfo")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return findCgroupMountpointAndRootFromReader(f, cgroupPath, subsystem)
|
return findCgroupMountpointAndRootFromMI(mi, cgroupPath, subsystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findCgroupMountpointAndRootFromReader(reader io.Reader, cgroupPath, subsystem string) (string, string, error) {
|
func findCgroupMountpointAndRootFromMI(mounts []*mountinfo.Info, cgroupPath, subsystem string) (string, string, error) {
|
||||||
scanner := bufio.NewScanner(reader)
|
for _, mi := range mounts {
|
||||||
for scanner.Scan() {
|
if strings.HasPrefix(mi.Mountpoint, cgroupPath) {
|
||||||
txt := scanner.Text()
|
for _, opt := range strings.Split(mi.VFSOptions, ",") {
|
||||||
fields := strings.Fields(txt)
|
|
||||||
if len(fields) < 9 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(fields[4], cgroupPath) {
|
|
||||||
for _, opt := range strings.Split(fields[len(fields)-1], ",") {
|
|
||||||
if opt == subsystem {
|
if opt == subsystem {
|
||||||
return fields[4], fields[3], nil
|
return mi.Mountpoint, mi.Root, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", "", NewNotFoundError(subsystem)
|
return "", "", NewNotFoundError(subsystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSubsystemAvailable(subsystem string) bool {
|
|
||||||
if IsCgroup2UnifiedMode() {
|
|
||||||
panic("don't call isSubsystemAvailable from cgroupv2 code")
|
|
||||||
}
|
|
||||||
|
|
||||||
cgroups, err := ParseCgroupFile("/proc/self/cgroup")
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
_, avail := cgroups[subsystem]
|
|
||||||
return avail
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
|
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
|
||||||
if len(m.Subsystems) == 0 {
|
if len(m.Subsystems) == 0 {
|
||||||
return "", fmt.Errorf("no subsystem for mount")
|
return "", fmt.Errorf("no subsystem for mount")
|
||||||
|
|
@ -117,25 +160,15 @@ func (m Mount) GetOwnCgroup(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, all bool) ([]Mount, error) {
|
func getCgroupMountsHelper(ss map[string]bool, mounts []*mountinfo.Info, all bool) ([]Mount, error) {
|
||||||
res := make([]Mount, 0, len(ss))
|
res := make([]Mount, 0, len(ss))
|
||||||
scanner := bufio.NewScanner(mi)
|
|
||||||
numFound := 0
|
numFound := 0
|
||||||
for scanner.Scan() && numFound < len(ss) {
|
for _, mi := range mounts {
|
||||||
txt := scanner.Text()
|
|
||||||
sepIdx := strings.Index(txt, " - ")
|
|
||||||
if sepIdx == -1 {
|
|
||||||
return nil, fmt.Errorf("invalid mountinfo format")
|
|
||||||
}
|
|
||||||
if txt[sepIdx+3:sepIdx+10] == "cgroup2" || txt[sepIdx+3:sepIdx+9] != "cgroup" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fields := strings.Split(txt, " ")
|
|
||||||
m := Mount{
|
m := Mount{
|
||||||
Mountpoint: fields[4],
|
Mountpoint: mi.Mountpoint,
|
||||||
Root: fields[3],
|
Root: mi.Root,
|
||||||
}
|
}
|
||||||
for _, opt := range strings.Split(fields[len(fields)-1], ",") {
|
for _, opt := range strings.Split(mi.VFSOptions, ",") {
|
||||||
seen, known := ss[opt]
|
seen, known := ss[opt]
|
||||||
if !known || (!all && seen) {
|
if !known || (!all && seen) {
|
||||||
continue
|
continue
|
||||||
|
|
@ -148,19 +181,18 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount,
|
||||||
if len(m.Subsystems) > 0 || all {
|
if len(m.Subsystems) > 0 || all {
|
||||||
res = append(res, m)
|
res = append(res, m)
|
||||||
}
|
}
|
||||||
}
|
if !all && numFound >= len(ss) {
|
||||||
if err := scanner.Err(); err != nil {
|
break
|
||||||
return nil, err
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCgroupMountsV1(all bool) ([]Mount, error) {
|
func getCgroupMountsV1(all bool) ([]Mount, error) {
|
||||||
f, err := os.Open("/proc/self/mountinfo")
|
mi, err := readCgroupMountinfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
allSubsystems, err := ParseCgroupFile("/proc/self/cgroup")
|
allSubsystems, err := ParseCgroupFile("/proc/self/cgroup")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -171,7 +203,8 @@ func getCgroupMountsV1(all bool) ([]Mount, error) {
|
||||||
for s := range allSubsystems {
|
for s := range allSubsystems {
|
||||||
allMap[s] = false
|
allMap[s] = false
|
||||||
}
|
}
|
||||||
return getCgroupMountsHelper(allMap, f, all)
|
|
||||||
|
return getCgroupMountsHelper(allMap, mi, all)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOwnCgroup returns the relative path to the cgroup docker is running in.
|
// GetOwnCgroup returns the relative path to the cgroup docker is running in.
|
||||||
|
|
|
||||||
13
common/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
13
common/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package configs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
|
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FreezerState string
|
type FreezerState string
|
||||||
|
|
@ -42,7 +43,7 @@ type Cgroup struct {
|
||||||
|
|
||||||
type Resources struct {
|
type Resources struct {
|
||||||
// Devices is the set of access rules for devices in the container.
|
// Devices is the set of access rules for devices in the container.
|
||||||
Devices []*DeviceRule `json:"devices"`
|
Devices []*devices.Rule `json:"devices"`
|
||||||
|
|
||||||
// Memory limit (in bytes)
|
// Memory limit (in bytes)
|
||||||
Memory int64 `json:"memory"`
|
Memory int64 `json:"memory"`
|
||||||
|
|
@ -126,4 +127,14 @@ type Resources struct {
|
||||||
|
|
||||||
// CpuWeight sets a proportional bandwidth limit.
|
// CpuWeight sets a proportional bandwidth limit.
|
||||||
CpuWeight uint64 `json:"cpu_weight"`
|
CpuWeight uint64 `json:"cpu_weight"`
|
||||||
|
|
||||||
|
// Unified is cgroupv2-only key-value map.
|
||||||
|
Unified map[string]string `json:"unified"`
|
||||||
|
|
||||||
|
// SkipDevices allows to skip configuring device permissions.
|
||||||
|
// Used by e.g. kubelet while creating a parent cgroup (kubepods)
|
||||||
|
// common for many containers.
|
||||||
|
//
|
||||||
|
// NOTE it is impossible to start a container which has this flag set.
|
||||||
|
SkipDevices bool `json:"skip_devices"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/opencontainers/runc/libcontainer/devices"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
@ -92,6 +93,9 @@ type Config struct {
|
||||||
// Path to a directory containing the container's root filesystem.
|
// Path to a directory containing the container's root filesystem.
|
||||||
Rootfs string `json:"rootfs"`
|
Rootfs string `json:"rootfs"`
|
||||||
|
|
||||||
|
// Umask is the umask to use inside of the container.
|
||||||
|
Umask *uint32 `json:"umask"`
|
||||||
|
|
||||||
// Readonlyfs will remount the container's rootfs as readonly where only externally mounted
|
// Readonlyfs will remount the container's rootfs as readonly where only externally mounted
|
||||||
// bind mounts are writtable.
|
// bind mounts are writtable.
|
||||||
Readonlyfs bool `json:"readonlyfs"`
|
Readonlyfs bool `json:"readonlyfs"`
|
||||||
|
|
@ -104,7 +108,7 @@ type Config struct {
|
||||||
Mounts []*Mount `json:"mounts"`
|
Mounts []*Mount `json:"mounts"`
|
||||||
|
|
||||||
// The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well!
|
// The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well!
|
||||||
Devices []*Device `json:"devices"`
|
Devices []*devices.Device `json:"devices"`
|
||||||
|
|
||||||
MountLabel string `json:"mount_label"`
|
MountLabel string `json:"mount_label"`
|
||||||
|
|
||||||
|
|
@ -239,15 +243,6 @@ const (
|
||||||
Poststop = "poststop"
|
Poststop = "poststop"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO move this to runtime-spec
|
|
||||||
// See: https://github.com/opencontainers/runtime-spec/pull/1046
|
|
||||||
const (
|
|
||||||
Creating = "creating"
|
|
||||||
Created = "created"
|
|
||||||
Running = "running"
|
|
||||||
Stopped = "stopped"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Capabilities struct {
|
type Capabilities struct {
|
||||||
// Bounding is the set of capabilities checked by the kernel.
|
// Bounding is the set of capabilities checked by the kernel.
|
||||||
Bounding []string
|
Bounding []string
|
||||||
|
|
|
||||||
17
common/vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go
generated
vendored
Normal file
17
common/vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package configs
|
||||||
|
|
||||||
|
import "github.com/opencontainers/runc/libcontainer/devices"
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Deprecated: use libcontainer/devices.Device
|
||||||
|
Device = devices.Device
|
||||||
|
|
||||||
|
// Deprecated: use libcontainer/devices.Rule
|
||||||
|
DeviceRule = devices.Rule
|
||||||
|
|
||||||
|
// Deprecated: use libcontainer/devices.Type
|
||||||
|
DeviceType = devices.Type
|
||||||
|
|
||||||
|
// Deprecated: use libcontainer/devices.Permissions
|
||||||
|
DevicePermissions = devices.Permissions
|
||||||
|
)
|
||||||
|
|
@ -56,7 +56,7 @@ func IsNamespaceSupported(ns NamespaceType) bool {
|
||||||
if nsFile == "" {
|
if nsFile == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile))
|
_, err := os.Stat("/proc/self/ns/" + nsFile)
|
||||||
// a namespace is supported if it exists and we have permissions to read it
|
// a namespace is supported if it exists and we have permissions to read it
|
||||||
supported = err == nil
|
supported = err == nil
|
||||||
supportedNamespaces[ns] = supported
|
supportedNamespaces[ns] = supported
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,17 @@
|
||||||
package configs
|
package devices
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Wildcard = -1
|
Wildcard = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO Windows: This can be factored out in the future
|
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
DeviceRule
|
Rule
|
||||||
|
|
||||||
// Path to the device.
|
// Path to the device.
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
|
@ -31,10 +26,10 @@ type Device struct {
|
||||||
Gid uint32 `json:"gid"`
|
Gid uint32 `json:"gid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DevicePermissions is a cgroupv1-style string to represent device access. It
|
// Permissions is a cgroupv1-style string to represent device access. It
|
||||||
// has to be a string for backward compatibility reasons, hence why it has
|
// has to be a string for backward compatibility reasons, hence why it has
|
||||||
// methods to do set operations.
|
// methods to do set operations.
|
||||||
type DevicePermissions string
|
type Permissions string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
deviceRead uint = (1 << iota)
|
deviceRead uint = (1 << iota)
|
||||||
|
|
@ -42,7 +37,7 @@ const (
|
||||||
deviceMknod
|
deviceMknod
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p DevicePermissions) toSet() uint {
|
func (p Permissions) toSet() uint {
|
||||||
var set uint
|
var set uint
|
||||||
for _, perm := range p {
|
for _, perm := range p {
|
||||||
switch perm {
|
switch perm {
|
||||||
|
|
@ -57,7 +52,7 @@ func (p DevicePermissions) toSet() uint {
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromSet(set uint) DevicePermissions {
|
func fromSet(set uint) Permissions {
|
||||||
var perm string
|
var perm string
|
||||||
if set&deviceRead == deviceRead {
|
if set&deviceRead == deviceRead {
|
||||||
perm += "r"
|
perm += "r"
|
||||||
|
|
@ -68,53 +63,53 @@ func fromSet(set uint) DevicePermissions {
|
||||||
if set&deviceMknod == deviceMknod {
|
if set&deviceMknod == deviceMknod {
|
||||||
perm += "m"
|
perm += "m"
|
||||||
}
|
}
|
||||||
return DevicePermissions(perm)
|
return Permissions(perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Union returns the union of the two sets of DevicePermissions.
|
// Union returns the union of the two sets of Permissions.
|
||||||
func (p DevicePermissions) Union(o DevicePermissions) DevicePermissions {
|
func (p Permissions) Union(o Permissions) Permissions {
|
||||||
lhs := p.toSet()
|
lhs := p.toSet()
|
||||||
rhs := o.toSet()
|
rhs := o.toSet()
|
||||||
return fromSet(lhs | rhs)
|
return fromSet(lhs | rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Difference returns the set difference of the two sets of DevicePermissions.
|
// Difference returns the set difference of the two sets of Permissions.
|
||||||
// In set notation, A.Difference(B) gives you A\B.
|
// In set notation, A.Difference(B) gives you A\B.
|
||||||
func (p DevicePermissions) Difference(o DevicePermissions) DevicePermissions {
|
func (p Permissions) Difference(o Permissions) Permissions {
|
||||||
lhs := p.toSet()
|
lhs := p.toSet()
|
||||||
rhs := o.toSet()
|
rhs := o.toSet()
|
||||||
return fromSet(lhs &^ rhs)
|
return fromSet(lhs &^ rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection computes the intersection of the two sets of DevicePermissions.
|
// Intersection computes the intersection of the two sets of Permissions.
|
||||||
func (p DevicePermissions) Intersection(o DevicePermissions) DevicePermissions {
|
func (p Permissions) Intersection(o Permissions) Permissions {
|
||||||
lhs := p.toSet()
|
lhs := p.toSet()
|
||||||
rhs := o.toSet()
|
rhs := o.toSet()
|
||||||
return fromSet(lhs & rhs)
|
return fromSet(lhs & rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty returns whether the set of permissions in a DevicePermissions is
|
// IsEmpty returns whether the set of permissions in a Permissions is
|
||||||
// empty.
|
// empty.
|
||||||
func (p DevicePermissions) IsEmpty() bool {
|
func (p Permissions) IsEmpty() bool {
|
||||||
return p == DevicePermissions("")
|
return p == Permissions("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid returns whether the set of permissions is a subset of valid
|
// IsValid returns whether the set of permissions is a subset of valid
|
||||||
// permissions (namely, {r,w,m}).
|
// permissions (namely, {r,w,m}).
|
||||||
func (p DevicePermissions) IsValid() bool {
|
func (p Permissions) IsValid() bool {
|
||||||
return p == fromSet(p.toSet())
|
return p == fromSet(p.toSet())
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceType rune
|
type Type rune
|
||||||
|
|
||||||
const (
|
const (
|
||||||
WildcardDevice DeviceType = 'a'
|
WildcardDevice Type = 'a'
|
||||||
BlockDevice DeviceType = 'b'
|
BlockDevice Type = 'b'
|
||||||
CharDevice DeviceType = 'c' // or 'u'
|
CharDevice Type = 'c' // or 'u'
|
||||||
FifoDevice DeviceType = 'p'
|
FifoDevice Type = 'p'
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t DeviceType) IsValid() bool {
|
func (t Type) IsValid() bool {
|
||||||
switch t {
|
switch t {
|
||||||
case WildcardDevice, BlockDevice, CharDevice, FifoDevice:
|
case WildcardDevice, BlockDevice, CharDevice, FifoDevice:
|
||||||
return true
|
return true
|
||||||
|
|
@ -123,7 +118,7 @@ func (t DeviceType) IsValid() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t DeviceType) CanMknod() bool {
|
func (t Type) CanMknod() bool {
|
||||||
switch t {
|
switch t {
|
||||||
case BlockDevice, CharDevice, FifoDevice:
|
case BlockDevice, CharDevice, FifoDevice:
|
||||||
return true
|
return true
|
||||||
|
|
@ -132,7 +127,7 @@ func (t DeviceType) CanMknod() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t DeviceType) CanCgroup() bool {
|
func (t Type) CanCgroup() bool {
|
||||||
switch t {
|
switch t {
|
||||||
case WildcardDevice, BlockDevice, CharDevice:
|
case WildcardDevice, BlockDevice, CharDevice:
|
||||||
return true
|
return true
|
||||||
|
|
@ -141,10 +136,10 @@ func (t DeviceType) CanCgroup() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceRule struct {
|
type Rule struct {
|
||||||
// Type of device ('c' for char, 'b' for block). If set to 'a', this rule
|
// Type of device ('c' for char, 'b' for block). If set to 'a', this rule
|
||||||
// acts as a wildcard and all fields other than Allow are ignored.
|
// acts as a wildcard and all fields other than Allow are ignored.
|
||||||
Type DeviceType `json:"type"`
|
Type Type `json:"type"`
|
||||||
|
|
||||||
// Major is the device's major number.
|
// Major is the device's major number.
|
||||||
Major int64 `json:"major"`
|
Major int64 `json:"major"`
|
||||||
|
|
@ -154,13 +149,13 @@ type DeviceRule struct {
|
||||||
|
|
||||||
// Permissions is the set of permissions that this rule applies to (in the
|
// Permissions is the set of permissions that this rule applies to (in the
|
||||||
// cgroupv1 format -- any combination of "rwm").
|
// cgroupv1 format -- any combination of "rwm").
|
||||||
Permissions DevicePermissions `json:"permissions"`
|
Permissions Permissions `json:"permissions"`
|
||||||
|
|
||||||
// Allow specifies whether this rule is allowed.
|
// Allow specifies whether this rule is allowed.
|
||||||
Allow bool `json:"allow"`
|
Allow bool `json:"allow"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeviceRule) CgroupString() string {
|
func (d *Rule) CgroupString() string {
|
||||||
var (
|
var (
|
||||||
major = strconv.FormatInt(d.Major, 10)
|
major = strconv.FormatInt(d.Major, 10)
|
||||||
minor = strconv.FormatInt(d.Minor, 10)
|
minor = strconv.FormatInt(d.Minor, 10)
|
||||||
|
|
@ -173,10 +168,3 @@ func (d *DeviceRule) CgroupString() string {
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%c %s:%s %s", d.Type, major, minor, d.Permissions)
|
return fmt.Sprintf("%c %s:%s %s", d.Type, major, minor, d.Permissions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeviceRule) Mkdev() (uint64, error) {
|
|
||||||
if d.Major == Wildcard || d.Minor == Wildcard {
|
|
||||||
return 0, errors.New("cannot mkdev() device with wildcards")
|
|
||||||
}
|
|
||||||
return unix.Mkdev(uint32(d.Major), uint32(d.Minor)), nil
|
|
||||||
}
|
|
||||||
16
common/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
Normal file
16
common/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package devices
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *Rule) Mkdev() (uint64, error) {
|
||||||
|
if d.Major == Wildcard || d.Minor == Wildcard {
|
||||||
|
return 0, errors.New("cannot mkdev() device with wildcards")
|
||||||
|
}
|
||||||
|
return unix.Mkdev(uint32(d.Major), uint32(d.Minor)), nil
|
||||||
|
}
|
||||||
5
common/vendor/github.com/opencontainers/runc/libcontainer/devices/device_windows.go
generated
vendored
Normal file
5
common/vendor/github.com/opencontainers/runc/libcontainer/devices/device_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package devices
|
||||||
|
|
||||||
|
func (d *Rule) Mkdev() (uint64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -23,7 +22,7 @@ var (
|
||||||
|
|
||||||
// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the
|
// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the
|
||||||
// information about a linux device and return that information as a Device struct.
|
// information about a linux device and return that information as a Device struct.
|
||||||
func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||||
var stat unix.Stat_t
|
var stat unix.Stat_t
|
||||||
err := unixLstat(path, &stat)
|
err := unixLstat(path, &stat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -31,28 +30,28 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
devType configs.DeviceType
|
devType Type
|
||||||
mode = stat.Mode
|
mode = stat.Mode
|
||||||
devNumber = uint64(stat.Rdev)
|
devNumber = uint64(stat.Rdev)
|
||||||
major = unix.Major(devNumber)
|
major = unix.Major(devNumber)
|
||||||
minor = unix.Minor(devNumber)
|
minor = unix.Minor(devNumber)
|
||||||
)
|
)
|
||||||
switch {
|
switch mode & unix.S_IFMT {
|
||||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
case unix.S_IFBLK:
|
||||||
devType = configs.BlockDevice
|
devType = BlockDevice
|
||||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
case unix.S_IFCHR:
|
||||||
devType = configs.CharDevice
|
devType = CharDevice
|
||||||
case mode&unix.S_IFIFO == unix.S_IFIFO:
|
case unix.S_IFIFO:
|
||||||
devType = configs.FifoDevice
|
devType = FifoDevice
|
||||||
default:
|
default:
|
||||||
return nil, ErrNotADevice
|
return nil, ErrNotADevice
|
||||||
}
|
}
|
||||||
return &configs.Device{
|
return &Device{
|
||||||
DeviceRule: configs.DeviceRule{
|
Rule: Rule{
|
||||||
Type: devType,
|
Type: devType,
|
||||||
Major: int64(major),
|
Major: int64(major),
|
||||||
Minor: int64(minor),
|
Minor: int64(minor),
|
||||||
Permissions: configs.DevicePermissions(permissions),
|
Permissions: Permissions(permissions),
|
||||||
},
|
},
|
||||||
Path: path,
|
Path: path,
|
||||||
FileMode: os.FileMode(mode),
|
FileMode: os.FileMode(mode),
|
||||||
|
|
@ -62,18 +61,18 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostDevices returns all devices that can be found under /dev directory.
|
// HostDevices returns all devices that can be found under /dev directory.
|
||||||
func HostDevices() ([]*configs.Device, error) {
|
func HostDevices() ([]*Device, error) {
|
||||||
return GetDevices("/dev")
|
return GetDevices("/dev")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDevices recursively traverses a directory specified by path
|
// GetDevices recursively traverses a directory specified by path
|
||||||
// and returns all devices found there.
|
// and returns all devices found there.
|
||||||
func GetDevices(path string) ([]*configs.Device, error) {
|
func GetDevices(path string) ([]*Device, error) {
|
||||||
files, err := ioutilReadDir(path)
|
files, err := ioutilReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var out []*configs.Device
|
var out []*Device
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
switch {
|
switch {
|
||||||
case f.IsDir():
|
case f.IsDir():
|
||||||
|
|
@ -104,6 +103,9 @@ func GetDevices(path string) ([]*configs.Device, error) {
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if device.Type == FifoDevice {
|
||||||
|
continue
|
||||||
|
}
|
||||||
out = append(out, device)
|
out = append(out, device)
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
|
|
|
||||||
|
|
@ -71,16 +71,6 @@ func Stat(pid int) (stat Stat_t, err error) {
|
||||||
return parseStat(string(bytes))
|
return parseStat(string(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProcessStartTime is deprecated. Use Stat(pid) and
|
|
||||||
// Stat_t.StartTime instead.
|
|
||||||
func GetProcessStartTime(pid int) (string, error) {
|
|
||||||
stat, err := Stat(pid)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%d", stat.StartTime), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseStat(data string) (stat Stat_t, err error) {
|
func parseStat(data string) (stat Stat_t, err error) {
|
||||||
// From proc(5), field 2 could contain space and is inside `(` and `)`.
|
// From proc(5), field 2 could contain space and is inside `(` and `)`.
|
||||||
// The following is an example:
|
// The following is an example:
|
||||||
|
|
|
||||||
6
common/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_windows.go
generated
vendored
6
common/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_windows.go
generated
vendored
|
|
@ -3,8 +3,8 @@
|
||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os/user"
|
"os/user"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func lookupUser(username string) (User, error) {
|
func lookupUser(username string) (User, error) {
|
||||||
|
|
@ -16,7 +16,7 @@ func lookupUser(username string) (User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupUid(uid int) (User, error) {
|
func lookupUid(uid int) (User, error) {
|
||||||
u, err := user.LookupId(fmt.Sprintf("%d", uid))
|
u, err := user.LookupId(strconv.Itoa(uid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return User{}, err
|
return User{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ func lookupGroup(groupname string) (Group, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupGid(gid int) (Group, error) {
|
func lookupGid(gid int) (Group, error) {
|
||||||
g, err := user.LookupGroupId(fmt.Sprintf("%d", gid))
|
g, err := user.LookupGroupId(strconv.Itoa(gid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Group{}, err
|
return Group{}, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ type Group struct {
|
||||||
|
|
||||||
// groupFromOS converts an os/user.(*Group) to local Group
|
// groupFromOS converts an os/user.(*Group) to local Group
|
||||||
//
|
//
|
||||||
// (This does not include Pass, Shell or Gecos)
|
// (This does not include Pass or List)
|
||||||
func groupFromOS(g *user.Group) (Group, error) {
|
func groupFromOS(g *user.Group) (Group, error) {
|
||||||
newGroup := Group{
|
newGroup := Group{
|
||||||
Name: g.Name,
|
Name: g.Name,
|
||||||
|
|
@ -466,7 +466,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
|
||||||
// we asked for a group but didn't find it. let's check to see
|
// we asked for a group but didn't find it. let's check to see
|
||||||
// if we wanted a numeric group
|
// if we wanted a numeric group
|
||||||
if !found {
|
if !found {
|
||||||
gid, err := strconv.Atoi(ag)
|
gid, err := strconv.ParseInt(ag, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unable to find group %s", ag)
|
return nil, fmt.Errorf("Unable to find group %s", ag)
|
||||||
}
|
}
|
||||||
|
|
@ -474,7 +474,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
|
||||||
if gid < minId || gid > maxId {
|
if gid < minId || gid > maxId {
|
||||||
return nil, ErrRange
|
return nil, ErrRange
|
||||||
}
|
}
|
||||||
gidMap[gid] = struct{}{}
|
gidMap[int(gid)] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gids := []int{}
|
gids := []int{}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -15,6 +16,20 @@ const (
|
||||||
exitSignalOffset = 128
|
exitSignalOffset = 128
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NativeEndian is the native byte order of the host system.
|
||||||
|
var NativeEndian binary.ByteOrder
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Copied from <golang.org/x/net/internal/socket/sys.go>.
|
||||||
|
i := uint32(1)
|
||||||
|
b := (*[4]byte)(unsafe.Pointer(&i))
|
||||||
|
if b[0] == 1 {
|
||||||
|
NativeEndian = binary.LittleEndian
|
||||||
|
} else {
|
||||||
|
NativeEndian = binary.BigEndian
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResolveRootfs ensures that the current working directory is
|
// ResolveRootfs ensures that the current working directory is
|
||||||
// not a symlink and returns the absolute path to the rootfs
|
// not a symlink and returns the absolute path to the rootfs
|
||||||
func ResolveRootfs(uncleanRootfs string) (string, error) {
|
func ResolveRootfs(uncleanRootfs string) (string, error) {
|
||||||
|
|
@ -106,7 +121,3 @@ func Annotations(labels []string) (bundle string, userAnnotations map[string]str
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetIntSize() int {
|
|
||||||
return int(unsafe.Sizeof(1))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ type Process struct {
|
||||||
SelinuxLabel string `json:"selinuxLabel,omitempty" platform:"linux"`
|
SelinuxLabel string `json:"selinuxLabel,omitempty" platform:"linux"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxCapabilities specifies the whitelist of capabilities that are kept for a process.
|
// LinuxCapabilities specifies the list of allowed capabilities that are kept for a process.
|
||||||
// http://man7.org/linux/man-pages/man7/capabilities.7.html
|
// http://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||||
type LinuxCapabilities struct {
|
type LinuxCapabilities struct {
|
||||||
// Bounding is the set of capabilities checked by the kernel.
|
// Bounding is the set of capabilities checked by the kernel.
|
||||||
|
|
@ -90,7 +90,7 @@ type User struct {
|
||||||
// GID is the group id.
|
// GID is the group id.
|
||||||
GID uint32 `json:"gid" platform:"linux,solaris"`
|
GID uint32 `json:"gid" platform:"linux,solaris"`
|
||||||
// Umask is the umask for the init process.
|
// Umask is the umask for the init process.
|
||||||
Umask uint32 `json:"umask,omitempty" platform:"linux,solaris"`
|
Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
|
||||||
// AdditionalGids are additional group ids set for the container's process.
|
// AdditionalGids are additional group ids set for the container's process.
|
||||||
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
|
||||||
// Username is the user name.
|
// Username is the user name.
|
||||||
|
|
@ -354,7 +354,7 @@ type LinuxRdma struct {
|
||||||
|
|
||||||
// LinuxResources has container runtime resource constraints
|
// LinuxResources has container runtime resource constraints
|
||||||
type LinuxResources struct {
|
type LinuxResources struct {
|
||||||
// Devices configures the device whitelist.
|
// Devices configures the device allowlist.
|
||||||
Devices []LinuxDeviceCgroup `json:"devices,omitempty"`
|
Devices []LinuxDeviceCgroup `json:"devices,omitempty"`
|
||||||
// Memory restriction configuration
|
// Memory restriction configuration
|
||||||
Memory *LinuxMemory `json:"memory,omitempty"`
|
Memory *LinuxMemory `json:"memory,omitempty"`
|
||||||
|
|
@ -372,6 +372,8 @@ type LinuxResources struct {
|
||||||
// Limits are a set of key value pairs that define RDMA resource limits,
|
// Limits are a set of key value pairs that define RDMA resource limits,
|
||||||
// where the key is device name and value is resource limits.
|
// where the key is device name and value is resource limits.
|
||||||
Rdma map[string]LinuxRdma `json:"rdma,omitempty"`
|
Rdma map[string]LinuxRdma `json:"rdma,omitempty"`
|
||||||
|
// Unified resources.
|
||||||
|
Unified map[string]string `json:"unified,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxDevice represents the mknod information for a Linux special device file
|
// LinuxDevice represents the mknod information for a Linux special device file
|
||||||
|
|
@ -392,7 +394,8 @@ type LinuxDevice struct {
|
||||||
GID *uint32 `json:"gid,omitempty"`
|
GID *uint32 `json:"gid,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxDeviceCgroup represents a device rule for the whitelist controller
|
// LinuxDeviceCgroup represents a device rule for the devices specified to
|
||||||
|
// the device controller
|
||||||
type LinuxDeviceCgroup struct {
|
type LinuxDeviceCgroup struct {
|
||||||
// Allow or deny
|
// Allow or deny
|
||||||
Allow bool `json:"allow"`
|
Allow bool `json:"allow"`
|
||||||
|
|
@ -628,6 +631,7 @@ const (
|
||||||
ArchS390X Arch = "SCMP_ARCH_S390X"
|
ArchS390X Arch = "SCMP_ARCH_S390X"
|
||||||
ArchPARISC Arch = "SCMP_ARCH_PARISC"
|
ArchPARISC Arch = "SCMP_ARCH_PARISC"
|
||||||
ArchPARISC64 Arch = "SCMP_ARCH_PARISC64"
|
ArchPARISC64 Arch = "SCMP_ARCH_PARISC64"
|
||||||
|
ArchRISCV64 Arch = "SCMP_ARCH_RISCV64"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LinuxSeccompAction taken upon Seccomp rule match
|
// LinuxSeccompAction taken upon Seccomp rule match
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ type State struct {
|
||||||
// ID is the container ID
|
// ID is the container ID
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
// Status is the runtime status of the container.
|
// Status is the runtime status of the container.
|
||||||
Status string `json:"status"`
|
Status ContainerState `json:"status"`
|
||||||
// Pid is the process ID for the container process.
|
// Pid is the process ID for the container process.
|
||||||
Pid int `json:"pid,omitempty"`
|
Pid int `json:"pid,omitempty"`
|
||||||
// Bundle is the path to the container's bundle directory.
|
// Bundle is the path to the container's bundle directory.
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ const (
|
||||||
//go:generate go run enumgen/gen.go
|
//go:generate go run enumgen/gen.go
|
||||||
type Cap int
|
type Cap int
|
||||||
|
|
||||||
// POSIX-draft defined capabilities.
|
// POSIX-draft defined capabilities and Linux extensions.
|
||||||
|
//
|
||||||
|
// Defined in https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h
|
||||||
const (
|
const (
|
||||||
// In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
|
// In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
|
||||||
// overrides the restriction of changing file ownership and group
|
// overrides the restriction of changing file ownership and group
|
||||||
|
|
@ -187,6 +189,7 @@ const (
|
||||||
// arbitrary SCSI commands
|
// arbitrary SCSI commands
|
||||||
// Allow setting encryption key on loopback filesystem
|
// Allow setting encryption key on loopback filesystem
|
||||||
// Allow setting zone reclaim policy
|
// Allow setting zone reclaim policy
|
||||||
|
// Allow everything under CAP_BPF and CAP_PERFMON for backward compatibility
|
||||||
CAP_SYS_ADMIN = Cap(21)
|
CAP_SYS_ADMIN = Cap(21)
|
||||||
|
|
||||||
// Allow use of reboot()
|
// Allow use of reboot()
|
||||||
|
|
@ -211,6 +214,7 @@ const (
|
||||||
// Allow more than 64hz interrupts from the real-time clock
|
// Allow more than 64hz interrupts from the real-time clock
|
||||||
// Override max number of consoles on console allocation
|
// Override max number of consoles on console allocation
|
||||||
// Override max number of keymaps
|
// Override max number of keymaps
|
||||||
|
// Control memory reclaim behavior
|
||||||
CAP_SYS_RESOURCE = Cap(24)
|
CAP_SYS_RESOURCE = Cap(24)
|
||||||
|
|
||||||
// Allow manipulation of system clock
|
// Allow manipulation of system clock
|
||||||
|
|
@ -256,8 +260,45 @@ const (
|
||||||
// Allow preventing system suspends
|
// Allow preventing system suspends
|
||||||
CAP_BLOCK_SUSPEND = Cap(36)
|
CAP_BLOCK_SUSPEND = Cap(36)
|
||||||
|
|
||||||
// Allow reading audit messages from the kernel
|
// Allow reading the audit log via multicast netlink socket
|
||||||
CAP_AUDIT_READ = Cap(37)
|
CAP_AUDIT_READ = Cap(37)
|
||||||
|
|
||||||
|
// Allow system performance and observability privileged operations
|
||||||
|
// using perf_events, i915_perf and other kernel subsystems
|
||||||
|
CAP_PERFMON = Cap(38)
|
||||||
|
|
||||||
|
// CAP_BPF allows the following BPF operations:
|
||||||
|
// - Creating all types of BPF maps
|
||||||
|
// - Advanced verifier features
|
||||||
|
// - Indirect variable access
|
||||||
|
// - Bounded loops
|
||||||
|
// - BPF to BPF function calls
|
||||||
|
// - Scalar precision tracking
|
||||||
|
// - Larger complexity limits
|
||||||
|
// - Dead code elimination
|
||||||
|
// - And potentially other features
|
||||||
|
// - Loading BPF Type Format (BTF) data
|
||||||
|
// - Retrieve xlated and JITed code of BPF programs
|
||||||
|
// - Use bpf_spin_lock() helper
|
||||||
|
//
|
||||||
|
// CAP_PERFMON relaxes the verifier checks further:
|
||||||
|
// - BPF progs can use of pointer-to-integer conversions
|
||||||
|
// - speculation attack hardening measures are bypassed
|
||||||
|
// - bpf_probe_read to read arbitrary kernel memory is allowed
|
||||||
|
// - bpf_trace_printk to print kernel memory is allowed
|
||||||
|
//
|
||||||
|
// CAP_SYS_ADMIN is required to use bpf_probe_write_user.
|
||||||
|
//
|
||||||
|
// CAP_SYS_ADMIN is required to iterate system wide loaded
|
||||||
|
// programs, maps, links, BTFs and convert their IDs to file descriptors.
|
||||||
|
//
|
||||||
|
// CAP_PERFMON and CAP_BPF are required to load tracing programs.
|
||||||
|
// CAP_NET_ADMIN and CAP_BPF are required to load networking programs.
|
||||||
|
CAP_BPF = Cap(39)
|
||||||
|
|
||||||
|
// Allow checkpoint/restore related operations.
|
||||||
|
// Introduced in kernel 5.9
|
||||||
|
CAP_CHECKPOINT_RESTORE = Cap(40)
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,12 @@ func (c Cap) String() string {
|
||||||
return "block_suspend"
|
return "block_suspend"
|
||||||
case CAP_AUDIT_READ:
|
case CAP_AUDIT_READ:
|
||||||
return "audit_read"
|
return "audit_read"
|
||||||
|
case CAP_PERFMON:
|
||||||
|
return "perfmon"
|
||||||
|
case CAP_BPF:
|
||||||
|
return "bpf"
|
||||||
|
case CAP_CHECKPOINT_RESTORE:
|
||||||
|
return "checkpoint_restore"
|
||||||
}
|
}
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
@ -125,5 +131,8 @@ func List() []Cap {
|
||||||
CAP_WAKE_ALARM,
|
CAP_WAKE_ALARM,
|
||||||
CAP_BLOCK_SUSPEND,
|
CAP_BLOCK_SUSPEND,
|
||||||
CAP_AUDIT_READ,
|
CAP_AUDIT_READ,
|
||||||
|
CAP_PERFMON,
|
||||||
|
CAP_BPF,
|
||||||
|
CAP_CHECKPOINT_RESTORE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,10 @@ github.com/containers/storage/pkg/system
|
||||||
github.com/containers/storage/pkg/tarlog
|
github.com/containers/storage/pkg/tarlog
|
||||||
github.com/containers/storage/pkg/truncindex
|
github.com/containers/storage/pkg/truncindex
|
||||||
github.com/containers/storage/pkg/unshare
|
github.com/containers/storage/pkg/unshare
|
||||||
# github.com/coreos/go-systemd/v22 v22.0.0
|
# github.com/coreos/go-systemd/v22 v22.1.0
|
||||||
github.com/coreos/go-systemd/v22/dbus
|
github.com/coreos/go-systemd/v22/dbus
|
||||||
|
# github.com/cyphar/filepath-securejoin v0.2.2
|
||||||
|
github.com/cyphar/filepath-securejoin
|
||||||
# github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/davecgh/go-spew/spew
|
github.com/davecgh/go-spew/spew
|
||||||
# github.com/docker/distribution v2.7.1+incompatible
|
# github.com/docker/distribution v2.7.1+incompatible
|
||||||
|
|
@ -148,10 +150,8 @@ github.com/godbus/dbus/v5
|
||||||
github.com/gogo/protobuf/gogoproto
|
github.com/gogo/protobuf/gogoproto
|
||||||
github.com/gogo/protobuf/proto
|
github.com/gogo/protobuf/proto
|
||||||
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
|
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
|
||||||
# github.com/golang/protobuf v1.4.2
|
# github.com/golang/protobuf v1.4.3
|
||||||
github.com/golang/protobuf/proto
|
github.com/golang/protobuf/proto
|
||||||
# github.com/google/go-cmp v0.5.2
|
|
||||||
## explicit
|
|
||||||
# github.com/gorilla/mux v1.8.0
|
# github.com/gorilla/mux v1.8.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/gorilla/mux
|
github.com/gorilla/mux
|
||||||
|
|
@ -227,16 +227,17 @@ github.com/opencontainers/go-digest
|
||||||
# github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
# github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
||||||
github.com/opencontainers/image-spec/specs-go
|
github.com/opencontainers/image-spec/specs-go
|
||||||
github.com/opencontainers/image-spec/specs-go/v1
|
github.com/opencontainers/image-spec/specs-go/v1
|
||||||
# github.com/opencontainers/runc v1.0.0-rc91
|
# github.com/opencontainers/runc v1.0.0-rc93
|
||||||
## explicit
|
## explicit
|
||||||
github.com/opencontainers/runc/libcontainer/apparmor
|
github.com/opencontainers/runc/libcontainer/apparmor
|
||||||
github.com/opencontainers/runc/libcontainer/cgroups
|
github.com/opencontainers/runc/libcontainer/cgroups
|
||||||
|
github.com/opencontainers/runc/libcontainer/cgroups/fscommon
|
||||||
github.com/opencontainers/runc/libcontainer/configs
|
github.com/opencontainers/runc/libcontainer/configs
|
||||||
github.com/opencontainers/runc/libcontainer/devices
|
github.com/opencontainers/runc/libcontainer/devices
|
||||||
github.com/opencontainers/runc/libcontainer/system
|
github.com/opencontainers/runc/libcontainer/system
|
||||||
github.com/opencontainers/runc/libcontainer/user
|
github.com/opencontainers/runc/libcontainer/user
|
||||||
github.com/opencontainers/runc/libcontainer/utils
|
github.com/opencontainers/runc/libcontainer/utils
|
||||||
# github.com/opencontainers/runtime-spec v1.0.3-0.20200710190001-3e4195d92445
|
# github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
|
||||||
## explicit
|
## explicit
|
||||||
github.com/opencontainers/runtime-spec/specs-go
|
github.com/opencontainers/runtime-spec/specs-go
|
||||||
# github.com/opencontainers/runtime-tools v0.9.0
|
# github.com/opencontainers/runtime-tools v0.9.0
|
||||||
|
|
@ -292,7 +293,7 @@ github.com/spf13/pflag
|
||||||
## explicit
|
## explicit
|
||||||
github.com/stretchr/testify/assert
|
github.com/stretchr/testify/assert
|
||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
# github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||||
## explicit
|
## explicit
|
||||||
github.com/syndtr/gocapability/capability
|
github.com/syndtr/gocapability/capability
|
||||||
# github.com/tchap/go-patricia v2.3.0+incompatible
|
# github.com/tchap/go-patricia v2.3.0+incompatible
|
||||||
|
|
@ -323,7 +324,7 @@ go.opencensus.io/trace/tracestate
|
||||||
# golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
# golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
## explicit
|
## explicit
|
||||||
golang.org/x/crypto/ssh/terminal
|
golang.org/x/crypto/ssh/terminal
|
||||||
# golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
|
# golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
golang.org/x/net/html
|
golang.org/x/net/html
|
||||||
golang.org/x/net/html/atom
|
golang.org/x/net/html/atom
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue