func spawn(cmd *exec.Cmd, _ *garden.TTYSpec, stdout io.Writer, stderr io.Writer) (process, io.WriteCloser, error) { ro, wo, err := os.Pipe() if err != nil { return nil, nil, fmt.Errorf("pipe failed: %s", err) } re, we, err := os.Pipe() if err != nil { return nil, nil, fmt.Errorf("pipe failed: %s", err) } ri, wi, err := os.Pipe() if err != nil { return nil, nil, fmt.Errorf("pipe failed: %s", err) } go io.Copy(stdout, ro) go io.Copy(stderr, re) attr := &syscall.ProcAttr{ Dir: cmd.Dir, Env: cmd.Env, Files: []uintptr{ri.Fd(), wo.Fd(), we.Fd()}, } lookedUpPath, err := lookExtensions(cmd.Path, cmd.Dir) if err != nil { return nil, nil, fmt.Errorf("look extensions failed: %s", err) } // Acquire the fork lock so that no other threads // create new fds that are not yet close-on-exec // before we fork. syscall.ForkLock.Lock() defer syscall.ForkLock.Unlock() p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(attr.Files)) for i := range attr.Files { if attr.Files[i] > 0 { err := syscall.DuplicateHandle(p, syscall.Handle(attr.Files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, nil, fmt.Errorf("duplicating handle failed: %s", err) } defer syscall.CloseHandle(syscall.Handle(fd[i])) } } si := new(syscall.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES si.StdInput = fd[0] si.StdOutput = fd[1] si.StdErr = fd[2] pi := new(syscall.ProcessInformation) flags := uint32(syscall.CREATE_UNICODE_ENVIRONMENT) flags |= win32.CREATE_SUSPENDED flags |= win32.CREATE_BREAKAWAY_FROM_JOB argvp0, err := syscall.UTF16PtrFromString(lookedUpPath) if err != nil { return nil, nil, fmt.Errorf("stringing failed: %s", err) } argvp0v0v0v0, err := syscall.UTF16PtrFromString(makeCmdLine(cmd.Args)) if err != nil { return nil, nil, fmt.Errorf("stringing failed: %s", err) } dirp, err := syscall.UTF16PtrFromString(attr.Dir) if err != nil { return nil, nil, fmt.Errorf("stringing failed: %s", err) } err = syscall.CreateProcess( argvp0, argvp0v0v0v0, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi, ) if err != nil { return nil, nil, fmt.Errorf("create process: %s", err) } ri.Close() wo.Close() we.Close() jobName, err := syscall.UTF16PtrFromString(fmt.Sprintf("%d", time.Now().UnixNano())) if err != nil { return nil, nil, fmt.Errorf("stringing failed: %s", err) } jobHandle, err := win32.CreateJobObject(nil, jobName) if err != nil { return nil, nil, fmt.Errorf("create job failed: %s", err) } err = win32.AssignProcessToJobObject(jobHandle, pi.Process) if err != nil { return nil, nil, fmt.Errorf("assign failed: %s", err) } _, err = win32.ResumeThread(pi.Thread) if err != nil { return nil, nil, fmt.Errorf("resume failed: %s", err) } return &jobProcess{ jobHandle: jobHandle, processHandle: pi.Process, }, wi, nil }
func trackCPUUsage() { handle, err := syscall.GetCurrentProcess() if err != nil { l.Warnln("Cannot track CPU usage:", err) return } var ctime, etime, ktime, utime syscall.Filetime err = syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime) if err != nil { l.Warnln("Cannot track CPU usage:", err) return } prevTime := ctime.Nanoseconds() prevUsage := ktime.Nanoseconds() + utime.Nanoseconds() // Always overflows for _ = range time.NewTicker(time.Second).C { err := syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime) if err != nil { continue } curTime := time.Now().UnixNano() timeDiff := curTime - prevTime curUsage := ktime.Nanoseconds() + utime.Nanoseconds() usageDiff := curUsage - prevUsage cpuUsageLock.Lock() copy(cpuUsagePercent[1:], cpuUsagePercent[0:]) cpuUsagePercent[0] = 100 * float64(usageDiff) / float64(timeDiff) cpuUsageLock.Unlock() prevTime = curTime prevUsage = curUsage } }
func init() { var err error currentProcess, err = syscall.GetCurrentProcess() if err != nil { log.Fatalf("GetCurrentProcess failed: %v", err) } }
func (c *PipeConn) File() (*os.File, error) { var s syscall.Handle p, _ := syscall.GetCurrentProcess() err := syscall.DuplicateHandle(p, c.handle, p, &s, 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, err } return os.NewFile(uintptr(s), c.addr.String()), nil }
func setProcessAffinity(v int) { h, err := syscall.GetCurrentProcess() if err != nil { log.Printf("GetCurrentProcess failed: %v", err) return } if err := setProcessAffinityMask(h, uintptr(v)); err != nil { log.Printf("SetProcessAffinityMask failed: %v", err) return } }
func TestGetProcessHandleCount(t *testing.T) { h, err := syscall.GetCurrentProcess() if err != nil { t.Fatal(err) } var count uint32 err = winapi.GetProcessHandleCount(h, &count) if err != nil { t.Fatal(err) } t.Logf("Handle count is %v", count) }
func fdCount() (count int, err error) { h, err := syscall.GetCurrentProcess() if err != nil { return 0, err } var proccount uint32 r1, _, err := getProcCount.Call( uintptr(h), uintptr(unsafe.Pointer(&proccount))) if r1 == 0 { return 0, err } return int(proccount), nil }
// openFileCnt returns the number of open files in this process func openFileCnt() int { cp, err := syscall.GetCurrentProcess() if err != nil { log.Println("getcurrentProcess: %v\n", err) } var c uint32 r, _, err := getProcessHandleCount.Call(uintptr(cp), uintptr(unsafe.Pointer(&c))) if r == 0 { log.Println(err) } return int(c) }
func fdCount() (count int, err error) { h, err := syscall.GetCurrentProcess() if err != nil { return 0, err } var procCount uint32 r1, _, err := getProcessHandleCount.Call( uintptr(h), uintptr(unsafe.Pointer(&procCount))) if r1 == 0 { // if r1 == 0, then GetProcessHandleCount failed and err will be set to // the formatted string for whatever GetLastError() returns. return 0, err } return int(procCount), nil }
// enableSeDebugPrivilege enables the SeDebugPrivilege if it is present in // the process's token. func enableSeDebugPrivilege() error { self, err := syscall.GetCurrentProcess() if err != nil { return err } var token syscall.Token err = syscall.OpenProcessToken(self, syscall.TOKEN_QUERY|syscall.TOKEN_ADJUST_PRIVILEGES, &token) if err != nil { return err } if err = windows.EnableTokenPrivileges(token, windows.SeDebugPrivilege); err != nil { return errors.Wrap(err, "EnableTokenPrivileges failed") } return nil }
func startInstance(cmd *exec.Cmd, r *os.File, w *os.File) error { var rHandle syscall.Handle var wHandle syscall.Handle p, _ := syscall.GetCurrentProcess() if err := syscall.DuplicateHandle(p, syscall.Handle(r.Fd()), p, &rHandle, 0, true, syscall.DUPLICATE_SAME_ACCESS); err != nil { return err } defer syscall.CloseHandle(rHandle) if err := syscall.DuplicateHandle(p, syscall.Handle(w.Fd()), p, &wHandle, 0, true, syscall.DUPLICATE_SAME_ACCESS); err != nil { return err } defer syscall.CloseHandle(wHandle) if cmd.Env == nil { cmd.Env = os.Environ() } cmd.Env = append(cmd.Env, fmt.Sprintf("ZSHANDLE_IN=%d", rHandle), fmt.Sprintf("ZSHANDLE_OUT=%d", wHandle)) return cmd.Start() }
// GetUsage gathers process times. func GetUsage() (Usage, error) { var creationTime syscall.Filetime var exitTime syscall.Filetime var kernelTime syscall.Filetime var userTime syscall.Filetime handle, err := syscall.GetCurrentProcess() if err != nil { return Usage{}, err } err = syscall.GetProcessTimes(handle, &creationTime, &exitTime, &kernelTime, &userTime) if err != nil { return Usage{}, err } return Usage{ System: filetimeToDuration(&kernelTime), User: filetimeToDuration(&userTime), }, nil }
func numHandles(t *testing.T) int { handleCounter.once.Do(func() { d, err := syscall.LoadDLL("kernel32.dll") if err != nil { t.Fatalf("LoadDLL: %v\n", err) } handleCounter.proc, err = d.FindProc("GetProcessHandleCount") if err != nil { t.Fatalf("FindProc: %v\n", err) } }) cp, err := syscall.GetCurrentProcess() if err != nil { t.Fatalf("GetCurrentProcess: %v\n", err) } var n uint32 r, _, err := handleCounter.proc.Call(uintptr(cp), uintptr(unsafe.Pointer(&n))) if r == 0 { t.Fatalf("GetProcessHandleCount: %v\n", error(err)) } return int(n) }
func GetCurrentProcess() (pseudoHandle HANDLE, err error) { _handle, err := syscall.GetCurrentProcess() pseudoHandle = HANDLE(_handle) return }
func startProcessAsUser( argv0 string, argv []string, username string, domain string, password string, attr *syscall.ProcAttr, ) (pid int, handle uintptr, err error) { if len(argv0) == 0 { return 0, 0, syscall.EWINDOWS } if attr == nil { attr = &zeroProcAttr } sys := attr.Sys if sys == nil { sys = &zeroSysProcAttr } if len(attr.Files) > 3 { return 0, 0, syscall.EWINDOWS } if len(attr.Files) < 3 { return 0, 0, syscall.EINVAL } if len(attr.Dir) != 0 { // StartProcess assumes that argv0 is relative to attr.Dir, // because it implies Chdir(attr.Dir) before executing argv0. // Windows CreateProcess assumes the opposite: it looks for // argv0 relative to the current directory, and, only once the new // process is started, it does Chdir(attr.Dir). We are adjusting // for that difference here by making argv0 absolute. var err error argv0, err = joinExeDirAndFName(attr.Dir, argv0) if err != nil { return 0, 0, err } } argv0p, err := syscall.UTF16PtrFromString(argv0) if err != nil { return 0, 0, err } var cmdline string // Windows CreateProcess takes the command line as a single string: // use attr.CmdLine if set, else build the command line by escaping // and joining each argument with spaces if sys.CmdLine != "" { cmdline = sys.CmdLine } else { cmdline = makeCmdLine(argv) } var argvp *uint16 if len(cmdline) != 0 { argvp, err = syscall.UTF16PtrFromString(cmdline) if err != nil { return 0, 0, err } } // Acquire the fork lock so that no other threads // create new fds that are not yet close-on-exec // before we fork. syscall.ForkLock.Lock() defer syscall.ForkLock.Unlock() p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(attr.Files)) for i := range attr.Files { if attr.Files[i] > 0 { err = syscall.DuplicateHandle(p, syscall.Handle(attr.Files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return 0, 0, errors.New("DuplicateHandle: " + err.Error()) } defer syscall.CloseHandle(syscall.Handle(fd[i])) } } si := new(syscall.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES if sys.HideWindow { si.Flags |= syscall.STARTF_USESHOWWINDOW si.ShowWindow = syscall.SW_HIDE } si.StdInput = fd[0] si.StdOutput = fd[1] si.StdErr = fd[2] token, err := logonUser(username, domain, password, logon32LogonInteractive, logon32ProviderDefault) if err != nil { return 0, 0, errors.New("logonUser: "******"createEnvironmentBlock: " + err.Error()) } env = &e[0] } else { env = createEnvBlock(attr.Env) } err = impersonateLoggedOnUser(token) if err != nil { return 0, 0, errors.New("impersonateLoggedOnUser: "******"createProcessAsUser: " + err.Error()) } defer syscall.CloseHandle(syscall.Handle(pi.Thread)) return int(pi.ProcessId), uintptr(pi.Process), nil }
// Launch creates and begins debugging a new process. func Launch(cmd []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists. if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } if _, err := os.Stat(argv0Go); err != nil { return nil, err } // Duplicate the stdin/stdout/stderr handles files := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)} p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(files)) for i := range files { err := syscall.DuplicateHandle(p, syscall.Handle(files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, err } defer syscall.CloseHandle(syscall.Handle(fd[i])) } argv0, err := syscall.UTF16PtrFromString(argv0Go) if err != nil { return nil, err } // create suitable command line for CreateProcess // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L326 // adapted from standard library makeCmdLine // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L86 var cmdLineGo string if len(cmd) >= 1 { for _, v := range cmd { if cmdLineGo != "" { cmdLineGo += " " } cmdLineGo += syscall.EscapeArg(v) } } var cmdLine *uint16 if cmdLineGo != "" { if cmdLine, err = syscall.UTF16PtrFromString(cmdLineGo); err != nil { return nil, err } } // Initialize the startup info and create process si := new(sys.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES si.StdInput = sys.Handle(fd[0]) si.StdOutput = sys.Handle(fd[1]) si.StdErr = sys.Handle(fd[2]) pi := new(sys.ProcessInformation) err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, DEBUGONLYTHISPROCESS, nil, nil, si, pi) if err != nil { return nil, err } sys.CloseHandle(sys.Handle(pi.Process)) sys.CloseHandle(sys.Handle(pi.Thread)) dbp := New(int(pi.ProcessId)) switch runtime.GOARCH { case "amd64": dbp.arch = AMD64Arch() } // Note - it should not actually be possible for the // call to waitForDebugEvent to fail, since Windows // will always fire a CreateProcess event immediately // after launching under DEBUGONLYTHISPROCESS. var tid, exitCode int dbp.execPtraceFunc(func() { tid, exitCode, err = dbp.waitForDebugEvent() }) if err != nil { return nil, err } if tid == 0 { dbp.postExit() return nil, ProcessExitedError{Pid: dbp.Pid, Status: exitCode} } return initializeDebugProcess(dbp, argv0Go, false) }
// Launch creates and begins debugging a new process. func Launch(cmd []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists and is an executable file if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } peFile, err := openExecutablePath(argv0Go) if err != nil { return nil, NotExecutableErr } peFile.Close() // Duplicate the stdin/stdout/stderr handles files := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)} p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(files)) for i := range files { err := syscall.DuplicateHandle(p, syscall.Handle(files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, err } defer syscall.CloseHandle(syscall.Handle(fd[i])) } argv0, err := syscall.UTF16PtrFromString(argv0Go) if err != nil { return nil, err } // create suitable command line for CreateProcess // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L326 // adapted from standard library makeCmdLine // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L86 var cmdLineGo string if len(cmd) >= 1 { for _, v := range cmd { if cmdLineGo != "" { cmdLineGo += " " } cmdLineGo += syscall.EscapeArg(v) } } var cmdLine *uint16 if cmdLineGo != "" { if cmdLine, err = syscall.UTF16PtrFromString(cmdLineGo); err != nil { return nil, err } } // Initialize the startup info and create process si := new(sys.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES si.StdInput = sys.Handle(fd[0]) si.StdOutput = sys.Handle(fd[1]) si.StdErr = sys.Handle(fd[2]) pi := new(sys.ProcessInformation) err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, _DEBUG_ONLY_THIS_PROCESS, nil, nil, si, pi) if err != nil { return nil, err } sys.CloseHandle(sys.Handle(pi.Process)) sys.CloseHandle(sys.Handle(pi.Thread)) return newDebugProcess(int(pi.ProcessId), argv0Go) }