def watchRunProgram(self, pid):
     usingMem = 0
     
     while True:
         wpid, status, res = os.wait4(pid,0)
         signal.signal(signal.SIGXCPU, self.sigHandler)
         
         # 정상 종료된 경우
         if os.WIFEXITED(status):
             return 'Grading', res[0], usingMem
         
         exitCode = os.WEXITSTATUS(status)
         
         # 종료 코드에 따라 return
         if  exitCode is 24:
             return ENUMResources.const.TIME_OVER, res[0], usingMem
         
         elif exitCode is not 5 and exitCode is not 0 and exitCode is not 17:
             return ENUMResources.const.RUNTIME_ERROR, 0, 0 
         
         elif os.WIFSIGNALED(status):
             try:
                 ptrace.kill(pid)
             except Exception as e:
                 pass
             
             return ENUMResources.const.RUNTIME_ERROR, 0, 0
         
         # 메모리 사용량 측정
         else:
             usingMem = self.getUsingMemory(pid, usingMem, res[6])
             
             ptrace.syscall(pid, 0)
    def watchRunProgram(self, pid):
        usingMem = 0

        while True:
            wpid, status, res = os.wait4(pid, 0)
            signal.signal(signal.SIGXCPU, self.sigHandler)

            # 정상 종료된 경우
            if os.WIFEXITED(status):
                return 'Grading', res[0], usingMem

            exitCode = os.WEXITSTATUS(status)

            # 종료 코드에 따라 return
            if exitCode is 24:
                return ENUMResources.const.TIME_OVER, res[0], usingMem

            elif exitCode is not 5 and exitCode is not 0 and exitCode is not 17:
                return ENUMResources.const.RUNTIME_ERROR, 0, 0

            elif os.WIFSIGNALED(status):
                try:
                    ptrace.kill(pid)
                except Exception as e:
                    pass

                return ENUMResources.const.RUNTIME_ERROR, 0, 0

            # 메모리 사용량 측정
            else:
                usingMem = self.getUsingMemory(pid, usingMem, res[6])

                ptrace.syscall(pid, 0)
Example #3
0
def trace_syscall(pid, flags, tricklist):
    scno = ptrace.peekuser(pid, ORIG_EAX)

    assert (0 <= scno < len(syscallmap.table)
            or scno == _badcall
            or flags.has_key('sigreturn')), \
            "unknown system call (=%s, pid=%s, flags=%s)" % (scno, pid, flags)

    if scno == _badcall:
        call = 'badcall'
    elif flags.has_key('sigreturn'):
        call = flags['sigreturn']  # !beforecall
    else:
        sysent = syscallmap.table[scno]
        call = sysent[syscallmap.CALL]

    eax = ptrace.peekuser(pid, EAX)

    beforecall = not flags.has_key('insyscall')
    if eax != -errno.ENOSYS and beforecall:  # XXX: is this test right?
        if call == 'execve' and debug():
            print 'debug: ignoring additional execve stop'
            return
        if 0 <= eax <= len(syscallmap.table):
            eaxcall = syscallmap.table[eax][3]
        else:
            eaxcall = ""
        # FIX: this probably fires for SIG_DFL stop calls (except SIGSTOP)
        print 'warning: received SIGTRAP or stray syscall exit: eax = %d (%s)' % (
            eax, eaxcall)
        # FIX: is this right?  what's really going on here?
        # no, don't do this, because of the SIG_DFL issue above!!!!!  --mkc
        #raise 'warning: received SIGTRAP or stray syscall exit:' \
        #      'pid = %d, eax = %d (%s)' % (pid, eax, eaxcall)
        #return
        # FIX: is this the right thing to do?
        flags['insyscall'] = 1
        flags['state'] = {}
        flags['call_changes'] = {}

    global _skipcallafter
    if beforecall:
        if not _call_weedout_mask[scno]:
            _skipcallafter[pid] = 1
            flags['insyscall'] = 1
            ptrace.syscall(pid, 0)
            return
        return trace_syscall_before(pid, flags, tricklist, call, scno, sysent)

    if _skipcallafter.has_key(pid):
        del _skipcallafter[pid]
        del flags['insyscall']
        ptrace.syscall(pid, 0)
        return
    return trace_syscall_after(pid, flags, tricklist, call, eax)
Example #4
0
def trace_syscall(pid, flags, tricklist):
    scno = ptrace.peekuser(pid, ORIG_EAX)

    assert (
        0 <= scno < len(syscallmap.table) or scno == _badcall or flags.has_key("sigreturn")
    ), "unknown system call (=%s, pid=%s, flags=%s)" % (scno, pid, flags)

    if scno == _badcall:
        call = "badcall"
    elif flags.has_key("sigreturn"):
        call = flags["sigreturn"]  # !beforecall
    else:
        sysent = syscallmap.table[scno]
        call = sysent[syscallmap.CALL]

    eax = ptrace.peekuser(pid, EAX)

    beforecall = not flags.has_key("insyscall")
    if eax != -errno.ENOSYS and beforecall:  # XXX: is this test right?
        if call == "execve" and debug():
            print "debug: ignoring additional execve stop"
            return
        if 0 <= eax <= len(syscallmap.table):
            eaxcall = syscallmap.table[eax][3]
        else:
            eaxcall = ""
        # FIX: this probably fires for SIG_DFL stop calls (except SIGSTOP)
        print "warning: received SIGTRAP or stray syscall exit: eax = %d (%s)" % (eax, eaxcall)
        # FIX: is this right?  what's really going on here?
        # no, don't do this, because of the SIG_DFL issue above!!!!!  --mkc
        # raise 'warning: received SIGTRAP or stray syscall exit:' \
        #      'pid = %d, eax = %d (%s)' % (pid, eax, eaxcall)
        # return
        # FIX: is this the right thing to do?
        flags["insyscall"] = 1
        flags["state"] = {}
        flags["call_changes"] = {}

    global _skipcallafter
    if beforecall:
        if not _call_weedout_mask[scno]:
            _skipcallafter[pid] = 1
            flags["insyscall"] = 1
            ptrace.syscall(pid, 0)
            return
        return trace_syscall_before(pid, flags, tricklist, call, scno, sysent)

    if _skipcallafter.has_key(pid):
        del _skipcallafter[pid]
        del flags["insyscall"]
        ptrace.syscall(pid, 0)
        return
    return trace_syscall_after(pid, flags, tricklist, call, eax)
Example #5
0
def force_syscall(pid, scno, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0):
    registers = peek_args(pid, 6)
    eip = ptrace.peekuser(pid, EIP)
    eax = ptrace.peekuser(pid, EAX)
    ptrace.pokeuser(pid, EIP, eip - 2)
    ptrace.pokeuser(pid, EAX, scno)  # Select new scno and point eip to syscall
    poke_args(pid, 6, [p1, p2, p3, p4, p5, p6])
    ptrace.syscall(pid, 0)  # We make it return to userland and do syscal
    wpid, status = os.waitpid(pid, wait_flags)
    assert pid == wpid
    ptrace.syscall(pid, 0)  # Kernel stops us before syscall is done
    wpid, status = os.waitpid(pid, wait_flags)
    if wpid != pid:
        print "problem: other syscall stopped woke up /2: ", pid, " != ", wpid
    assert pid == wpid  # Kernel stops us when syscall is done
    res = ptrace.peekuser(pid, EAX)  # We get the syscall result
    ptrace.pokeuser(pid, EAX, eax)  # and then mimic like nothing happened
    poke_args(pid, 6, registers)
    return res
Example #6
0
def force_syscall(pid, scno, p1=0, p2=0, p3=0, p4=0, p5=0, p6=0):
    registers = peek_args(pid, 6)
    eip = ptrace.peekuser(pid, EIP)
    eax = ptrace.peekuser(pid, EAX)
    ptrace.pokeuser(pid, EIP, eip - 2)
    ptrace.pokeuser(pid, EAX, scno)  # Select new scno and point eip to syscall
    poke_args(pid, 6, [p1, p2, p3, p4, p5, p6])
    ptrace.syscall(pid, 0)  # We make it return to userland and do syscal
    wpid, status = os.waitpid(pid, wait_flags)
    assert pid == wpid
    ptrace.syscall(pid, 0)  # Kernel stops us before syscall is done
    wpid, status = os.waitpid(pid, wait_flags)
    if wpid != pid:
        print "problem: other syscall stopped woke up /2: ", pid, " != ", wpid
    assert pid == wpid  # Kernel stops us when syscall is done
    res = ptrace.peekuser(pid, EAX)  # We get the syscall result
    ptrace.pokeuser(pid, EAX, eax)  # and then mimic like nothing happened
    poke_args(pid, 6, registers)
    return res
Example #7
0
    def __traceProgram(self, pid):
        while True:
            wpid, status, res = os.wait4(pid, 0)

            # normal termination
            if os.WIFEXITED(status):
                return True, res[0]

            # abnormal termination
            elif os.WIFSIGNALED(status):
                try:
                    ptrace.kill(pid)
                except Exception as e:
                    pass

                return RUNTIME_ERROR, res[0]

            else:
                ptrace.syscall(pid, 0)
 def WatchRunProgram(self, pid):
     usingMem = 0
     
     while True:
         wpid, status, res = os.wait4(pid,0)
 
         if os.WIFEXITED(status):
             return 'Grading', res[0], usingMem
         
         exitCode = os.WEXITSTATUS(status)
         if exitCode != 5 and exitCode != 0 and exitCode != 17:
             return ENUMResources.const.RUNTIME_ERROR, 0, 0 
             
         elif os.WIFSIGNALED(status):
             return ENUMResources.const.TIME_OVER, res[0], usingMem
         
         else:
             usingMem = self.GetUsingMemory(pid, usingMem)
             
             
             ptrace.syscall(pid, 0)
Example #9
0
            if flags.has_key('startup'):
                # XXX: This is a slight race, as we're assuming this is the
                # SIGTRAP after first exec.
                # Hmm: is this an early chance to do something interesting?
                try:
                    ptrace.settracesysgood(wpid)
                except OSError, e:
                    if e.errno == errno.EIO:
                        # kernel doesn't have this patch (which means it'd
                        # better have the old one)
                        if debug():
                            print "warning: using tracesysgood backward compatibility mode"
                    else:
                        sys.exit("%s settracesysgood error [%s]" % (sys.argv[0], e))

                ptrace.syscall(wpid, 0)
                del flags['startup']
                continue

            stopsig = os.WSTOPSIG(status)
            
            if waitchannelhack:
                callstop = _subterfugue.atcallstop(wpid, stopsig)
            else:
                callstop = stopsig == signal.SIGTRAP | 0x80

            if not callstop:
                sig = trace_signal(wpid, flags, tricklist, stopsig)
                if (sig == signal.SIGSTOP or sig == signal.SIGTSTP
                    or sig == signal.SIGTTIN or sig == signal.SIGTTOU):
                    # FIX: more needed for ~SIGSTOP case
Example #10
0
def trace_syscall_after(pid, flags, tricklist, call, eax):
    result = eax
    state = flags["state"]
    call_changes = flags["call_changes"]
    # del flags['call_changes']		 # ?

    # FIX: copy/reverse slow?
    tricklist = tricklist[:]

    # do callafters for tricks we did callbefores on, in reverse order,
    # minus the annulled trick (if any)
    if flags.has_key("annul"):
        result, annultrick = flags["annul"]
        assert isinstance(result, types.IntType), "oops: waitsuspend not cleared?"
        del flags["annul"]
        call = call_changes[annultrick]
        while tricklist and tricklist.pop()[0] != annultrick:
            pass
    elif flags.has_key("sigreturn"):
        # we have to do this because ORIG_EAX somehow gets stomped by the
        # sigreturn calls.  maybe this is a kernel bug?
        call = flags["sigreturn"]
        del flags["sigreturn"]
    tricklist.reverse()

    memory = getMemory(pid)

    for trick, callmask, signalmask in tricklist:
        call = call_changes.get(trick, call)
        if (not callmask or callmask.has_key(call)) and trick.is_enabled(pid):
            r = trick.callafter(pid, call, result, state.get(trick))
            if r != None:
                result = r
            memory.pop(trick)

    assert memory.empty()  # all momentary changes got popped

    if result != eax:
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, EAX, result)
        ptrace.pokeuser(pid, EAX, result)

        # undo any changes to child's args made on entry
        # XXX: does this go here?
    for n, arg in flags.get("args_delta", []):
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, 4 * n, arg)
        ptrace.pokeuser(pid, 4 * n, arg)
    call_save = flags.get("call_delta", -1)
    if call_save >= 0:
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, call_save)
        ptrace.pokeuser(pid, ORIG_EAX, call_save)

        # could continue child hereabouts
    ptrace.syscall(pid, 0)

    if flags.has_key("call_delta"):
        del flags["call_delta"]
    if flags.has_key("args_delta"):
        del flags["args_delta"]
    del flags["insyscall"]
Example #11
0
        if isinstance(call, types.StringType):
            callno = syscallmap.lookup_number(call)
        else:
            callno = call

        try:
            if debug():
                print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, callno)
            ptrace.pokeuser(pid, ORIG_EAX, callno)
            flags["call_delta"] = scno
        except OSError, e:
            # FIX: do something better here
            sys.exit("panic: call alter failed in trick %s (%s)" % (trick, e))

        # could continue child hereabouts
    ptrace.syscall(pid, 0)

    flags["state"] = state
    flags["insyscall"] = 1
    if flags.has_key("newchild"):
        assert call == "clone"
        newppid, tag = flags["newchild"]  # FIX: better way to pass these back?
        del flags["newchild"]
        # XXX: deep copy causes a problem?  CHECK THIS
        f = copy.copy(flags)
        f["newchildflags"] = {}
        f["children"] = []
        if newppid == pid:
            f["parent"] = pid
        f["exit_signal"] = args[0] & clone.CSIGNAL
        return (newppid, tag, f)
Example #12
0
                # XXX: This is a slight race, as we're assuming this is the
                # SIGTRAP after first exec.
                # Hmm: is this an early chance to do something interesting?
                try:
                    ptrace.settracesysgood(wpid)
                except OSError, e:
                    if e.errno == errno.EIO:
                        # kernel doesn't have this patch (which means it'd
                        # better have the old one)
                        if debug():
                            print "warning: using tracesysgood backward compatibility mode"
                    else:
                        sys.exit("%s settracesysgood error [%s]" %
                                 (sys.argv[0], e))

                ptrace.syscall(wpid, 0)
                del flags['startup']
                continue

            stopsig = os.WSTOPSIG(status)

            if waitchannelhack:
                callstop = _subterfugue.atcallstop(wpid, stopsig)
            else:
                callstop = stopsig == signal.SIGTRAP | 0x80

            if not callstop:
                sig = trace_signal(wpid, flags, tricklist, stopsig)
                if (sig == signal.SIGSTOP or sig == signal.SIGTSTP
                        or sig == signal.SIGTTIN or sig == signal.SIGTTOU):
                    # FIX: more needed for ~SIGSTOP case
Example #13
0
def trace_syscall_after(pid, flags, tricklist, call, eax):
    result = eax
    state = flags['state']
    call_changes = flags['call_changes']
    #del flags['call_changes']		 # ?

    # FIX: copy/reverse slow?
    tricklist = tricklist[:]

    # do callafters for tricks we did callbefores on, in reverse order,
    # minus the annulled trick (if any)
    if flags.has_key('annul'):
        result, annultrick = flags['annul']
        assert isinstance(result,
                          types.IntType), "oops: waitsuspend not cleared?"
        del flags['annul']
        call = call_changes[annultrick]
        while tricklist and tricklist.pop()[0] != annultrick:
            pass
    elif flags.has_key('sigreturn'):
        # we have to do this because ORIG_EAX somehow gets stomped by the
        # sigreturn calls.  maybe this is a kernel bug?
        call = flags['sigreturn']
        del flags['sigreturn']
    tricklist.reverse()

    memory = getMemory(pid)

    for trick, callmask, signalmask in tricklist:
        call = call_changes.get(trick, call)
        if (not callmask or callmask.has_key(call)) \
                                         and trick.is_enabled(pid):
            r = trick.callafter(pid, call, result, state.get(trick))
            if r != None:
                result = r
            memory.pop(trick)

    assert memory.empty()  # all momentary changes got popped

    if result != eax:
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, EAX, result)
        ptrace.pokeuser(pid, EAX, result)

    # undo any changes to child's args made on entry
    # XXX: does this go here?
    for n, arg in flags.get('args_delta', []):
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, 4 * n, arg)
        ptrace.pokeuser(pid, 4 * n, arg)
    call_save = flags.get('call_delta', -1)
    if call_save >= 0:
        if debug():
            print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, call_save)
        ptrace.pokeuser(pid, ORIG_EAX, call_save)

    # could continue child hereabouts
    ptrace.syscall(pid, 0)

    if flags.has_key('call_delta'):
        del flags['call_delta']
    if flags.has_key('args_delta'):
        del flags['args_delta']
    del flags['insyscall']
Example #14
0
        if isinstance(call, types.StringType):
            callno = syscallmap.lookup_number(call)
        else:
            callno = call

        try:
            if debug():
                print "ptrace.pokeuser(%s, %s, %s)" % (pid, ORIG_EAX, callno)
            ptrace.pokeuser(pid, ORIG_EAX, callno)
            flags['call_delta'] = scno
        except OSError, e:
            # FIX: do something better here
            sys.exit('panic: call alter failed in trick %s (%s)' % (trick, e))

    # could continue child hereabouts
    ptrace.syscall(pid, 0)

    flags['state'] = state
    flags['insyscall'] = 1
    if flags.has_key('newchild'):
        assert call == 'clone'
        newppid, tag = flags['newchild']  # FIX: better way to pass these back?
        del flags['newchild']
        # XXX: deep copy causes a problem?  CHECK THIS
        f = copy.copy(flags)
        f['newchildflags'] = {}
        f['children'] = []
        if newppid == pid:
            f['parent'] = pid
        f['exit_signal'] = args[0] & clone.CSIGNAL
        return (newppid, tag, f)