Add PDEATHSIG support to nsinit library
| ... | ... |
@@ -123,6 +123,7 @@ func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, da |
| 123 | 123 |
command.Env = append(os.Environ(), env...) |
| 124 | 124 |
|
| 125 | 125 |
system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces))) |
| 126 |
+ command.SysProcAttr.Pdeathsig = syscall.SIGKILL |
|
| 126 | 127 |
command.ExtraFiles = []*os.File{pipe}
|
| 127 | 128 |
|
| 128 | 129 |
return command |
| ... | ... |
@@ -85,12 +85,53 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, |
| 85 | 85 |
return err |
| 86 | 86 |
} |
| 87 | 87 |
} |
| 88 |
+ |
|
| 89 |
+ pdeathSignal, err := system.GetParentDeathSignal() |
|
| 90 |
+ if err != nil {
|
|
| 91 |
+ return fmt.Errorf("get parent death signal %s", err)
|
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 88 | 94 |
if err := FinalizeNamespace(container); err != nil {
|
| 89 | 95 |
return fmt.Errorf("finalize namespace %s", err)
|
| 90 | 96 |
} |
| 97 |
+ |
|
| 98 |
+ // FinalizeNamespace can change user/group which clears the parent death |
|
| 99 |
+ // signal, so we restore it here. |
|
| 100 |
+ if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
|
|
| 101 |
+ return fmt.Errorf("restore parent death signal %s", err)
|
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 91 | 104 |
return system.Execv(args[0], args[0:], container.Env) |
| 92 | 105 |
} |
| 93 | 106 |
|
| 107 |
+// RestoreParentDeathSignal sets the parent death signal to old. |
|
| 108 |
+func RestoreParentDeathSignal(old int) error {
|
|
| 109 |
+ if old == 0 {
|
|
| 110 |
+ return nil |
|
| 111 |
+ } |
|
| 112 |
+ |
|
| 113 |
+ current, err := system.GetParentDeathSignal() |
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ return fmt.Errorf("get parent death signal %s", err)
|
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ if old == current {
|
|
| 119 |
+ return nil |
|
| 120 |
+ } |
|
| 121 |
+ |
|
| 122 |
+ if err := system.ParentDeathSignal(uintptr(old)); err != nil {
|
|
| 123 |
+ return fmt.Errorf("set parent death signal %s", err)
|
|
| 124 |
+ } |
|
| 125 |
+ |
|
| 126 |
+ // Signal self if parent is already dead. Does nothing if running in a new |
|
| 127 |
+ // PID namespace, as Getppid will always return 0. |
|
| 128 |
+ if syscall.Getppid() == 1 {
|
|
| 129 |
+ return syscall.Kill(syscall.Getpid(), syscall.Signal(old)) |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ return nil |
|
| 133 |
+} |
|
| 134 |
+ |
|
| 94 | 135 |
// SetupUser changes the groups, gid, and uid for the user inside the container |
| 95 | 136 |
func SetupUser(u string) error {
|
| 96 | 137 |
uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid()) |
| ... | ... |
@@ -3,6 +3,7 @@ package system |
| 3 | 3 |
import ( |
| 4 | 4 |
"os/exec" |
| 5 | 5 |
"syscall" |
| 6 |
+ "unsafe" |
|
| 6 | 7 |
) |
| 7 | 8 |
|
| 8 | 9 |
func Chroot(dir string) error {
|
| ... | ... |
@@ -122,6 +123,18 @@ func ParentDeathSignal(sig uintptr) error {
|
| 122 | 122 |
return nil |
| 123 | 123 |
} |
| 124 | 124 |
|
| 125 |
+func GetParentDeathSignal() (int, error) {
|
|
| 126 |
+ var sig int |
|
| 127 |
+ |
|
| 128 |
+ _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0) |
|
| 129 |
+ |
|
| 130 |
+ if err != 0 {
|
|
| 131 |
+ return -1, err |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ return sig, nil |
|
| 135 |
+} |
|
| 136 |
+ |
|
| 125 | 137 |
func Setctty() error {
|
| 126 | 138 |
if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
|
| 127 | 139 |
return err |