Ejemplo n.º 1
0
def send_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    Send call entry handler that always replays. It does several 
    things:
    1. Peek ECX register for system call parametrs
    2. Validate sockfd and message length
    3. Noop out the current syscall
    4. Set return value

    Checks:
    0: int sockfd: file descriptor or sending socket
    2: size_t len: length of const void *buf

    Sets:

  <Returns>
    None

  """
    logging.debug('Entering send entry handler')
    ecx = util.cint.peek_register(pid, util.cint.ECX)
    params = util.extract_socketcall_parameters(pid, ecx, 3)
    util.validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    util.validate_integer_argument(pid, syscall_object, 2, 2, params=params)
    trace_fd = int(syscall_object.args[0].value)
    # TODO: compare trace fd against execution fd????
    util.noop_current_syscall(pid)
    util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 2
0
def times_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    times call entry handler that always replays. It does several things:
    1. Noop out the current system call
    2. Populate the tms structure
    3. Set the return value
    
    Checks: 
    nothing

    Sets: 
    contents of the structure passed as a parameter
    errno

  <Returns>
    None

  """
    logging.debug('Entering times entry handler')
    util.noop_current_syscall(pid)
    if syscall_object.args[0].value != 'NULL':
        logging.debug('Got times() call with out structure supplied')
        addr = util.cint.peek_register(pid, util.cint.EBX)
        utime = int(syscall_object.args[0].value.split('=')[1])
        logging.debug('utime: %d', utime)
        stime = int(syscall_object.args[1].value.split('=')[1])
        logging.debug('stime: %d', stime)
        cutime = int(syscall_object.args[2].value.split('=')[1])
        logging.debug('cutime: %d', cutime)
        cstime = int(syscall_object.args[3].value.split('=')[1].rstrip('}'))
        logging.debug('cstime: %d', cstime)
        util.cint.populate_tms_structure(pid, addr, utime, stime, cutime,
                                         cstime)
    util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 3
0
def time_forger(pid):
    """
  <Purpose>
    Forge a time() call based on injected state.

    Checks:
    Nothing

    Sets:
    return value: The time or -1 (error)
    0:The the value of the integer pointed to by 0, if not NULL
    errno

  <Returns>
    None

  """
    logging.debug('Forging time call')
    t = util.cint.injected_state['times'][-1]
    times = util.cint.injected_state['times']
    new_t = t + _get_avg_time_result_delta(times)
    util.cint.injected_state['times'].append(new_t)
    syscall_object = lambda: None
    syscall_object.name = 'time'
    syscall_object.ret = []
    syscall_object.ret.append(t)
    addr = util.cint.peek_register(pid, util.cint.EBX)
    if addr != 0:
        util.cint.populate_unsigned_int(pid, addr, t)
    util.noop_current_syscall(pid)
    util.apply_return_conditions(pid, syscall_object)
    # Back up one system call we passed it when we decided to forge this
    # call
    util.cint.syscall_index -= 1
Ejemplo n.º 4
0
def gettimeofday_forger(pid):
    """
  <Purpose>
    Forge a gettimeofday call based on injected state

    Checks:
    1: struct timezone *tz

    Sets:
    return value
    errno

  <Returns>
    None

  """
    logging.debug('Forging gettimeofday call')
    timezone_addr = util.cint.peek_register(pid, util.cint.ECX)
    if timezone_addr != 0:
        raise NotImplementedError(
            'Cannot forge gettimeofday() with a timezone')
    time_addr = util.cint.peek_register(pid, util.cint.EBX)
    seconds_times = [
        x['seconds'] for x in util.cint.injected_state['gettimeofdays']
    ]
    microseconds_times = [
        x['microseconds'] for x in util.cint.injected_state['gettimeofdays']
    ]
    if not seconds_times and not microseconds_times:
        seconds_delta = _get_avg_time_result_delta(seconds_times)
        microseconds_delta = _get_avg_time_result_delta(microseconds_times)
        last_seconds = util.cint.injected_state['gettimeofdays'][-1]['seconds']
        last_microseconds = util.cint.injected_state['gettimeofdays'][-1][
            'microseconds']
        seconds = last_seconds + seconds_delta
        microseconds = last_microseconds + microseconds_delta
    else:
        seconds = int(time.time())
        microseconds = 0
    util.cint.injected_state['gettimeofdays'].append({
        'seconds':
        seconds,
        'microseconds':
        microseconds
    })
    logging.debug('Using seconds: %d microseconds: %d', seconds, microseconds)
    syscall_object = lambda: None
    syscall_object.name = 'gettimeofday'
    syscall_object.ret = []
    syscall_object.ret.append(0)
    util.noop_current_syscall(pid)
    util.cint.populate_timeval_structure(pid, time_addr, seconds, microseconds)
    util.apply_return_conditions(pid, syscall_object)
    # Back up one system call we passed it when we decided to forge this
    # call
    util.cint.syscall_index -= 1
Ejemplo n.º 5
0
def sendmmsg_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    sendmmsg call entry handler that replays based on trace sockfd.
    It does several things:
    1. Validate sockfd
    2. Determine replay based on trace sockfd
    3. Noop out the current system call if replay is necessary
    4. Check return value to be successful when replaying, and retrieve
    messages
    5. Extract socketcall parameters, and retrieve address
    6. TODO

    Checks:
    0: int sockfd: file descriptor of transmitting file descriptor

    Sets:
    return value
    errno

  <Returns>
    None
  
  """
    logging.debug('Entering sendmmsg entry handler')
    sockfd_from_trace = syscall_object.args[0].value
    util.validate_integer_argument(pid, syscall_object, 0, 0)
    if should_replay_based_on_fd(sockfd_from_trace):
        logging.debug('Replaying this sytem call')
        util.noop_current_syscall(pid)
        if syscall_object.ret[0] != -1:
            logging.debug('Got successful sendmmsg call')
            number_of_messages = syscall_object.ret[0]
            if syscall_id == 102:
                p = util.cint.peek_register(pid, util.cint.ECX)
                params = util.extract_socketcall_parameters(pid, p, 4)
                addr = params[1]
            else:
                addr = util.cint.peek_register(pid, util.cint.ECX)
            logging.debug('Number of messages %d', number_of_messages)
            logging.debug('Address of buffer %x', addr & 0xffffffff)
            lengths = [
                int(syscall_object.args[x].value.rstrip('}'))
                for x in range(6, (number_of_messages * 6) + 1, 6)
            ]
            logging.debug('Lengths: %s', lengths)
            util.cint.write_sendmmsg_lengths(pid, addr, number_of_messages,
                                             lengths)
        else:
            logging.debug('Got unsuccessful sendmmsg call')
        util.apply_return_conditions(pid, syscall_object)
    else:
        logging.debug('Not replaying this system call')
        swap_trace_fd_to_execution_fd(pid, 0, syscall_object)
Ejemplo n.º 6
0
def fadvise64_64_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering fadvise_64_64 entry handler')
    validate_integer_argument(pid, syscall_object, 0, 0)
    validate_integer_argument(pid, syscall_object, 1, 1)
    validate_integer_argument(pid, syscall_object, 2, 2)
    if should_replay_based_on_fd(int(syscall_object.args[0].value)):
        logging.debug('Replaying this system call')
        noop_current_syscall(pid)
        apply_return_conditions(pid, syscall_object)
    else:
        logging.debug('Not replaying this system call')
Ejemplo n.º 7
0
def utimensat_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    utimensat call entry handler that always replays. It does
    several things:
    1. Check if AT_FDCWD flag was passed, if not, validate
    flag passed
    2. Noop out the current system call
    
    TODO: replay execution behavior

  <Returns>
    None

  """
    logging.debug('Entering utimensat entry handler')
    if syscall_object.args[0].value != 'AT_FDCWD':
        util.validate_integer_argument(pid, syscall_object, 0, 0)
    util.noop_current_syscall(pid)
    logging.debug('Replaying this system call')
    # This code is commented out because I don't think these are out addresses.
    # That is, the kernel doesn't modify anything in the array.  This is a
    # "return success" situation.
    #timespec0_addr = util.cint.peek_register_unsigned(pid, util.cint.EDX)
    #timespec1_addr = timespec0_addr + 8
    #logging.debug('Timespec 0 addr: %x', timespec0_addr)
    #logging.debug('Timespec 1 addr: %x', timespec1_addr)
    #timespec0_seconds = syscall_object.args[2].value
    #timespec0_seconds = int(timespec0_seconds.strip('[]{}'))
    #timespec0_nseconds = syscall_object.args[3].value[0]
    #timespec0_nseconds = int(timespec0_nseconds.rstrip('[]{}'))
    #logging.debug('Timespec0 seconds: %d nseconds: %d',
    #            timespec0_seconds,
    #            timespec0_nseconds)
    #timespec1_seconds = syscall_object.args[4].value
    #timespec1_seconds = int(timespec1_seconds.strip('[]{}'))
    #timespec1_nseconds = syscall_object.args[5].value
    #timespec1_nseconds = int(timespec1_nseconds.rstrip('[]{}'))
    #logging.debug('Timespec1 seconds: %d nseconds: %d',
    #            timespec1_seconds,
    #            timespec1_nseconds)
    #util.cint.populate_timespec_structure(pid,
    #                               timespec0_addr,
    #                               timespec0_seconds,
    #                               timespec0_nseconds)
    #util.cint.populate_timespec_structure(pid,
    #                               timespec1_addr,
    #                               timespec1_seconds,
    #                               timespec1_nseconds)
    util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 8
0
def set_tid_address_exit_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering set_tid_address_exit_handler')
    addr_from_trace = int('0x' + syscall_object.args[0].value, 16)
    tid_from_trace = int(syscall_object.ret[0])
    # We have to use the address from the trace here for two reasons:
    #  1. We already confirmed at the traces matches execution in this regard
    #  in the entry handler
    #  2. Registers have been trashed by this point so we don't have any choice
    logging.debug('Address from trace: %x', addr_from_trace)
    logging.debug('TID from trace: %d', tid_from_trace)
    # We place the TID from the trace into the appropriate memory location
    # so future references are correct
    cint.populate_unsigned_int(pid, addr_from_trace, tid_from_trace)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 9
0
def timer_gettime_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    timer_gettime call entry handler that replays based on return value.
    It does several things:
    1. Check if the return value is successful (0)
    2. Check if the timer_id from trace is different from execution
    4. Retrieve the addr parameter from the ECX register
    5. Populate the itimerspec structure
    6. Noop out the current system call
    7. Set the return value

    Checks:
    0: timer_t timerid
    return value

    Sets:
    3: struct itimerspec *old_value
    return value
    errno

  <Returns>
    None

  """
    logging.debug("Entering the timer_gettime entry handler")
    if syscall_object.ret[0] == -1:
        raise NotImplementedError('Unsuccessful calls not implemented')
    else:
        logging.debug('Got successful timer_gettime call')
        logging.debug('Replaying this system call')

        # these should be the same probably?
        timer_id_from_trace = int(syscall_object.args[0].value[0].strip('0x'))
        timer_id_from_execution = int(
            util.cint.peek_register(pid, util.cint.EBX))

        if timer_id_from_trace != timer_id_from_execution:
            raise util.ReplayDeltaError("Timer id ({}) from execution "
                                        "differs from trace ({})".format(
                                            timer_id_from_execution,
                                            timer_id_from_trace))

        addr = util.cint.peek_register(pid, util.cint.ECX)
        itimerspec_starting_index = 1
        timer_extract_and_populate_itimerspec(syscall_object, pid, addr,
                                              itimerspec_starting_index)
        util.noop_current_syscall(pid)
        util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 10
0
def uname_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering uname handler')
    args = {
        x.value.split('=')[0]: x.value.split('=')[1]
        for x in syscall_object.args
    }
    args = {x.strip('{}'): y.strip('"{}') for x, y in args.iteritems()}
    logging.debug(args)
    address = cint.peek_register(pid, cint.EBX)
    noop_current_syscall(pid)
    cint.populate_uname_structure(pid, address, args['sysname'],
                                  args['nodename'], args['release'],
                                  args['version'], args['machine'],
                                  args['domainname'])
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 11
0
def recv_subcall_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    recv subcall entry handler that replays based on fd. It does several 
    things:
    1. Retrieve parameters of socketcall from ECX register 
    2. Validate sockfd and length arguments.
    3. Determine if replay is necessary by fd from trace
    If replay: 
      4. Noop the current system call
      5. Retrieve buffer pointer address and cleaned up
         data in the buffer
      6. Use buffer address and retrieved data to populate the buffer
      7. Sets the return value
    If not replayed:
      4. Swap trace fd to execution

  Checks:
  0: int sockfd
  2: size_t len

  Sets:
  1: void *buf: buffer representing data received
  return value
  errno

  <Returns>
    None
  """
    p = util.cint.peek_register(pid, util.cint.ECX)
    params = util.extract_socketcall_parameters(pid, p, 4)
    # We don't check params[1] because it is the address of an empty buffer
    # We don't check params[3] because it is a flags field
    util.validate_integer_argument(pid, syscall_object, 0, 0, params)
    util.validate_integer_argument(pid, syscall_object, 2, 2, params)
    # Decide if we want to replay this system call
    fd_from_trace = syscall_object.args[0].value
    if should_replay_based_on_fd(fd_from_trace):
        logging.info('Replaying this system call')
        util.noop_current_syscall(pid)
        buffer_address = params[1]
        data = util.cleanup_quotes(syscall_object.args[1].value)
        data = data.decode('string_escape')
        util.cint.populate_char_buffer(pid, buffer_address, data)
        util.apply_return_conditions(pid, syscall_object)
    else:
        logging.info("Not replaying this system call")
        swap_trace_fd_to_execution_fd(pid, 0, syscall_object, params_addr=p)
Ejemplo n.º 12
0
def gettimeofday_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    gettimeofday call entry handler that replays based on the return value.
    It does several things:
    1. Check if the return value is successful (0)
    2. Noop out the current system call
    3. Populate the timeval structur
    4. Set the return value

    Checks:
    return value

    Sets:
    0: struct timeval *tv
    return value
    errno

  <Returns>
    None

  """
    logging.debug('Entering gettimeofday entry handler')
    if syscall_object.ret[0] == -1:
        raise NotImplementedError('Unsuccessful calls not implemented')
    elif syscall_object.args[2].value != 'NULL':
        raise NotImplementedError('time zones not implemented')
    else:
        util.noop_current_syscall(pid)
        addr = util.cint.peek_register_unsigned(pid, util.cint.EBX)
        seconds = syscall_object.args[0].value.strip('{}, ')
        # gettimeofday() call might have the tv_sec and tv_usec labels in the
        # output structure.  If it does, we need to split() it off.
        if 'tv_sec' in seconds:
            seconds = seconds.split('=')[1]
        seconds = int(seconds)
        # gettimeofday() call might have the tv_sec and tv_usec labels in the
        # output structure.  If it does, we need to split() it off.
        microseconds = syscall_object.args[1].value.strip('{}')
        if 'tv_usec' in microseconds:
            microseconds = microseconds.split('=')[1]
        microseconds = int(microseconds)
        logging.debug('Address: %x', addr)
        logging.debug('Seconds: %d', seconds)
        logging.debug('Microseconds: %d', microseconds)
        logging.debug('Populating timeval structure')
        util.cint.populate_timeval_structure(pid, addr, seconds, microseconds)
        util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 13
0
def timer_create_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    timer_create call entry handler that replays based on the return value.
    It does several things:
    1. Check to see if return value is successful (0)
    2. Check sigevent to be SIGEV_NONE
    3. Retrieve timerid address from EDX register
    4. Populate the timer_t structure with parameters
    5. Noop the current system call
    5. Set the return value

    Checks:
    1: struct sigevent *sevp: how to noify the expiration of the timer
    2. timer_t *timerid: returned timer_t pointer that identifies the timer.
    return value

    Sets:
    2: timer_t *timerid
    return value
    errno

  <Returns>
    None

  """
    logging.debug("Entering the timer_create entry handler")
    if syscall_object.ret[0] == -1:
        raise NotImplementedError('Unsuccessful calls not implemented')
    else:
        # only SIGEV_NONE is supported as other sigevents can't be replicated as of now
        sigev_type = syscall_object.args[3].value.strip()
        logging.debug("Sigevent type: %s", str(sigev_type))

        if sigev_type != 'SIGEV_NONE':
            raise NotImplementedError("Sigevent type %s is not supported" %
                                      (sigev_type))

        addr = util.cint.peek_register(pid, util.cint.EDX)
        logging.debug('timerid address: %x', addr)

        timerid = int(syscall_object.args[-1].value.strip('{}'))
        logging.debug(str(timerid))

        util.cint.populate_timer_t_structure(pid, addr, timerid)

        util.noop_current_syscall(pid)
        util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 14
0
def timer_delete_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    timer_delete call entry handler.

    TODO: add functionality:
      * check return value
      * check timer_id in trace and execution

  <Returns>
    None

  """
    logging.debug("Entering the timer_delete entry handler")
    util.noop_current_syscall(pid)
    util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 15
0
def recvfrom_subcall_entry_handler(syscall_id, syscall_object, pid):
    p = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, p, 6)
    validate_integer_argument(pid, syscall_object, 0, 0, params)
    validate_integer_argument(pid, syscall_object, 2, 2, params)
    # We don't check params[1] because it is the address of an empty buffer
    # We don't check params[3] because it is a flags field
    # We don't check params[4] because it is the address of an empty buffer
    # We don't check params[5] because it is the address of a length
    data_buf_addr_e = params[1]
    data_buf_length_e = params[2]
    sockaddr_addr_e = params[4]
    sockaddr_length_addr_e = params[5]

    fd_t = syscall_object.args[0].value
    data = syscall_object.args[1].value
    data = cleanup_quotes(data)
    data = data.decode('string_escape')
    sockfields = syscall_object.args[4].value
    port = int(sockfields[1].value)
    ip = sockfields[2].value
    sockaddr_length_t = int(syscall_object.args[5].value.strip('[]'))

    ret_val = int(syscall_object.ret[0])

    # Decide if we want to replay this system call
    if should_replay_based_on_fd(fd_t):
        logging.info('Replaying this system call')
        noop_current_syscall(pid)
        if len(data) != ret_val:
            raise ReplayDeltaError('Decoded bytes length ({}) does not equal '
                                   'return value from trace ({})'.format(
                                       len(data), ret_val))
        cint.populate_char_buffer(pid, data_buf_addr_e, data)
        cint.populate_af_inet_sockaddr(pid, sockaddr_addr_e, port, ip,
                                       sockaddr_length_addr_e,
                                       sockaddr_length_t)
        buf = cint.copy_address_range(pid, data_buf_addr_e,
                                      data_buf_addr_e + data_buf_length_e)
        if buf[:ret_val] != data:
            raise ReplayDeltaError('Data copied by read() handler doesn\'t '
                                   'match after copy')
        apply_return_conditions(pid, syscall_object)
        print(cint.peek_register(pid, cint.EAX))
    else:
        logging.info('Not replaying this system call')
        swap_trace_fd_to_execution_fd(pid, 0, syscall_object, params_addr=p)
Ejemplo n.º 16
0
def sched_getaffinity_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering sched_getaffinity entry handler')
    # We don't validate the first argument because the PID,
    # which is different for some reason?
    validate_integer_argument(pid, syscall_object, 1, 1)
    try:
        cpu_set_val = int(syscall_object.args[2].value.strip('{}'))
    except ValueError:
        raise NotImplementedError('handler cannot deal with multi-value '
                                  'cpu_sets: {}'
                                  .format(syscall_object.args[2]))
    cpu_set_addr = cint.peek_register(pid, cint.EDX)
    logging.debug('cpu_set value: %d', cpu_set_val)
    logging.debug('cpu_set address: %d', cpu_set_addr)
    noop_current_syscall(pid)
    cint.populate_cpu_set(pid, cpu_set_addr, cpu_set_val)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 17
0
def getsockname_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: The socket file descriptor
    Sets:
    addr: a struct sockaddr populated with the requested information
    addrlen: length of the sockaddr struct being populated
    return value: 0 (success) or -1 (failure)
    errno

    Not Implemented:
    * Use address validator to check the addresses
    """
    logging.debug('Entering getsockname handler')
    # Pull out the info that we can check
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 3)
    # We don't compare params[1] because it is the address of an empty buffer
    # We don't compare params[2] because it is the address of an out parameter
    # Get values from trace for comparison
    fd_from_trace = syscall_object.args[0].value
    validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    # Decide if this is a file descriptor we want to deal with
    noop_current_syscall(pid)
    if syscall_object.ret[0] != -1:
        logging.debug('Got successful getsockname call')
        addr = params[1]
        length_addr = params[2]
        length = int(syscall_object.args[2].value.strip('[]'))
        logging.debug('Addr: %d', addr & 0xffffffff)
        logging.debug('Length addr: %d', length_addr & 0xffffffff)
        logging.debug('Length: %d', length)
        sockfields = syscall_object.args[1].value
        family = sockfields[0].value
        port = int(sockfields[1].value)
        ip = sockfields[2].value
        logging.debug('Family: %s', family)
        logging.debug('Port: %d', port)
        logging.debug('Ip: %s', ip)
        if family != 'AF_INET':
            raise NotImplementedError('getsockname only supports ' 'AF_INET')
        cint.populate_af_inet_sockaddr(pid, addr, port, ip, length_addr,
                                       length)
    else:
        logging.debug('Got unsuccessful getsockname call')
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 18
0
def ioctl_entry_handler(syscall_id, syscall_object, pid):
    """Always replay.
    Checks:
    0: int fd: the file descriptor being operated on
    Sets:
    The return value

    Special Action:
    does a variety of things depending on the supplied action


    """
    logging.debug('Entering ioctl handler')
    validate_integer_argument(pid, syscall_object, 0, 0)
    trace_fd = int(syscall_object.args[0].value)
    edx = cint.peek_register(pid, cint.EDX)
    logging.debug('edx: %x', edx & 0xffffffff)
    addr = edx
    noop_current_syscall(pid)
    if syscall_object.ret[0] != -1:
        cmd = syscall_object.args[1].value
        cmd_from_exe = cint.peek_register(pid, cint.ECX)
        _validate_ioctl_cmd(cmd, cmd_from_exe)

        # Alan: optimized ioctl handler
        ioctl_handlers = {
            'TCGETS': _tcgets_handler,
            'FIONREAD': _fionread_handler,
            'FIONBIO': _fionbio_handler,
            'TIOCGWINSZ': _tiocgwinsz_handler,
            'TIOCGPGRP': _tiocgpgrp_handler
            #'TCSETSW', _tcsetsw_handler),
            #'TIOCSWINSZ', _tiocswinsz_handler),
            #'TCSETSF', _tcsetsf_handler),
            #'TCSETS', _tcsets_handler),
            #'FIOCLEX', _fioclex_handler)
        }

        # transfer to handler
        try:
            ioctl_handlers[cmd](pid, addr, syscall_object)
        except KeyError:
            raise NotImplementedError("Unsupport ioctl call with %s flag", cmd)

    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 19
0
def socket_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: The domain of the socket
    Sets:
    return value: file descriptor of the new socket -1 (error)
        (added as replay file descriptor)
    errno

    Not Implemented:
    * Determine what is not implemented
    """
    logging.debug('Entering socket subcall entry handler')

    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 3)
    # Only PF_INET and PF_LOCAL socket calls are handled
    execution_is_PF_INET = (params[0] == cint.PF_INET)
    trace_is_PF_INET = (str(syscall_object.args[0]) == '[\'PF_INET\']')
    execution_is_PF_LOCAL = (params[0] == 1)  # define PF_LOCAL 1
    trace_is_PF_LOCAL = (str(syscall_object.args[0]) == '[\'PF_LOCAL\']')
    logging.debug('Execution is PF_INET: %s', execution_is_PF_INET)
    logging.debug('Trace is PF_INET: %s', trace_is_PF_INET)
    logging.debug('Exeuction is PF_LOCAL: %s', execution_is_PF_LOCAL)
    logging.debug('Trace is PF_LOCAL: %s', trace_is_PF_LOCAL)
    if execution_is_PF_INET != trace_is_PF_INET:
        raise ReplayDeltaError(
            'Encountered socket subcall with mismatch between '
            'execution protocol family and trace protocol family')
    if execution_is_PF_LOCAL != trace_is_PF_LOCAL:
        raise ReplayDeltaError(
            'Encountered socket subcall with mismatch between '
            'execution protocol family and trace protocol family')
    # Decide if we want to deal with this socket call or not
    if trace_is_PF_INET or \
       execution_is_PF_INET or \
       trace_is_PF_LOCAL or \
       execution_is_PF_LOCAL:
        noop_current_syscall(pid)
        fd = int(syscall_object.ret[0])
        logging.debug('File Descriptor from trace: %s', fd)
        apply_return_conditions(pid, syscall_object)
    else:
        logging.info('Ignoring non-PF_INET call to socket')
Ejemplo n.º 20
0
def timer_settime_entry_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    timer_settime call entry handler that replays based on the return value.
    It does several things:
    1. Check if the return value is successful (0)
    2. Check if old_value parameter is present.
    If old_value is present:
        3. Extract and populate the itimerspec structure
    3. Noop out the current system call
    5. Set the return value

    Checks:
    3: struct itimerspec *old_value
    return value

    Sets:
    3: struct itimerspec *old_value
    return value
    errno

  <Returns>
    None

  """
    logging.debug("Entering the timer_settime entry handler")
    if syscall_object.ret[0] == -1:
        raise NotImplementedError('Unsuccessful calls not implemented')
    else:
        logging.debug(str(syscall_object.args[-1]))
        old_value_present = syscall_object.args[-1].value != 'NULL'
        if old_value_present:
            logging.debug("Old value present, have to copy it into memory")

            addr = util.cint.peek_register(pid, util.cint.ESI)
            logging.debug('old_value address: %x', addr)

            itimerspec_starting_index = 6
            timer_extract_and_populate_itimerspec(syscall_object, pid, addr,
                                                  itimerspec_starting_index)

        util.noop_current_syscall(pid)
        util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 21
0
def accept_subcall_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: sockfd: the socket file descriptor
    Sets:
    return value: The file descriptor -1 (error)
    errno

    Not Implemented:
    * Implement a function to check null terminated strings to clean up this
      mess of checking
    """
    logging.debug('Checking if line from trace is interrupted accept')
    if syscall_object.ret[0] == '?':
        raise NotImplementedError('Interrupted accept()s not implemented')
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 3)
    sockaddr_addr = params[1]
    sockaddr_len_addr = params[2]
    fd_from_trace = syscall_object.args[0].value
    validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    # Decide if this is a system call we want to replay
    noop_current_syscall(pid)
    if syscall_object.ret[0] != -1 and syscall_object.args[1].value != 'NULL':
        sockfields = syscall_object.args[1].value
        family = sockfields[0].value
        port = int(sockfields[1].value)
        ip = sockfields[2].value
        sockaddr_length = int(syscall_object.args[2].value.strip('[]'))
        logging.debug('Family: %s', family)
        logging.debug('Port: %s', port)
        logging.debug('IP: %s', ip)
        logging.debug('sockaddr Length: %s', sockaddr_length)
        logging.debug('sockaddr addr: %x', sockaddr_addr & 0xffffffff)
        logging.debug('sockaddr length addr: %x',
                      sockaddr_len_addr & 0xffffffff)
        logging.debug('pid: %s', pid)
        cint.populate_af_inet_sockaddr(pid, sockaddr_addr, port, ip,
                                       sockaddr_len_addr, sockaddr_length)
    if syscall_object.ret[0] != -1:
        ret = syscall_object.ret[0]
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 22
0
def shutdown_subcall_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: sockfd: the socket file descriptor
    Sets:
    return value: 0 (success) or -1 (error)
    errno

    """
    logging.debug('Entering shutdown entry handler')
    # Pull out the info we can check
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 2)
    fd_from_trace = syscall_object.args[0].value
    validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    # TODO: We need to check the 'how' parameter here
    # Check to make sure everything is the same
    # Decide if we want to replay this system call
    noop_current_syscall(pid)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 23
0
def syscall_return_success_handler(syscall_id, syscall_object, pid):
    """
  <Purpose>
    Generic handler that does two things:
    1. Noop out the current system call
    2. Sets the return value from the current syscall_object
    Checks:
    Nothing

    Sets:
    return value: The return value specified in syscall_object
        (added as replay file descriptor)
    errno
  <Returns>
    None

  """
    logging.debug('Using default "return success" handler')
    util.noop_current_syscall(pid)
    util.apply_return_conditions(pid, syscall_object)
Ejemplo n.º 24
0
def connect_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: The socket file descriptor
    2: The length of the sockaddr structure pointed to by 1
    Sets:
    return value: file descriptor of the new socket -1 (error)
    errno

    Not Implemented:
    * Determine what is not implemented
    """

    logging.debug('Entering connect entry handler')
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 3)
    validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    validate_integer_argument(pid, syscall_object, 2, 2, params=params)
    trace_fd = int(syscall_object.args[0].value)
    noop_current_syscall(pid)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 25
0
def getpeername_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering getpeername handler')
    # Pull out the info that we can check
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 3)
    fd = params[0]
    # We don't compare params[1] because it is the address of an empty buffer
    # We don't compare params[2] because it is the address of an out parameter
    # Get values from trace for comparison
    fd_from_trace = syscall_object.args[0].value
    # Check to make sure everything is the same
    if fd != int(fd_from_trace):
        raise ReplayDeltaError(
            'File descriptor from execution ({}) '
            'does not match file descriptor from trace ({})'.format(
                fd, fd_from_trace))
    # Decide if this is a file descriptor we want to deal with
    noop_current_syscall(pid)
    if syscall_object.ret[0] != -1:
        logging.debug('Got successful getpeername call')
        addr = params[1]
        length_addr = params[2]
        length = int(syscall_object.args[2].value.strip('[]'))
        logging.debug('Addr: %d', addr)
        logging.debug('Length addr: %d', length_addr)
        logging.debug('Length: %d', length)
        sockfields = syscall_object.args[1].value
        family = sockfields[0].value
        port = int(sockfields[1].value)
        ip = sockfields[2].value
        logging.debug('Family: %s', family)
        logging.debug('Port: %d', port)
        logging.debug('Ip: %s', ip)
        if family != 'AF_INET':
            raise NotImplementedError('getpeername only ' 'supports AF_INET')
        cint.populate_af_inet_sockaddr(pid, addr, port, ip, length_addr,
                                       length)
    else:
        logging.debug('Got unsuccessful getpeername call')
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 26
0
def recv_subcall_entry_handler(syscall_id, syscall_object, pid):
    p = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, p, 4)
    # Pull out everything we can check
    fd_from_trace = syscall_object.args[0].value
    # We don't check params[1] because it is the address of an empty buffer
    # We don't check params[3] because it is a flags field
    # Check to make everything is the same
    validate_integer_argument(pid, syscall_object, 0, 0, params)
    validate_integer_argument(pid, syscall_object, 2, 2, params)
    # Decide if we want to replay this system call
    if should_replay_based_on_fd(fd_from_trace):
        logging.info('Replaying this system call')
        noop_current_syscall(pid)
        buffer_address = params[1]
        data = cleanup_quotes(syscall_object.args[1].value)
        data = data.decode('string_escape')
        cint.populate_char_buffer(pid, buffer_address, data)
        apply_return_conditions(pid, syscall_object)
    else:
        swap_trace_fd_to_execution_fd(pid, 0, syscall_object, params_addr=p)
        logging.info('Not replaying this system call')
Ejemplo n.º 27
0
def getresgid_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering getresgid entry handler')
    ruid = int(syscall_object.args[0].value.strip('[]'))
    euid = int(syscall_object.args[0].value.strip('[]'))
    suid = int(syscall_object.args[0].value.strip('[]'))
    ruid_addr = cint.peek_register(pid, cint.EBX)
    euid_addr = cint.peek_register(pid, cint.ECX)
    suid_addr = cint.peek_register(pid, cint.EDX)

    logging.debug('ruid: %d', ruid)
    logging.debug('euid: %d', euid)
    logging.debug('suid: %d', suid)

    logging.debug('ruid addr: %x', ruid_addr & 0xffffffff)
    logging.debug('ruid addr: %x', euid_addr & 0xffffffff)
    logging.debug('ruid addr: %x', suid_addr & 0xffffffff)
    noop_current_syscall(pid)

    cint.populate_unsigned_int(pid, ruid_addr, ruid)
    cint.populate_unsigned_int(pid, euid_addr, euid)
    cint.populate_unsigned_int(pid, suid_addr, suid)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 28
0
def getrlimit_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering getrlimit handler')
    cmd = syscall_object.args[0].value[0]
    if cmd != 'RLIMIT_STACK':
        raise Exception('Unimplemented getrlimit command {}'.format(cmd))
    addr = cint.peek_register(pid, cint.ECX)
    rlim_cur = syscall_object.args[1].value.strip('{')
    rlim_cur = rlim_cur.split('=')[1]
    if rlim_cur.find('*') == -1:
        raise Exception('Unimplemented rlim_cur format {}'.format(rlim_cur))
    rlim_cur = int(rlim_cur.split('*')[0]) * int(rlim_cur.split('*')[1])
    rlim_max = syscall_object.args[2].value.strip('}')
    rlim_max = rlim_max.split('=')[1]
    if rlim_max != 'RLIM_INFINITY':
        raise Exception('Unlimited rlim_max format {}'.format(rlim_max))
    rlim_max = 0x7fffffffffffffff
    logging.debug('rlim_cur: %s', rlim_cur)
    logging.debug('rlim_max: %x', rlim_max)
    logging.debug('Address: %s', addr)
    noop_current_syscall(pid)
    cint.populate_rlimit_structure(pid, addr, rlim_cur, rlim_max)
    apply_return_conditions(pid, syscall_object)
Ejemplo n.º 29
0
def prlimit64_entry_handler(syscall_id, syscall_object, pid):
    logging.debug('Entering prlimit64 entry handler')
    validate_integer_argument(pid, syscall_object, 0, 0)
    have_new_limit = False
    have_old_limit = False
    if(syscall_object.args[2].value != 'NULL'
       and syscall_object.args[3].value != 'NULL'
       and syscall_object.args[4].value == 'NULL'):
            logging.debug('We have a new limit')
            have_new_limit = True
    elif(syscall_object.args[2].value == 'NULL'
         and syscall_object.args[3].value != 'NULL'
         and syscall_object.args[4].value != 'NULL'):
        logging.debug('We have an old limit')
        have_old_limit = True
    if have_new_limit and not have_old_limit:
        if syscall_object.args[1].value != 'RLIMIT_CORE':
            raise NotImplementedError('prlimit commands with a new limit only '
                                      'support RLIMIT_CORE')
        noop_current_syscall(pid)
        apply_return_conditions(pid, syscall_object)
    elif not have_new_limit and have_old_limit:
        if syscall_object.args[1].value != 'RLIMIT_NOFILE':
            raise NotImplementedError('prlimit commands other than '
                                      'RLIMIT_NOFILE are not supported')
        rlim_cur = int(syscall_object.args[3].value.split('=')[1])
        logging.debug('rlim_cur: %d', rlim_cur)
        rlim_max = syscall_object.args[4].value.split('=')[1]
        rlim_max = rlim_max.split('*')
        rlim_max = int(rlim_max[0]) * int(rlim_max[1].strip('}'))
        logging.debug('rlim_max: %d', rlim_max)
        addr = cint.peek_register(pid, cint.ESI)
        logging.debug('addr: %x', addr & 0xFFFFFFFF)
        noop_current_syscall(pid)
        cint.populate_rlimit_structure(pid, addr, rlim_cur, rlim_max)
        apply_return_conditions(pid, syscall_object)
    else:
        raise NotImplementedError('prlimit64 calls with both a new and old '
                                  'limit are not supported')
Ejemplo n.º 30
0
def setsockopt_entry_handler(syscall_id, syscall_object, pid):
    """Replay Always
    Checks:
    0: sockfd: the socket file descriptor
    Sets:
    optval: out parameter
    return value: 0 (success) or -1 (error)
    errno

    Not Implemented: More checking

    """
    logging.debug('Entering setsockopt handler')
    ecx = cint.peek_register(pid, cint.ECX)
    params = extract_socketcall_parameters(pid, ecx, 5)
    fd_from_trace = int(syscall_object.args[0].value)
    optval_addr = params[3]
    # We don't check param[3] because it is an address of an empty buffer
    # We don't check param[4] because it is an address of an empty length
    validate_integer_argument(pid, syscall_object, 0, 0, params=params)
    noop_current_syscall(pid)
    apply_return_conditions(pid, syscall_object)