Example #1
0
func (c *CloneParams) Unfreeze(pid int) error {
	err := syscall.PtraceDetach(pid)
	co, ok := <-c.comm
	if !ok {
		return os.NewSyscallError("PtraceDetach", err)
	}
	return childError(co)
}
Example #2
0
func (t *PTracer) detachThread(thread *thread) {
	syscall.PtraceDetach(thread.tid)
	process := thread.process
	delete(process.threads, thread.tid)
	delete(t.threads, thread.tid)
	if len(process.threads) == 0 {
		delete(t.processes, process.pid)
		close(process.detached)
		log.Printf("Process %d detached", process.pid)
	}
}
Example #3
0
func main() {
	tpid := flag.Int("pid", 0, "the pid you want to f**k with")
	tname := flag.String("rename", "", "the name you want it to be called")
	flag.Parse()

	if *tpid == 0 || *tname == "" {
		flag.Usage() // RTFM
		os.Exit(1)
	}

	StackLocation := FindStack(*tpid)

	if StackLocation == "" {
		log.Fatal("Unable to find stack. this shouldnt happen.")
	}

	log.Printf("Found stack at %s", StackLocation)

	cmdline := GetCmdLine(*tpid)
	offset := GetRamOffset(*tpid, StackLocation, cmdline)

	data := []byte(fmt.Sprint(*tname))
	data = append(data, 0x00)

	eh, _ := os.FindProcess(*tpid)

	err := syscall.PtraceAttach(eh.Pid)

	if err != nil {
		log.Fatalf("Could not attach to the PID. Why? %s", err)
	}

	_, err = syscall.PtracePokeData(eh.Pid, uintptr(offset), data)

	if err != nil {
		log.Fatalf("now I've f****d up! %s is the error", err)
	}

	// fmt.Printf("No idea what it means, but here is 'c' : %d", c)

	err = syscall.PtraceDetach(eh.Pid)

	if err != nil {
		log.Fatalf("Unable to detach?? Why? %s", err)
	}

	err = syscall.Kill(eh.Pid, syscall.SIGCONT)

	if err != nil {
		log.Fatalf("Unable to detach?? Why? %s", err)
	}

}
func RenamePid(tpid int, tname string) {
	log.Printf("Attempting to rename pid %d to %s", tpid, tname)
	StackLocation := FindStack(tpid)

	if StackLocation == "" {
		log.Printf("Unable to find stack. this shouldnt happen.")
		return
	}

	cmdline := GetCmdLine(tpid)
	offset := GetRamOffset(tpid, StackLocation, cmdline)

	data := []byte(fmt.Sprint(tname))
	data = append(data, 0x00)

	eh, _ := os.FindProcess(tpid)

	err := syscall.PtraceAttach(eh.Pid)

	if err != nil {
		log.Printf("Could not attach to the PID. Why? %s", err)
		return
	}

	_, err = syscall.PtracePokeData(eh.Pid, uintptr(offset), data)

	if err != nil {
		log.Printf("now I've f****d up! %s is the error", err)
		return
	}

	// fmt.Printf("No idea what it means, but here is 'c' : %d", c)

	err = syscall.PtraceDetach(eh.Pid)

	if err != nil {
		log.Printf("Unable to detach?? Why? %s", err)
		return
	}

	err = syscall.Kill(eh.Pid, syscall.SIGCONT)

	if err != nil {
		log.Printf("Unable to detach?? Why? %s", err)
		return
	}
}
Example #5
0
func (t *Task) Tracer() error {
	runtime.LockOSThread()

	if err := syscall.PtraceAttach(t.pid); err != nil {
		return err
	}
	defer func() {
		// syscall.PtraceCont(t.pid, 0)
		syscall.PtraceDetach(t.pid)
	}()

	regsout := new(syscall.PtraceRegs)
	status := new(syscall.WaitStatus)
	var timer *time.Timer
	refresh := func() { t.RefreshFiles(); timer.Stop(); timer = nil }
	for {
		if _, err := syscall.Wait4(t.pid, status, 0, nil); err != nil {
			log.Println("wait failed", err)
			return err
		}
		if status.Exited() {
			log.Println("exited")
			return nil
		}

		if err := syscall.PtraceGetRegs(t.pid, regsout); err != nil {
			log.Println("getregs failed", err)
			return err
		}

		// linux_amd64
		if regsout.Orig_rax == syscall.SYS_OPEN {
			if timer != nil {
				if timer.Stop() == false {
					log.Println("cannot stop the timer")
				}
			}
			timer = time.AfterFunc(1e9, refresh) // Wait until open()s "settle".
		}

		if err := PtraceSyscall(t.pid); err != nil {
			log.Println("PtraceSyscall failed", err)
			return err
		}
	}
	panic("can't reach")
}
Example #6
0
func TestGoshDoesNotReportSigStopOrContinueAsExitEvenUnderPtrace(t *testing.T) {
	assert := assrt.NewAssert(t)

	cmdr := NewRunningCommand(
		exec.Command("bash", "-c", "sleep 1; exit 4;"),
	)
	cmdr.Start()

	// Ride the wild wind
	if err := syscall.PtraceAttach(cmdr.Pid()); err != nil {
		panic(err)
	}

	NewRunningCommand(exec.Command("kill", "-SIGSTOP", Itoa(cmdr.Pid()))).Start().Wait()

	assert.Equal(
		false,
		cmdr.WaitSoon(1500*time.Millisecond),
	)

	NewRunningCommand(exec.Command("kill", "-SIGCONT", Itoa(cmdr.Pid()))).Start().Wait()

	// Must detach ptrace again for the wait to return.
	if err := syscall.PtraceDetach(cmdr.Pid()); err != nil {
		// This boggles my mind.  You can pause before and after this, and that pid most certainly does exist, but here we occationally get errors nonetheless.
		// Have to skip, because we are attached, that process does exist, and if we can't detach, waiting for exit is going to hang forever.
		t.Skipf("error detaching ptrace: %+v -- pid=%v\n", err, cmdr.Pid())
	}

	assert.Equal(
		4,
		cmdr.GetExitCode(),
	)
	assert.Equal(
		nil,
		cmdr.err,
	)
	assert.Equal(
		FINISHED,
		cmdr.State(),
	)
}
func (t *thread) ptraceDetach() os.Error {
	err := syscall.PtraceDetach(t.tid)
	return os.NewSyscallError("ptrace(DETACH)", err)
}
Example #8
0
func main() {
	flag.Parse()

	if len(flag.Args()) < 1 {
		os.Exit(1)
	}

	// note the unshare system call worketh not for Go.
	// So do it ourselves. We have to start ourselves up again,
	// after having spawned ourselves with lots of clone
	// flags sets. To know that we spawned ourselves we add '#'
	// as the last arg. # was chosen because shells normally filter
	// it out, so its presence as our last arg is highly indicative
	// that we really spawned us. Also, for testing, you can always
	// pass it by hand to see what the namespace looks like.
	a := os.Args
	if a[len(a)-1][0] != '#' {
		a = append(a, "#")
		if syscall.Geteuid() != 0 {
			a[len(a)-1] = "#u"
		}
		// spawn ourselves with the right unsharing settings.
		c := exec.Command(a[0], a[1:]...)
		c.SysProcAttr = &syscall.SysProcAttr{Cloneflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID}
		//		c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNET

		if syscall.Geteuid() != 0 {
			c.SysProcAttr.Cloneflags |= syscall.CLONE_NEWUSER
			// Interesting. Won't build statically?
			//c.SysProcAttr.UidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: syscall.Getuid(), Size: 1}}
			//c.SysProcAttr.GidMappings = []syscall.SysProcIDMap{{ContainerID: 0, HostID: syscall.Getgid(), Size: 1}}
		}

		c.Stdin = os.Stdin
		c.Stdout = os.Stdout
		c.Stderr = os.Stderr
		//t, err := getTermios(1)
		//if err != nil {
		//	log.Fatalf("Can't get termios on fd 1: %v", err)
		//}
		if err := c.Run(); err != nil {
			log.Printf(err.Error())
		}
		//if err := t.set(1); err != nil {
		//	log.Printf("Can't reset termios on fd1: %v", err)
		//}
		os.Exit(1)
	}

	unprivileged := a[len(a)-1] == "#u"

	// unlike pflask, we require that you set a chroot.
	// If you make it /, strange things are bound to happen.
	// if that is too limiting we'll have to change this.
	if *chroot == "" {
		log.Fatalf("you are required to set the chroot via --chroot")
	}

	a = flag.Args()
	//log.Printf("greetings %v\n", a)
	a = a[:len(a)-1]

	ptm, pts, sname, err := ptsopen()
	if err != nil {
		log.Fatalf(err.Error())
	}

	// child code. Not really. What really happens here is we set
	// ourselves into the container, and spawn the child. It's a bit odd
	// but we're the master, but we'll run in the container? I don't know
	// how else to do it. This may require we set some things up first,
	// esp. the network. But, it's all fun and games until someone loses
	// an eye.
	MountAll(*chroot, unprivileged)

	if !unprivileged {
		copy_nodes(*chroot)
	}

	make_ptmx(*chroot)

	make_symlinks(*chroot)

	make_console(*chroot, sname, unprivileged)

	//umask(0022);

	/* TODO: drop capabilities */

	//do_user(user);

	e := make(map[string]string)
	if *keepenv {
		for _, v := range os.Environ() {
			k := strings.SplitN(v, "=", 2)
			e[k[0]] = k[1]
		}
	}

	term := os.Getenv("TERM")
	e["TERM"] = term
	e["PATH"] = "/usr/sbin:/usr/bin:/sbin:/bin"
	e["USER"] = *user
	e["LOGNAME"] = *user
	e["HOME"] = "/root"

	if *env != "" {
		for _, c := range strings.Split(*env, ",") {
			k := strings.SplitN(c, "=", 2)
			if len(k) != 2 {
				log.Printf("Bogus environment string %v", c)
				continue
			}
			e[k[0]] = k[1]
		}
	}
	e["container"] = "pflask"

	if *cgroup == "" {
		var envs []string
		for k, v := range e {
			envs = append(envs, k+"="+v)
		}
		if err := syscall.Chroot(*chroot); err != nil {
			log.Fatal(err)
		}
		if err := syscall.Chdir(*chdir); err != nil {
			log.Fatal(err)
		}
		log.Fatal(syscall.Exec(a[0], a[1:], envs))
	}

	c := exec.Command(a[0], a[1:]...)
	c.Env = nil
	for k, v := range e {
		c.Env = append(c.Env, k+"="+v)
	}

	c.SysProcAttr = &syscall.SysProcAttr{
		Chroot:  *chroot,
		Setctty: true,
		Setsid:  true,
	}
	c.Stdout = pts
	c.Stdin = pts
	c.Stderr = c.Stdout
	c.SysProcAttr.Setctty = true
	c.SysProcAttr.Setsid = true
	c.SysProcAttr.Ptrace = true
	c.Dir = *chdir
	err = c.Start()
	if err != nil {
		panic(err)
	}
	kid := c.Process.Pid
	log.Printf("Started %d\n", kid)

	// set up the containers, then resume the process.
	// Its children will get the containers as it clones.

	cg := cgroupname(*cgpath)
	cg.Do(*cgroup, kid)

	// sometimes the detach fails. Looks like a race condition: we're
	// sending the detach before the child has hit the TRACE_ME point.
	// Experimentally, when it fails, even one seconds it too short to
	// sleep. Sleep for 5 seconds.
	// Oh well it's not that. It's that there is some one of these
	// processes not in the PID namespace of the child? Who knows, sigh.
	// This is an aspect of the Go runtime that is seriously broken.

	for i := 0; ; i++ {
		if err = syscall.PtraceDetach(kid); err != nil {
			log.Printf("Could not detach %v, sleeping 250 milliseconds", kid)
			time.Sleep(250 * time.Millisecond)
			continue
		}
		if i > 100 {
			log.Fatalf("Tried for 10 seconds to get a DETACH. Let's fix the go runtime someday")
		}
		break
	}

	raw()

	go func() {
		io.Copy(os.Stdout, ptm)
		os.Exit(1)
	}()
	io.Copy(ptm, os.Stdin)
}
Example #9
0
func (t *Tracer) Detach() error {
	return syscall.PtraceDetach(t.Process.Pid)
}
Example #10
0
func main() {
	var wstat syscall.WaitStatus
	var complete func(syscall.PtraceRegs) = nil
	var die = false
	regs := syscall.PtraceRegs{}
	isSyscall := func(wstat syscall.WaitStatus) bool {
		return (((uint32(wstat) & 0xff00) >> 8) & 0x80) != 0
	}

	sc := initSyscalls()

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Kill, os.Interrupt)
	go check(c, &die)

	if pid == -1 {
		log.Fatal("No pid set")
	}

	err := syscall.PtraceAttach(pid)
	if err != nil {
		log.Print("attach")
		log.Print(err)
		goto fail
	}

	_, err = syscall.Wait4(pid, &wstat, 0, nil)
	if err != nil {
		log.Printf("wait %d err %s\n", pid, err)
		goto fail
	}
	err = syscall.PtraceSetOptions(pid, syscall.PTRACE_O_TRACESYSGOOD)
	if err != nil {
		log.Print("ptrace set options")
		log.Print(err)
		goto fail
	}

	for !die {
		err = syscall.PtraceSyscall(pid, 0)
		if err != nil {
			log.Print("syscall")
			log.Print(err)
			goto fail
		}

		_, err = syscall.Wait4(pid, &wstat, 0, nil)
		if err != nil {
			log.Printf("wait %d err %s\n", pid, err)
			goto fail
		}

		// ENTER
		if wstat.Stopped() {
			if isSyscall(wstat) {
				err = syscall.PtraceGetRegs(pid, &regs)
				if err != nil {
					log.Print("regs")
					log.Print(err)
					goto fail
				}
				complete = sc.Call(regs)
			}
		}
		err = syscall.PtraceSyscall(pid, 0)
		if err != nil {
			log.Print("syscall 2")
			log.Print(err)
			goto fail
		}

		_, err = syscall.Wait4(pid, &wstat, 0, nil)
		if err != nil {
			log.Printf("wait %d err %s\n", pid, err)
			goto fail
		}

		os.Stdout.Sync()
		if wstat.Stopped() {
			if isSyscall(wstat) {
				err = syscall.PtraceGetRegs(pid, &regs)
				if err != nil {
					log.Print("regs")
					log.Print(err)
					goto fail
				}
				//log.Printf("NUM: %d ::%#v", syscallNum, regs)
				if complete != nil {
					complete(regs)
					complete = nil
				}
			}
		}
	}

fail:
	syscall.Kill(pid, 18)
	err = syscall.PtraceDetach(pid)
	if err != nil {
		log.Print("detach")
		log.Print(err)
	}
}