Beispiel #1
0
int tracer_copy_out( struct tracer *t, const void *data, const void *uaddr, int length )
{
    int result;
    static int has_fast_write=1;
    UPTRINT_T iuaddr = (UPTRINT_T)uaddr;

    if(length==0) return 0;

#if !defined(CCTOOLS_CPU_I386)
    if(!tracer_is_64bit(t)) iuaddr &= 0xffffffff;
#endif

    if(has_fast_write) {
        result = full_pwrite64(t->memory_file,data,length,iuaddr);
        if( result!=length ) {
            has_fast_write = 0;
            debug(D_SYSCALL,"writing to /proc/X/mem failed, falling back to slow ptrace write");
        } else {
            return result;
        }
    }

    result = tracer_copy_out_slow(t,data,(void*)iuaddr,length);

    return result;
}
Beispiel #2
0
int tracer_copy_in( struct tracer *t, void *data, const void *uaddr, int length )
{
    int result;
    static int fast_read_success = 0;
    static int fast_read_failure = 0;
    static int fast_read_attempts = 100;

    UPTRINT_T iuaddr = (UPTRINT_T)uaddr;

#if !defined(CCTOOLS_CPU_I386)
    if(!tracer_is_64bit(t)) iuaddr &= 0xffffffff;
#endif

    if(fast_read_success>0 || fast_read_failure<fast_read_attempts) {
        result = full_pread64(t->memory_file,data,length,iuaddr);
        if(result>0) {
            fast_read_success++;
            return result;
        } else {
            fast_read_failure++;
            // fall through to slow method, print message on the last attempt.
            if(fast_read_success==0 && fast_read_failure>=fast_read_attempts) {
                debug(D_SYSCALL,"reading from /proc/X/mem failed, falling back to slow ptrace read");
            }
        }
    }

    result = tracer_copy_in_slow(t,data,(void*)iuaddr,length);

    return result;
}
Beispiel #3
0
ssize_t tracer_copy_in_string( struct tracer *t, char *str, const void *uaddr, size_t length, int flags )
{
	if(length==0) return 0;

#if !defined(CCTOOLS_CPU_I386)
	if(!tracer_is_64bit(t)) {
		uaddr = VOID_MATH(uaddr, & 0xffffffff);
	}
#endif

	ssize_t rc = copy_in_fast(t,str,uaddr,length,flags);
	if (rc == -1 && errno == ENOSYS && !(flags & TRACER_O_FAST))
		rc = copy_in_string_slow(t,str,uaddr,length,flags);
	/* check for NUL */
	if (rc > 0) {
		void *nul = memchr(str,'\0',length);
		if (nul) {
			rc = (ssize_t)((uintptr_t)nul-(uintptr_t)str);
		} else {
			*str = '\0';
			errno = EINVAL;
			rc = -1;
		}
	}
	return rc;
}
Beispiel #4
0
int tracer_copy_in( struct tracer *t, void *data, const void *uaddr, int length )
{
	int result;
	static int has_fast_read = 1;

	UPTRINT_T iuaddr = (UPTRINT_T)uaddr;

#if !defined(CCTOOLS_CPU_I386)
	if(!tracer_is_64bit(t)) iuaddr &= 0xffffffff;
#endif

	if(has_fast_read) {
		result = full_pread64(t->memory_file,data,length,iuaddr);
		if( result<=0 && errno==EINVAL ) {
			has_fast_read = 0;
			debug(D_SYSCALL,"reading from /proc/X/mem failed, falling back to slow ptrace read");
		} else {
			return result;
		}
	}

	result = tracer_copy_in_slow(t,data,(void*)iuaddr,length);

	return result;
}
Beispiel #5
0
const char * tracer_syscall_name( struct tracer *t, int syscall )
{
    if(tracer_is_64bit(t)) {
        return tracer_syscall64_name(syscall);
    } else {
        return tracer_syscall32_name(syscall);
    }
}
Beispiel #6
0
int tracer_args_set( struct tracer *t, INT64_T syscall, const INT64_T *args, int nargs )
{
	if(!t->gotregs) {
		if(ptrace(PTRACE_GETREGS,t->pid,0,&t->regs) == -1)
			ERROR;
		t->gotregs = 1;
	}

#if 0 /* Enable this for extreme debugging... */
	{
		int i;
		buffer_t B;
		buffer_init(&B);
		buffer_putfstring(&B, "SET args[%zu] = {", (size_t)nargs);
		for (i = 0; i < nargs; i++)
			buffer_putfstring(&B, "%" PRId64 ", ", args[i]);
		buffer_putliteral(&B, "}");
		debug(D_DEBUG, "%s", buffer_tostring(&B, NULL));
		buffer_free(&B);
	}
#endif

#ifdef CCTOOLS_CPU_I386
	t->regs.regs32.orig_eax = syscall;
	if(nargs>=1) t->regs.regs32.ebx = args[0];
	if(nargs>=2) t->regs.regs32.ecx = args[1];
	if(nargs>=3) t->regs.regs32.edx = args[2];
	if(nargs>=4) t->regs.regs32.esi = args[3];
	if(nargs>=5) t->regs.regs32.edi = args[4];
	if(nargs>=6) t->regs.regs32.ebp = args[5];
#else
	if(tracer_is_64bit(t)) {
		t->regs.regs64.orig_rax = syscall;
		if(nargs>=1) t->regs.regs64.rdi = args[0];
		if(nargs>=2) t->regs.regs64.rsi = args[1];
		if(nargs>=3) t->regs.regs64.rdx = args[2];
		if(nargs>=4) t->regs.regs64.r10 = args[3];
		if(nargs>=5) t->regs.regs64.r8  = args[4];
		if(nargs>=6) t->regs.regs64.r9  = args[5];
	} else {
		t->regs.regs64.orig_rax = syscall;
		if(nargs>=1) t->regs.regs64.rbx = args[0];
		if(nargs>=2) t->regs.regs64.rcx = args[1];
		if(nargs>=3) t->regs.regs64.rdx = args[2];
		if(nargs>=4) t->regs.regs64.rsi = args[3];
		if(nargs>=5) t->regs.regs64.rdi  = args[4];
		if(nargs>=6) {
			if (t->has_args5_bug) t->regs.regs64.r9 = args[5];
			else                  t->regs.regs64.rbp = args[5];
		}
	}
#endif

	t->setregs = 1;

	return 1;
}
Beispiel #7
0
ssize_t tracer_copy_in( struct tracer *t, void *data, const void *uaddr, size_t length, int flags )
{
	if(length==0) return 0;

#if !defined(CCTOOLS_CPU_I386)
	if(!tracer_is_64bit(t)) {
		uaddr = VOID_MATH(uaddr, & 0xffffffff);
	}
#endif

	ssize_t rc = copy_in_fast(t,data,uaddr,length,flags);
	if (rc == -1 && errno == ENOSYS && !(flags & TRACER_O_FAST))
		rc = tracer_copy_in_slow(t,data,uaddr,length,flags);
	assert(!(flags & TRACER_O_ATOMIC) || (rc == -1 || (size_t)rc == length));
	return rc;
}
Beispiel #8
0
int tracer_args_get( struct tracer *t, INT64_T *syscall, INT64_T args[TRACER_ARGS_MAX] )
{
	if(!t->gotregs) {
		if(ptrace(PTRACE_GETREGS,t->pid,0,&t->regs) == -1)
			ERROR;
		t->gotregs = 1;
	}

#ifdef CCTOOLS_CPU_I386
	*syscall = t->regs.regs32.orig_eax;
	args[0] = t->regs.regs32.ebx;
	args[1] = t->regs.regs32.ecx;
	args[2] = t->regs.regs32.edx;
	args[3] = t->regs.regs32.esi;
	args[4] = t->regs.regs32.edi;
	args[5] = t->regs.regs32.ebp;
#else
	if(tracer_is_64bit(t)) {
		*syscall = t->regs.regs64.orig_rax;
#if 0 /* Enable this for extreme debugging... */
		debug(D_DEBUG, "rax = %d; -%d is -ENOSYS (rax == -ENOSYS indicates syscall-enter-stop)", (int)t->regs.regs64.rax, ENOSYS);
#endif
		args[0] = t->regs.regs64.rdi;
		args[1] = t->regs.regs64.rsi;
		args[2] = t->regs.regs64.rdx;
		args[3] = t->regs.regs64.r10;
		args[4] = t->regs.regs64.r8;
		args[5] = t->regs.regs64.r9;
	} else {
		*syscall = t->regs.regs64.orig_rax;
		args[0] = t->regs.regs64.rbx;
		args[1] = t->regs.regs64.rcx;
		args[2] = t->regs.regs64.rdx;
		args[3] = t->regs.regs64.rsi;
		args[4] = t->regs.regs64.rdi;
		if (t->has_args5_bug) args[5] = t->regs.regs64.r9;
		else                  args[5] = t->regs.regs64.rbp;
	}
#endif
#if 0 /* Enable this for extreme debugging... */
	debug(D_DEBUG, "GET args[] = {%"PRId64", %"PRId64", %"PRId64", %"PRId64", %"PRId64", %"PRId64"}", args[0], args[1], args[2], args[3], args[4], args[5]);
#endif

	return 1;
}
Beispiel #9
0
int tracer_args_set( struct tracer *t, INT64_T syscall, INT64_T args[TRACER_ARGS_MAX], int nargs )
{
    if(!t->gotregs) {
        if(ptrace(PTRACE_GETREGS,t->pid,0,&t->regs)!=0) FATAL;
        t->gotregs = 1;
    }

#ifdef CCTOOLS_CPU_I386
    t->regs.regs32.orig_eax = syscall;
    if(nargs>=1) t->regs.regs32.ebx = args[0];
    if(nargs>=2) t->regs.regs32.ecx = args[1];
    if(nargs>=3) t->regs.regs32.edx = args[2];
    if(nargs>=4) t->regs.regs32.esi = args[3];
    if(nargs>=5) t->regs.regs32.edi = args[4];
    if(nargs>=6) t->regs.regs32.ebp = args[5];
#else
    if(tracer_is_64bit(t)) {
        t->regs.regs64.orig_rax = syscall;
        if(nargs>=1) t->regs.regs64.rdi = args[0];
        if(nargs>=2) t->regs.regs64.rsi = args[1];
        if(nargs>=3) t->regs.regs64.rdx = args[2];
        if(nargs>=4) t->regs.regs64.r10 = args[3];
        if(nargs>=5) t->regs.regs64.r8  = args[4];
        if(nargs>=6) t->regs.regs64.r9  = args[5];
    } else {
        t->regs.regs64.orig_rax = syscall;
        if(nargs>=1) t->regs.regs64.rbx = args[0];
        if(nargs>=2) t->regs.regs64.rcx = args[1];
        if(nargs>=3) t->regs.regs64.rdx = args[2];
        if(nargs>=4) t->regs.regs64.rsi = args[3];
        if(nargs>=5) t->regs.regs64.rdi  = args[4];
        if(nargs>=6) {
            if (t->has_args5_bug) t->regs.regs64.r9 = args[5];
            else                  t->regs.regs64.rbp = args[5];
        }
    }
#endif

    if(ptrace(PTRACE_SETREGS,t->pid,0,&t->regs)!=0) FATAL;

    return 1;
}
Beispiel #10
0
int tracer_args_get( struct tracer *t, INT64_T *syscall, INT64_T args[TRACER_ARGS_MAX] )
{
    if(!t->gotregs) {
        if(ptrace(PTRACE_GETREGS,t->pid,0,&t->regs)!=0) FATAL;
        t->gotregs = 1;
    }

#ifdef CCTOOLS_CPU_I386
    *syscall = t->regs.regs32.orig_eax;
    args[0] = t->regs.regs32.ebx;
    args[1] = t->regs.regs32.ecx;
    args[2] = t->regs.regs32.edx;
    args[3] = t->regs.regs32.esi;
    args[4] = t->regs.regs32.edi;
    args[5] = t->regs.regs32.ebp;
#else
    if(tracer_is_64bit(t)) {
        *syscall = t->regs.regs64.orig_rax;
        args[0] = t->regs.regs64.rdi;
        args[1] = t->regs.regs64.rsi;
        args[2] = t->regs.regs64.rdx;
        args[3] = t->regs.regs64.r10;
        args[4] = t->regs.regs64.r8;
        args[5] = t->regs.regs64.r9;
    } else {
        *syscall = t->regs.regs64.orig_rax;
        args[0] = t->regs.regs64.rbx;
        args[1] = t->regs.regs64.rcx;
        args[2] = t->regs.regs64.rdx;
        args[3] = t->regs.regs64.rsi;
        args[4] = t->regs.regs64.rdi;
        if (t->has_args5_bug) args[5] = t->regs.regs64.r9;
        else                  args[5] = t->regs.regs64.rbp;
    }
#endif

    return 1;
}