Update libcontainer to a37b2a4f152e2a1c9de596f54c0
| ... | ... |
@@ -65,7 +65,7 @@ mv tmp-digest src/github.com/docker/distribution/digest |
| 65 | 65 |
mkdir -p src/github.com/docker/distribution/registry |
| 66 | 66 |
mv tmp-api src/github.com/docker/distribution/registry/api |
| 67 | 67 |
|
| 68 |
-clone git github.com/docker/libcontainer 90f8aa670f1f424041059060c7c63fe4dee2e441 |
|
| 68 |
+clone git github.com/docker/libcontainer a37b2a4f152e2a1c9de596f54c051cb889de0691 |
|
| 69 | 69 |
# libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh) |
| 70 | 70 |
clone git github.com/coreos/go-systemd v2 |
| 71 | 71 |
clone git github.com/godbus/dbus v2 |
| ... | ... |
@@ -3245,8 +3245,8 @@ func (s *DockerSuite) TestMountIntoProc(c *check.C) {
|
| 3245 | 3245 |
func (s *DockerSuite) TestMountIntoSys(c *check.C) {
|
| 3246 | 3246 |
testRequires(c, NativeExecDriver) |
| 3247 | 3247 |
defer deleteAllContainers() |
| 3248 |
- code, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/sys/", "busybox", "true")) |
|
| 3249 |
- if err == nil || code == 0 {
|
|
| 3250 |
- c.Fatal("container should not be able to mount into /sys")
|
|
| 3248 |
+ _, err := runCommand(exec.Command(dockerBinary, "run", "-v", "/sys/fs/cgroup", "busybox", "true")) |
|
| 3249 |
+ if err != nil {
|
|
| 3250 |
+ c.Fatal("container should be able to mount into /sys/fs/cgroup")
|
|
| 3251 | 3251 |
} |
| 3252 | 3252 |
} |
| ... | ... |
@@ -262,6 +262,11 @@ func (raw *data) join(subsystem string) (string, error) {
|
| 262 | 262 |
} |
| 263 | 263 |
|
| 264 | 264 |
func writeFile(dir, file, data string) error {
|
| 265 |
+ // Normally dir should not be empty, one case is that cgroup subsystem |
|
| 266 |
+ // is not mounted, we will get empty dir, and we want it fail here. |
|
| 267 |
+ if dir == "" {
|
|
| 268 |
+ return fmt.Errorf("no such directory for %s.", file)
|
|
| 269 |
+ } |
|
| 265 | 270 |
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) |
| 266 | 271 |
} |
| 267 | 272 |
|
| ... | ... |
@@ -17,7 +17,7 @@ func (s *CpuGroup) Apply(d *data) error {
|
| 17 | 17 |
// We always want to join the cpu group, to allow fair cpu scheduling |
| 18 | 18 |
// on a container basis |
| 19 | 19 |
dir, err := d.join("cpu")
|
| 20 |
- if err != nil {
|
|
| 20 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 21 | 21 |
return err |
| 22 | 22 |
} |
| 23 | 23 |
|
| ... | ... |
@@ -16,7 +16,7 @@ type CpusetGroup struct {
|
| 16 | 16 |
|
| 17 | 17 |
func (s *CpusetGroup) Apply(d *data) error {
|
| 18 | 18 |
dir, err := d.path("cpuset")
|
| 19 |
- if err != nil {
|
|
| 19 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 20 | 20 |
return err |
| 21 | 21 |
} |
| 22 | 22 |
|
| ... | ... |
@@ -48,6 +48,11 @@ func (s *CpusetGroup) GetStats(path string, stats *cgroups.Stats) error {
|
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 | 50 |
func (s *CpusetGroup) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error {
|
| 51 |
+ // This might happen if we have no cpuset cgroup mounted. |
|
| 52 |
+ // Just do nothing and don't fail. |
|
| 53 |
+ if dir == "" {
|
|
| 54 |
+ return nil |
|
| 55 |
+ } |
|
| 51 | 56 |
if err := s.ensureParent(dir); err != nil {
|
| 52 | 57 |
return err |
| 53 | 58 |
} |
| ... | ... |
@@ -11,6 +11,8 @@ type DevicesGroup struct {
|
| 11 | 11 |
func (s *DevicesGroup) Apply(d *data) error {
|
| 12 | 12 |
dir, err := d.join("devices")
|
| 13 | 13 |
if err != nil {
|
| 14 |
+ // We will return error even it's `not found` error, devices |
|
| 15 |
+ // cgroup is hard requirement for container's security. |
|
| 14 | 16 |
return err |
| 15 | 17 |
} |
| 16 | 18 |
|
| ... | ... |
@@ -16,8 +16,7 @@ type MemoryGroup struct {
|
| 16 | 16 |
|
| 17 | 17 |
func (s *MemoryGroup) Apply(d *data) error {
|
| 18 | 18 |
dir, err := d.join("memory")
|
| 19 |
- // only return an error for memory if it was specified |
|
| 20 |
- if err != nil && (d.c.Memory != 0 || d.c.MemoryReservation != 0 || d.c.MemorySwap != 0) {
|
|
| 19 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 21 | 20 |
return err |
| 22 | 21 |
} |
| 23 | 22 |
defer func() {
|
| ... | ... |
@@ -256,6 +256,11 @@ func (m *Manager) GetPaths() map[string]string {
|
| 256 | 256 |
} |
| 257 | 257 |
|
| 258 | 258 |
func writeFile(dir, file, data string) error {
|
| 259 |
+ // Normally dir should not be empty, one case is that cgroup subsystem |
|
| 260 |
+ // is not mounted, we will get empty dir, and we want it fail here. |
|
| 261 |
+ if dir == "" {
|
|
| 262 |
+ return fmt.Errorf("no such directory for %s.", file)
|
|
| 263 |
+ } |
|
| 259 | 264 |
return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) |
| 260 | 265 |
} |
| 261 | 266 |
|
| ... | ... |
@@ -276,16 +281,16 @@ func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
|
| 276 | 276 |
|
| 277 | 277 |
func joinCpu(c *configs.Cgroup, pid int) error {
|
| 278 | 278 |
path, err := getSubsystemPath(c, "cpu") |
| 279 |
- if err != nil {
|
|
| 279 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 280 | 280 |
return err |
| 281 | 281 |
} |
| 282 | 282 |
if c.CpuQuota != 0 {
|
| 283 |
- if err = ioutil.WriteFile(filepath.Join(path, "cpu.cfs_quota_us"), []byte(strconv.FormatInt(c.CpuQuota, 10)), 0700); err != nil {
|
|
| 283 |
+ if err = writeFile(path, "cpu.cfs_quota_us", strconv.FormatInt(c.CpuQuota, 10)); err != nil {
|
|
| 284 | 284 |
return err |
| 285 | 285 |
} |
| 286 | 286 |
} |
| 287 | 287 |
if c.CpuPeriod != 0 {
|
| 288 |
- if err = ioutil.WriteFile(filepath.Join(path, "cpu.cfs_period_us"), []byte(strconv.FormatInt(c.CpuPeriod, 10)), 0700); err != nil {
|
|
| 288 |
+ if err = writeFile(path, "cpu.cfs_period_us", strconv.FormatInt(c.CpuPeriod, 10)); err != nil {
|
|
| 289 | 289 |
return err |
| 290 | 290 |
} |
| 291 | 291 |
} |
| ... | ... |
@@ -293,7 +298,7 @@ func joinCpu(c *configs.Cgroup, pid int) error {
|
| 293 | 293 |
} |
| 294 | 294 |
|
| 295 | 295 |
func joinFreezer(c *configs.Cgroup, pid int) error {
|
| 296 |
- if _, err := join(c, "freezer", pid); err != nil {
|
|
| 296 |
+ if _, err := join(c, "freezer", pid); err != nil && !cgroups.IsNotFound(err) {
|
|
| 297 | 297 |
return err |
| 298 | 298 |
} |
| 299 | 299 |
|
| ... | ... |
@@ -393,6 +398,8 @@ func getUnitName(c *configs.Cgroup) string {
|
| 393 | 393 |
// This happens at least for v208 when any sibling unit is started. |
| 394 | 394 |
func joinDevices(c *configs.Cgroup, pid int) error {
|
| 395 | 395 |
path, err := join(c, "devices", pid) |
| 396 |
+ // Even if it's `not found` error, we'll return err because devices cgroup |
|
| 397 |
+ // is hard requirement for container security. |
|
| 396 | 398 |
if err != nil {
|
| 397 | 399 |
return err |
| 398 | 400 |
} |
| ... | ... |
@@ -410,11 +417,11 @@ func joinMemory(c *configs.Cgroup, pid int) error {
|
| 410 | 410 |
} |
| 411 | 411 |
|
| 412 | 412 |
path, err := getSubsystemPath(c, "memory") |
| 413 |
- if err != nil {
|
|
| 413 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 414 | 414 |
return err |
| 415 | 415 |
} |
| 416 | 416 |
|
| 417 |
- return ioutil.WriteFile(filepath.Join(path, "memory.memsw.limit_in_bytes"), []byte(strconv.FormatInt(memorySwap, 10)), 0700) |
|
| 417 |
+ return writeFile(path, "memory.memsw.limit_in_bytes", strconv.FormatInt(memorySwap, 10)) |
|
| 418 | 418 |
} |
| 419 | 419 |
|
| 420 | 420 |
// systemd does not atm set up the cpuset controller, so we must manually |
| ... | ... |
@@ -422,7 +429,7 @@ func joinMemory(c *configs.Cgroup, pid int) error {
|
| 422 | 422 |
// level must have a full setup as the default for a new directory is "no cpus" |
| 423 | 423 |
func joinCpuset(c *configs.Cgroup, pid int) error {
|
| 424 | 424 |
path, err := getSubsystemPath(c, "cpuset") |
| 425 |
- if err != nil {
|
|
| 425 |
+ if err != nil && !cgroups.IsNotFound(err) {
|
|
| 426 | 426 |
return err |
| 427 | 427 |
} |
| 428 | 428 |
|
| ... | ... |
@@ -215,7 +215,6 @@ func checkMountDestination(rootfs, dest string) error {
|
| 215 | 215 |
} |
| 216 | 216 |
invalidDestinations := []string{
|
| 217 | 217 |
"/proc", |
| 218 |
- "/sys", |
|
| 219 | 218 |
} |
| 220 | 219 |
for _, invalid := range invalidDestinations {
|
| 221 | 220 |
path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest) |
| ... | ... |
@@ -15,8 +15,8 @@ func TestCheckMountDestOnProc(t *testing.T) {
|
| 15 | 15 |
func TestCheckMountDestInSys(t *testing.T) {
|
| 16 | 16 |
dest := "/rootfs//sys/fs/cgroup" |
| 17 | 17 |
err := checkMountDestination("/rootfs", dest)
|
| 18 |
- if err == nil {
|
|
| 19 |
- t.Fatal("destination inside proc should return an error")
|
|
| 18 |
+ if err != nil {
|
|
| 19 |
+ t.Fatal("destination inside /sys should not return an error")
|
|
| 20 | 20 |
} |
| 21 | 21 |
} |
| 22 | 22 |
|
| ... | ... |
@@ -44,6 +44,6 @@ clone git github.com/codegangsta/cli 1.1.0 |
| 44 | 44 |
clone git github.com/coreos/go-systemd v2 |
| 45 | 45 |
clone git github.com/godbus/dbus v2 |
| 46 | 46 |
clone git github.com/Sirupsen/logrus v0.7.3 |
| 47 |
-clone git github.com/syndtr/gocapability 8e4cdcb |
|
| 47 |
+clone git github.com/syndtr/gocapability 66ef2aa |
|
| 48 | 48 |
|
| 49 | 49 |
# intentionally not vendoring Docker itself... that'd be a circle :) |