Пример #1
0
func read_ptrace_events(args []string) (*exec.Cmd, func() *syscall.PtraceRegs) {

	cmd := exec.Command(args[0], args[1:]...)
	cmd.SysProcAttr = &syscall.SysProcAttr{Ptrace: true}
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Start()
	if err != nil {
		panic(err)
	}

	_, err = cmd.Process.Wait()
	if err != nil {
		panic(err)
	}

	child := cmd.Process.Pid

	err = syscall.PtraceSetOptions(child, syscall.PTRACE_O_TRACESYSGOOD)
	if err != nil {
		panic(err)
	}

	var regs syscall.PtraceRegs

	return cmd, func() *syscall.PtraceRegs {

		err = syscall.PtraceSyscall(child, 0)
		if err != nil {
			panic(err)
		}
		state, err := cmd.Process.Wait()
		if err != nil {
			panic(err)
		}
		waitstatus, ok := state.Sys().(syscall.WaitStatus)
		if !ok {
			panic(err)
		}
		if waitstatus.Exited() {
			// Process quit
			return nil
		}
		if !waitstatus.Stopped() {
			panic("Not handled: process isn't sigstopped!")
		}
		sig := waitstatus.StopSignal()
		if sig&0x80 == 0 {
			// Not something we're build to handle
			// High bit should be set for syscalls because of PTRACE_O_SYSGOOD
			return nil
		}
		err = syscall.PtraceGetRegs(child, &regs)
		if err != nil {
			panic(err)
		}
		return &regs
	}
}
Пример #2
0
func (t *PTracer) handleStopped(pid int, status syscall.WaitStatus) {
	signal := syscall.Signal(0)
	target, err := t.thread(pid)
	if err != nil {
		log.Printf("thread failed: %v", err)
		return
	}

	if !target.attached {
		target.attached = true

		err = syscall.PtraceSetOptions(pid, ptraceOptions)
		if err != nil {
			log.Printf("SetOptions failed, pid=%d, err=%v", pid, err)
			return
		}

	} else if status.Stopped() && status.StopSignal() == syscall.SIGTRAP|ptraceTracesysgoodBit {
		// pid entered Syscall-enter-stop or syscall-exit-stop
		target.syscallStopped()

	} else if status.Stopped() && status.StopSignal() == syscall.SIGTRAP {
		// pid entered PTRACE_EVENT stop
		switch status.TrapCause() {
		case syscall.PTRACE_EVENT_CLONE:
			err := target.handleClone(pid)
			if err != nil {
				log.Printf("clone failed: %v", err)
				return
			}
		default:
			log.Printf("Unknown PTRACE_EVENT %d for pid %d", status.TrapCause(), pid)
		}
	} else if status.Exited() || status.Signaled() {
		// "tracer can safely assume pid will exit"
		t.threadExited(target)
		return
	} else if status.Stopped() {
		// tracee received a non-trace related signal
		signal = status.StopSignal()

		if signal == syscall.SIGSTOP && target.process.detaching {
			t.detachThread(target)
			return
		}
	} else {
		// unknown stop - shouldn't happen!
		log.Printf("Pid %d random stop with status %x", pid, status)
	}

	// Restart stopped caller in syscall trap mode.
	// log.Printf("Restarting pid %d with signal %d", pid, int(signal))
	err = syscall.PtraceSyscall(pid, int(signal))
	if err != nil {
		log.Printf("PtraceSyscall failed, pid=%d, err=%v", pid, err)
	}
}
Пример #3
0
// traceSyscalls executes a command exec with the arguments args and calls
// the function callback for every syscall executed by the command's process.
func traceSyscalls(proc *os.Process, state func(pid int, regs *syscall.PtraceRegs)) {
	// flags used with ptrace
	const flags = syscall.PTRACE_O_TRACEVFORK |
		syscall.PTRACE_O_TRACEFORK |
		syscall.PTRACE_O_TRACECLONE |
		syscall.PTRACE_O_TRACEEXEC |
		syscall.PTRACE_O_TRACESYSGOOD

	if err := syscall.PtraceSetOptions(proc.Pid, flags); err != nil {
		log.Fatal("PtrageSetOptions", err)
	}
	if err := syscall.PtraceSyscall(proc.Pid, 0); err != nil {
		log.Fatalf("PtraceCont: %v", err)
	}
	for {
		signal := 0
		pid, status, err := wait(-1)
		if err != nil {
			break
		}
		if status.Exited() || status.Signaled() {
			continue
		}
		if status.Stopped() {
			switch waitEvent(status) {
			case EventFork, EventVFork, EventClone, EventExec:
				if cpid, err := syscall.PtraceGetEventMsg(pid); err == nil {
					log.Printf("process %d created new process %d", pid, cpid)
				}
			default:
				if stopSignal := status.StopSignal(); stopSignal&0x7f != syscall.SIGTRAP {
					signal = int(stopSignal)
				}
				var regs syscall.PtraceRegs
				if syscall.PtraceGetRegs(pid, &regs) == nil {
					state(pid, &regs)
				}
			}
		}
		syscall.PtraceSyscall(pid, signal)
	}
}
Пример #4
0
func waitSyscall(proc *os.Process) bool {
	for {
		syscall.PtraceSyscall(proc.Pid, 0)

		var status syscall.WaitStatus
		syscall.Wait4(proc.Pid, &status, 0, nil)
		if status.Stopped() {
			return false
		}
		if status.Exited() {
			return true
		}
	}
}
Пример #5
0
func (t *Tracer) Syscall(sig syscall.Signal) (uint64, error) {
	err := syscall.PtraceSyscall(t.Process.Pid, int(sig))
	if err != nil {
		return 0, err
	}

	status := syscall.WaitStatus(0)
	_, err = syscall.Wait4(t.Process.Pid, &status, 0, nil)
	if err != nil {
		return 0, err
	}

	regs, err := t.GetRegs()
	if err != nil {
		return 0, err
	}

	return regs.Orig_rax, nil
}
Пример #6
0
func wait_for_syscall(pid int) (exited bool, err error) {
	var waitStatus syscall.WaitStatus
	for {
		// Entering a syscall
		if err = syscall.PtraceSyscall(pid, 0); err != nil {
			return
		}

		if _, err = syscall.Wait4(pid, &waitStatus, 0, nil); err != nil {
			return
		}

		// Is it for us ?
		if waitStatus.Stopped() && waitStatus.StopSignal()&0x80 == 0x80 {
			return
		}

		if waitStatus.Exited() {
			exited = true
			return
		}
	}
}
Пример #7
0
func Run(startChan <-chan int,
	stopChan chan struct{},
	appName string,
	appArgs []string,
	dirName string) <-chan *report.PtMonitorReport {
	log.Info("ptmon: starting...")

	sysInfo := system.GetSystemInfo()
	archName := system.MachineToArchName(sysInfo.Machine)
	syscallResolver := system.CallNumberResolver(archName)

	reportChan := make(chan *report.PtMonitorReport, 1)

	go func() {
		ptReport := &report.PtMonitorReport{
			ArchName:     string(archName),
			SyscallStats: map[string]report.SyscallStatInfo{},
		}

		syscallStats := map[int16]uint64{}
		eventChan := make(chan syscallEvent)
		doneMonitoring := make(chan int)

		var app *exec.Cmd

		go func() {
			//Ptrace is not pretty... and it requires that you do all ptrace calls from the same thread
			runtime.LockOSThread()

			var err error
			app, err = target.Start(appName, appArgs, dirName, true)
			utils.FailOn(err)
			targetPid := app.Process.Pid

			log.Debugf("ptmon: target PID ==> %d\n", targetPid)

			var wstat syscall.WaitStatus
			_, err = syscall.Wait4(targetPid, &wstat, 0, nil)
			if err != nil {
				log.Warnf("ptmon: error waiting for %d: %v\n", targetPid, err)
				doneMonitoring <- 1
			}

			log.Debugln("ptmon: initial process status =>", wstat)

			if wstat.Exited() {
				log.Warn("ptmon: app exited (unexpected)")
				doneMonitoring <- 2
			}

			if wstat.Signaled() {
				log.Warn("ptmon: app signalled (unexpected)")
				doneMonitoring <- 3
			}

			syscallReturn := false
			gotCallNum := false
			gotRetVal := false
			var callNum uint64
			var retVal uint64
			for wstat.Stopped() {
				var regs syscall.PtraceRegs

				switch syscallReturn {
				case false:
					if err := syscall.PtraceGetRegs(targetPid, &regs); err != nil {
						log.Fatalf("ptmon: PtraceGetRegs(call): %v", err)
					}

					callNum = regs.Orig_rax
					syscallReturn = true
					gotCallNum = true
				case true:
					if err := syscall.PtraceGetRegs(targetPid, &regs); err != nil {
						log.Fatalf("ptmon: PtraceGetRegs(return): %v", err)
					}

					retVal = regs.Rax
					syscallReturn = false
					gotRetVal = true
				}

				err = syscall.PtraceSyscall(targetPid, 0)
				if err != nil {
					log.Warnf("ptmon: PtraceSyscall error: %v\n", err)
					break
				}
				_, err = syscall.Wait4(targetPid, &wstat, 0, nil)
				if err != nil {
					log.Warnf("ptmon: error waiting 4 %d: %v\n", targetPid, err)
					break
				}

				if gotCallNum && gotRetVal {
					gotCallNum = false
					gotRetVal = false

					eventChan <- syscallEvent{
						callNum: int16(callNum),
						retVal:  retVal,
					}
				}
			}

			log.Infoln("ptmon: monitor is exiting... status=", wstat)
			doneMonitoring <- 0
		}()

	done:
		for {
			select {
			case rc := <-doneMonitoring:
				log.Info("ptmon: done =>", rc)
				break done
			case <-stopChan:
				log.Info("ptmon: stopping...")
				//NOTE: need a better way to stop the target app...
				if err := app.Process.Signal(syscall.SIGTERM); err != nil {
					log.Warnln("ptmon: error stopping target app =>", err)
					if err := app.Process.Kill(); err != nil {
						log.Warnln("ptmon: error killing target app =>", err)
					}
				}
				break done
			case e := <-eventChan:
				ptReport.SyscallCount++

				if _, ok := syscallStats[e.callNum]; ok {
					syscallStats[e.callNum]++
				} else {
					syscallStats[e.callNum] = 1
				}
			}
		}

		log.Debugf("ptmon: executed syscall count = %d\n", ptReport.SyscallCount)
		log.Debugf("ptmon: number of syscalls: %v\n", len(syscallStats))
		for scNum, scCount := range syscallStats {
			log.Debugf("[%v] %v = %v", scNum, syscallResolver(scNum), scCount)
			ptReport.SyscallStats[strconv.FormatInt(int64(scNum), 10)] = report.SyscallStatInfo{
				Number: scNum,
				Name:   syscallResolver(scNum),
				Count:  scCount,
			}
		}

		ptReport.SyscallNum = uint32(len(ptReport.SyscallStats))
		reportChan <- ptReport
	}()

	return reportChan
}
Пример #8
0
func (c *Cmd) Run() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	err := c.Cmd.Start()
	if err != nil {
		return err
	}

	ready := map[int]bool{}

	status := syscall.WaitStatus(0)
	usage := syscall.Rusage{}
	for {
		pid, err := syscall.Wait4(c.Cmd.Process.Pid, &status, 0, &usage)
		if err != nil {
			return err
		}

		if !ready[pid] {
			_, _, errno := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), syscall.RLIMIT_CPU, uintptr(unsafe.Pointer(&syscall.Rlimit{
				Cur: uint64(c.Limits.Cpu)/1e9 + 1,
				Max: uint64(c.Limits.Cpu)/1e9 + 1,
			})), 0, 0, 0)
			if errno != 0 {
				err = errno
				return err
			}

			_, _, errno = syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), syscall.RLIMIT_DATA, uintptr(unsafe.Pointer(&syscall.Rlimit{
				Cur: c.Limits.Memory,
				Max: c.Limits.Memory,
			})), 0, 0, 0)
			if errno != 0 {
				err = errno
				return err
			}

			ready[pid] = true
		}

		c.Usages.Cpu = time.Duration(usage.Utime.Nano())
		c.Usages.Memory = uint64(usage.Maxrss * (1 << 10))

		switch {
		case status.Exited():
			if status.ExitStatus() != 0 {
				return ExitError(status)
			}
			return nil

		case status.Signaled():
			return ExitError(status)

		case status.Stopped():
			switch {
			case status.StopSignal()&syscall.SIGTRAP > 0:
				regs := syscall.PtraceRegs{}
				err = syscall.PtraceGetRegs(pid, &regs)
				if err != nil {
					return err
				}

				switch regs.Orig_rax {
				case syscall.SYS_READ:
				case syscall.SYS_WRITE:
				case syscall.SYS_OPEN:
				case syscall.SYS_CLOSE:
				case syscall.SYS_STAT:
				case syscall.SYS_FSTAT:
				case syscall.SYS_LSTAT:
				case syscall.SYS_POLL:
				case syscall.SYS_LSEEK:
				case syscall.SYS_MMAP:
				case syscall.SYS_MPROTECT:
				case syscall.SYS_MUNMAP:
				case syscall.SYS_BRK:
				case syscall.SYS_RT_SIGACTION:
				case syscall.SYS_RT_SIGPROCMASK:
				case syscall.SYS_RT_SIGRETURN:
				case syscall.SYS_IOCTL:
				case syscall.SYS_PREAD64:
				case syscall.SYS_PWRITE64:
				case syscall.SYS_READV:
				case syscall.SYS_WRITEV:
				case syscall.SYS_ACCESS:
				case syscall.SYS_PIPE:
				case syscall.SYS_SELECT:
				case syscall.SYS_SCHED_YIELD:
				case syscall.SYS_MREMAP:
				case syscall.SYS_MSYNC:
				case syscall.SYS_MINCORE:
				case syscall.SYS_MADVISE:
				case syscall.SYS_SHMGET:
				case syscall.SYS_SHMAT:
				case syscall.SYS_SHMCTL:
				case syscall.SYS_DUP:
				case syscall.SYS_DUP2:
				case syscall.SYS_PAUSE:
				case syscall.SYS_NANOSLEEP:
				case syscall.SYS_GETITIMER:
				case syscall.SYS_ALARM:
				case syscall.SYS_SETITIMER:
				case syscall.SYS_GETPID:
				case syscall.SYS_SENDFILE:
				case syscall.SYS_SOCKET:
				case syscall.SYS_CONNECT:
				case syscall.SYS_ACCEPT:
				case syscall.SYS_SENDTO:
				case syscall.SYS_RECVFROM:
				case syscall.SYS_SENDMSG:
				case syscall.SYS_RECVMSG:
				case syscall.SYS_SHUTDOWN:
				case syscall.SYS_BIND:
				case syscall.SYS_LISTEN:
				case syscall.SYS_GETSOCKNAME:
				case syscall.SYS_GETPEERNAME:
				case syscall.SYS_SOCKETPAIR:
				case syscall.SYS_SETSOCKOPT:
				case syscall.SYS_GETSOCKOPT:
				case syscall.SYS_CLONE:
				case syscall.SYS_FORK:
				case syscall.SYS_VFORK:
				case syscall.SYS_EXECVE:
					// err = syscall.Kill(pid, syscall.SIGKILL)
					// if err != nil {
					// 	return err
					// }

				case syscall.SYS_EXIT:
				case syscall.SYS_WAIT4:
				case syscall.SYS_KILL:
				case syscall.SYS_UNAME:
				case syscall.SYS_SEMGET:
				case syscall.SYS_SEMOP:
				case syscall.SYS_SEMCTL:
				case syscall.SYS_SHMDT:
				case syscall.SYS_MSGGET:
				case syscall.SYS_MSGSND:
				case syscall.SYS_MSGRCV:
				case syscall.SYS_MSGCTL:
				case syscall.SYS_FCNTL:
				case syscall.SYS_FLOCK:
				case syscall.SYS_FSYNC:
				case syscall.SYS_FDATASYNC:
				case syscall.SYS_TRUNCATE:
				case syscall.SYS_FTRUNCATE:
				case syscall.SYS_GETDENTS:
				case syscall.SYS_GETCWD:
				case syscall.SYS_CHDIR:
				case syscall.SYS_FCHDIR:
				case syscall.SYS_RENAME:
				case syscall.SYS_MKDIR:
				case syscall.SYS_RMDIR:
				case syscall.SYS_CREAT:
				case syscall.SYS_LINK:
				case syscall.SYS_UNLINK:
				case syscall.SYS_SYMLINK:
				case syscall.SYS_READLINK:
				case syscall.SYS_CHMOD:
				case syscall.SYS_FCHMOD:
				case syscall.SYS_CHOWN:
				case syscall.SYS_FCHOWN:
				case syscall.SYS_LCHOWN:
				case syscall.SYS_UMASK:
				case syscall.SYS_GETTIMEOFDAY:
				case syscall.SYS_GETRLIMIT:
				case syscall.SYS_GETRUSAGE:
				case syscall.SYS_SYSINFO:
				case syscall.SYS_TIMES:
				case syscall.SYS_PTRACE:
				case syscall.SYS_GETUID:
				case syscall.SYS_SYSLOG:
				case syscall.SYS_GETGID:
				case syscall.SYS_SETUID:
				case syscall.SYS_SETGID:
				case syscall.SYS_GETEUID:
				case syscall.SYS_GETEGID:
				case syscall.SYS_SETPGID:
				case syscall.SYS_GETPPID:
				case syscall.SYS_GETPGRP:
				case syscall.SYS_SETSID:
				case syscall.SYS_SETREUID:
				case syscall.SYS_SETREGID:
				case syscall.SYS_GETGROUPS:
				case syscall.SYS_SETGROUPS:
				case syscall.SYS_SETRESUID:
				case syscall.SYS_GETRESUID:
				case syscall.SYS_SETRESGID:
				case syscall.SYS_GETRESGID:
				case syscall.SYS_GETPGID:
				case syscall.SYS_SETFSUID:
				case syscall.SYS_SETFSGID:
				case syscall.SYS_GETSID:
				case syscall.SYS_CAPGET:
				case syscall.SYS_CAPSET:
				case syscall.SYS_RT_SIGPENDING:
				case syscall.SYS_RT_SIGTIMEDWAIT:
				case syscall.SYS_RT_SIGQUEUEINFO:
				case syscall.SYS_RT_SIGSUSPEND:
				case syscall.SYS_SIGALTSTACK:
				case syscall.SYS_UTIME:
				case syscall.SYS_MKNOD:
				case syscall.SYS_USELIB:
				case syscall.SYS_PERSONALITY:
				case syscall.SYS_USTAT:
				case syscall.SYS_STATFS:
				case syscall.SYS_FSTATFS:
				case syscall.SYS_SYSFS:
				case syscall.SYS_GETPRIORITY:
				case syscall.SYS_SETPRIORITY:
				case syscall.SYS_SCHED_SETPARAM:
				case syscall.SYS_SCHED_GETPARAM:
				case syscall.SYS_SCHED_SETSCHEDULER:
				case syscall.SYS_SCHED_GETSCHEDULER:
				case syscall.SYS_SCHED_GET_PRIORITY_MAX:
				case syscall.SYS_SCHED_GET_PRIORITY_MIN:
				case syscall.SYS_SCHED_RR_GET_INTERVAL:
				case syscall.SYS_MLOCK:
				case syscall.SYS_MUNLOCK:
				case syscall.SYS_MLOCKALL:
				case syscall.SYS_MUNLOCKALL:
				case syscall.SYS_VHANGUP:
				case syscall.SYS_MODIFY_LDT:
				case syscall.SYS_PIVOT_ROOT:
				case syscall.SYS__SYSCTL:
				case syscall.SYS_PRCTL:
				case syscall.SYS_ARCH_PRCTL:
				case syscall.SYS_ADJTIMEX:
				case syscall.SYS_SETRLIMIT:
				case syscall.SYS_CHROOT:
				case syscall.SYS_SYNC:
				case syscall.SYS_ACCT:
				case syscall.SYS_SETTIMEOFDAY:
				case syscall.SYS_MOUNT:
				case syscall.SYS_UMOUNT2:
				case syscall.SYS_SWAPON:
				case syscall.SYS_SWAPOFF:
				case syscall.SYS_REBOOT:
				case syscall.SYS_SETHOSTNAME:
				case syscall.SYS_SETDOMAINNAME:
				case syscall.SYS_IOPL:
				case syscall.SYS_IOPERM:
				case syscall.SYS_CREATE_MODULE:
				case syscall.SYS_INIT_MODULE:
				case syscall.SYS_DELETE_MODULE:
				case syscall.SYS_GET_KERNEL_SYMS:
				case syscall.SYS_QUERY_MODULE:
				case syscall.SYS_QUOTACTL:
				case syscall.SYS_NFSSERVCTL:
				case syscall.SYS_GETPMSG:
				case syscall.SYS_PUTPMSG:
				case syscall.SYS_AFS_SYSCALL:
				case syscall.SYS_TUXCALL:
				case syscall.SYS_SECURITY:
				case syscall.SYS_GETTID:
				case syscall.SYS_READAHEAD:
				case syscall.SYS_SETXATTR:
				case syscall.SYS_LSETXATTR:
				case syscall.SYS_FSETXATTR:
				case syscall.SYS_GETXATTR:
				case syscall.SYS_LGETXATTR:
				case syscall.SYS_FGETXATTR:
				case syscall.SYS_LISTXATTR:
				case syscall.SYS_LLISTXATTR:
				case syscall.SYS_FLISTXATTR:
				case syscall.SYS_REMOVEXATTR:
				case syscall.SYS_LREMOVEXATTR:
				case syscall.SYS_FREMOVEXATTR:
				case syscall.SYS_TKILL:
				case syscall.SYS_TIME:
				case syscall.SYS_FUTEX:
				case syscall.SYS_SCHED_SETAFFINITY:
				case syscall.SYS_SCHED_GETAFFINITY:
				case syscall.SYS_SET_THREAD_AREA:
				case syscall.SYS_IO_SETUP:
				case syscall.SYS_IO_DESTROY:
				case syscall.SYS_IO_GETEVENTS:
				case syscall.SYS_IO_SUBMIT:
				case syscall.SYS_IO_CANCEL:
				case syscall.SYS_GET_THREAD_AREA:
				case syscall.SYS_LOOKUP_DCOOKIE:
				case syscall.SYS_EPOLL_CREATE:
				case syscall.SYS_EPOLL_CTL_OLD:
				case syscall.SYS_EPOLL_WAIT_OLD:
				case syscall.SYS_REMAP_FILE_PAGES:
				case syscall.SYS_GETDENTS64:
				case syscall.SYS_SET_TID_ADDRESS:
				case syscall.SYS_RESTART_SYSCALL:
				case syscall.SYS_SEMTIMEDOP:
				case syscall.SYS_FADVISE64:
				case syscall.SYS_TIMER_CREATE:
				case syscall.SYS_TIMER_SETTIME:
				case syscall.SYS_TIMER_GETTIME:
				case syscall.SYS_TIMER_GETOVERRUN:
				case syscall.SYS_TIMER_DELETE:
				case syscall.SYS_CLOCK_SETTIME:
				case syscall.SYS_CLOCK_GETTIME:
				case syscall.SYS_CLOCK_GETRES:
				case syscall.SYS_CLOCK_NANOSLEEP:
				case syscall.SYS_EXIT_GROUP:
				case syscall.SYS_EPOLL_WAIT:
				case syscall.SYS_EPOLL_CTL:
				case syscall.SYS_TGKILL:
				case syscall.SYS_UTIMES:
				case syscall.SYS_VSERVER:
				case syscall.SYS_MBIND:
				case syscall.SYS_SET_MEMPOLICY:
				case syscall.SYS_GET_MEMPOLICY:
				case syscall.SYS_MQ_OPEN:
				case syscall.SYS_MQ_UNLINK:
				case syscall.SYS_MQ_TIMEDSEND:
				case syscall.SYS_MQ_TIMEDRECEIVE:
				case syscall.SYS_MQ_NOTIFY:
				case syscall.SYS_MQ_GETSETATTR:
				case syscall.SYS_KEXEC_LOAD:
				case syscall.SYS_WAITID:
				case syscall.SYS_ADD_KEY:
				case syscall.SYS_REQUEST_KEY:
				case syscall.SYS_KEYCTL:
				case syscall.SYS_IOPRIO_SET:
				case syscall.SYS_IOPRIO_GET:
				case syscall.SYS_INOTIFY_INIT:
				case syscall.SYS_INOTIFY_ADD_WATCH:
				case syscall.SYS_INOTIFY_RM_WATCH:
				case syscall.SYS_MIGRATE_PAGES:
				case syscall.SYS_OPENAT:
				case syscall.SYS_MKDIRAT:
				case syscall.SYS_MKNODAT:
				case syscall.SYS_FCHOWNAT:
				case syscall.SYS_FUTIMESAT:
				case syscall.SYS_NEWFSTATAT:
				case syscall.SYS_UNLINKAT:
				case syscall.SYS_RENAMEAT:
				case syscall.SYS_LINKAT:
				case syscall.SYS_SYMLINKAT:
				case syscall.SYS_READLINKAT:
				case syscall.SYS_FCHMODAT:
				case syscall.SYS_FACCESSAT:
				case syscall.SYS_PSELECT6:
				case syscall.SYS_PPOLL:
				case syscall.SYS_UNSHARE:
				case syscall.SYS_SET_ROBUST_LIST:
				case syscall.SYS_GET_ROBUST_LIST:
				case syscall.SYS_SPLICE:
				case syscall.SYS_TEE:
				case syscall.SYS_SYNC_FILE_RANGE:
				case syscall.SYS_VMSPLICE:
				case syscall.SYS_MOVE_PAGES:
				case syscall.SYS_UTIMENSAT:
				case syscall.SYS_EPOLL_PWAIT:
				case syscall.SYS_SIGNALFD:
				case syscall.SYS_TIMERFD_CREATE:
				case syscall.SYS_EVENTFD:
				case syscall.SYS_FALLOCATE:
				case syscall.SYS_TIMERFD_SETTIME:
				case syscall.SYS_TIMERFD_GETTIME:
				case syscall.SYS_ACCEPT4:
				case syscall.SYS_SIGNALFD4:
				case syscall.SYS_EVENTFD2:
				case syscall.SYS_EPOLL_CREATE1:
				case syscall.SYS_DUP3:
				case syscall.SYS_PIPE2:
				case syscall.SYS_INOTIFY_INIT1:
				case syscall.SYS_PREADV:
				case syscall.SYS_PWRITEV:
				case syscall.SYS_RT_TGSIGQUEUEINFO:
				case syscall.SYS_PERF_EVENT_OPEN:
				case syscall.SYS_RECVMMSG:
				case syscall.SYS_FANOTIFY_INIT:
				case syscall.SYS_FANOTIFY_MARK:
				case syscall.SYS_PRLIMIT64:
				}

				err = syscall.PtraceSyscall(pid, 0)
				if err != nil {
					return err
				}

			default:
				return ExitError(status)
			}
		}
	}

	panic("unreachable")
}
Пример #9
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)
	}
}