浏览代码

nsinit.Init() restores parent death signal before exec

Docker-DCO-1.1-Signed-off-by: Bernerd Schaefer <bj.schaefer@gmail.com> (github: bernerdschaefer)
Bernerd Schaefer 11 年之前
父节点
当前提交
00e1adfead
共有 1 个文件被更改,包括 41 次插入0 次删除
  1. 41 0
      pkg/libcontainer/nsinit/init.go

+ 41 - 0
pkg/libcontainer/nsinit/init.go

@@ -85,12 +85,53 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string,
 			return err
 			return err
 		}
 		}
 	}
 	}
+
+	pdeathSignal, err := system.GetParentDeathSignal()
+	if err != nil {
+		return fmt.Errorf("get parent death signal %s", err)
+	}
+
 	if err := FinalizeNamespace(container); err != nil {
 	if err := FinalizeNamespace(container); err != nil {
 		return fmt.Errorf("finalize namespace %s", err)
 		return fmt.Errorf("finalize namespace %s", err)
 	}
 	}
+
+	// FinalizeNamespace can change user/group which clears the parent death
+	// signal, so we restore it here.
+	if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
+		return fmt.Errorf("restore parent death signal %s", err)
+	}
+
 	return system.Execv(args[0], args[0:], container.Env)
 	return system.Execv(args[0], args[0:], container.Env)
 }
 }
 
 
+// RestoreParentDeathSignal sets the parent death signal to old.
+func RestoreParentDeathSignal(old int) error {
+	if old == 0 {
+		return nil
+	}
+
+	current, err := system.GetParentDeathSignal()
+	if err != nil {
+		return fmt.Errorf("get parent death signal %s", err)
+	}
+
+	if old == current {
+		return nil
+	}
+
+	if err := system.ParentDeathSignal(uintptr(old)); err != nil {
+		return fmt.Errorf("set parent death signal %s", err)
+	}
+
+	// Signal self if parent is already dead. Does nothing if running in a new
+	// PID namespace, as Getppid will always return 0.
+	if syscall.Getppid() == 1 {
+		return syscall.Kill(syscall.Getpid(), syscall.Signal(old))
+	}
+
+	return nil
+}
+
 // SetupUser changes the groups, gid, and uid for the user inside the container
 // SetupUser changes the groups, gid, and uid for the user inside the container
 func SetupUser(u string) error {
 func SetupUser(u string) error {
 	uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid())
 	uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid())