瀏覽代碼

Merge pull request #5792 from bernerdschaefer/nsinit-supports-pdeathsig

Add PDEATHSIG support to nsinit library
Victor Marmol 11 年之前
父節點
當前提交
cb7680b9b9
共有 3 個文件被更改,包括 55 次插入0 次删除
  1. 1 0
      pkg/libcontainer/nsinit/exec.go
  2. 41 0
      pkg/libcontainer/nsinit/init.go
  3. 13 0
      pkg/system/calls_linux.go

+ 1 - 0
pkg/libcontainer/nsinit/exec.go

@@ -123,6 +123,7 @@ func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, da
 	command.Env = append(os.Environ(), env...)
 	command.Env = append(os.Environ(), env...)
 
 
 	system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces)))
 	system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces)))
+	command.SysProcAttr.Pdeathsig = syscall.SIGKILL
 	command.ExtraFiles = []*os.File{pipe}
 	command.ExtraFiles = []*os.File{pipe}
 
 
 	return command
 	return command

+ 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())

+ 13 - 0
pkg/system/calls_linux.go

@@ -3,6 +3,7 @@ package system
 import (
 import (
 	"os/exec"
 	"os/exec"
 	"syscall"
 	"syscall"
+	"unsafe"
 )
 )
 
 
 func Chroot(dir string) error {
 func Chroot(dir string) error {
@@ -122,6 +123,18 @@ func ParentDeathSignal(sig uintptr) error {
 	return nil
 	return nil
 }
 }
 
 
+func GetParentDeathSignal() (int, error) {
+	var sig int
+
+	_, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0)
+
+	if err != 0 {
+		return -1, err
+	}
+
+	return sig, nil
+}
+
 func Setctty() error {
 func Setctty() error {
 	if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
 	if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
 		return err
 		return err