diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index a8eb4bf9273..d5f00dd33e9 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -293,6 +293,11 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att exitSignal: uint64(SIGCHLD), cgroup: uint64(sys.CgroupFD), } + } else if flags&CLONE_NEWTIME != 0 { + clone3 = &cloneArgs{ + flags: uint64(flags), + exitSignal: uint64(SIGCHLD), + } } // About to call fork. diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index e0aa3fe996d..06b9495be20 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -487,6 +487,52 @@ func TestUseCgroupFDHelper(*testing.T) { fmt.Print(string(selfCg)) } +func TestCloneTimeNamespace(t *testing.T) { + testenv.MustHaveExec(t) + + if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { + timens, err := os.Readlink("/proc/self/ns/time") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + fmt.Print(string(timens)) + os.Exit(0) + } + + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + + cmd := testenv.Command(t, exe, "-test.run=TestCloneTimeNamespace") + cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1") + cmd.SysProcAttr = &syscall.SysProcAttr{ + Cloneflags: syscall.CLONE_NEWTIME, + } + out, err := cmd.CombinedOutput() + if err != nil { + if isNotSupported(err) { + // CLONE_NEWTIME does not appear to be supported. + t.Skipf("skipping, CLONE_NEWTIME not supported: %v", err) + } + t.Fatalf("Cmd failed with err %v, output: %s", err, out) + } + + // Inode numer of the time namespaces should be different. + // Based on https://man7.org/linux/man-pages/man7/time_namespaces.7.html#EXAMPLES + timens, err := os.Readlink("/proc/self/ns/time") + if err != nil { + t.Fatal(err) + } + + parentTimeNS := string(timens) + childTimeNS := string(out) + if childTimeNS == parentTimeNS { + t.Fatalf("expected child time namespace to be different from parent time namespace: %s", parentTimeNS) + } +} + type capHeader struct { version uint32 pid int32