Ejemplo n.º 1
0
static GObjectClass *
get_threshold_class (GObject *obj)
{
	GType gtype = G_TYPE_FROM_INSTANCE (obj);
	while (HAS_PREFIX (g_type_name (gtype)))
		gtype = g_type_parent (gtype);
	GObjectClass *klass = g_type_class_peek (gtype);
	if (klass == NULL) klass = g_type_class_ref (gtype);
	return klass;
}
Ejemplo n.º 2
0
enum translation_state action_jmp(struct translate *ts) {
  unsigned char *addr = ts->cur_instr;

  unsigned char *original_addr = addr;
  
  PRINT_DEBUG("original_addr=%x / addr=%x\n", original_addr, addr);  
  
  unsigned char* transl_addr = ts->transl_instr;
  int length = ts->next_instr - ts->cur_instr;

  PRINT_DEBUG_FUNCTION_START("action_jmp(*addr=%p, *transl_addr=%p, length=%i)",
                             addr, transl_addr, length);
#if defined(FBT_STATISTIC)
  fbt_nr_translated_jmp++;
#endif

  /* read call argument (either 8bit or 32bit offset) and add EIP (EIP = addr +
     length) to argument --> absolute target address = addr + length + offset */
  #if defined(ASSERTIONS)
  assert(!HAS_PREFIX(*addr)); /* no prefixes allowed */
  #endif

  int32_t jump_target=0;
  if (*addr == 0xE9) {
    /* 32bit offset */
    jump_target = *((int32_t*)(addr + 1)) + (int32_t)original_addr + length;
    PRINT_DEBUG("jump_target = %x + %x + %x", *(int32_t*)(addr + 1), original_addr, length);
  } else {
    /* our argument is only an 8bit offset */
    jump_target = (int32_t)(*((char*)(addr + 1)) + original_addr + length);
  }
  
  PRINT_DEBUG("original jmp_target: %p", (void*)jump_target);

/* It seems that some binaries like /bin/ls uses direct jmp's into plt instead of direct calls. */
/* We need to handle and inline this jmps correctly. */
#if defined(INLINE_PLT_CALLS)
/* Check if call targets plt section and resolve destination address */
unsigned long resolved_addr = sl_resolve_plt_call(jump_target, ts->tld->dso_objects);
if (resolved_addr != jump_target) {
  /* PLT call, check transfer and inline it */
  #if defined(VERIFY_CFTX)

  #if defined(ENABLE_TRANSLATION_TIME_SYMBOL_LOOKUP)
  struct sh_symbol* symbol = fbt_find_symbol(ts->tld, addr);
  fbt_check_transfer(ts->tld, original_addr, (unsigned char*)&resolved_addr, CFTX_CALL_IND, symbol); /* treat like an indirect call */
  #else
  fbt_check_transfer(ts->tld, original_addr, (unsigned char*)&resolved_addr, CFTX_CALL_IND); /* treat like an indirect call */
  #endif
  
  #endif /* VERIFY_CFTX */
  
  jump_target = resolved_addr;
}
#endif
/* End - PLT Jmps inlining! */

  /* check if the target is already translated; if it is not, do so now */
  void *transl_target = fbt_ccache_find(ts->tld, (void*)jump_target);
  if (transl_target == NULL) {
    /* we still have to translate the call target */
    PRINT_DEBUG_FUNCTION_END("-> open, transl_length=0");
    /* no need to actually jump
      simply change the next instr pointer to the first instr of the function
      this will put the body of the function right as the next instr in the
      translated code */
    ts->next_instr = (unsigned char*)jump_target;
    /* put the target into the tcache so later jumps can use the translated
       code */
    #ifndef TRACK_BASIC_BLOCKS
    //fbt_ccache_add_entry(ts->tld, (void*)jump_target, ts->transl_instr);
    #endif
    
    return OPEN;
  }

  PRINT_DEBUG("translated jmp_target: %p", transl_target);

  /* write: jmp */
  #if defined(TRACK_CFTX)
  struct control_flow_transfer cft = {
    .location = transl_addr + 1,
    .original = addr
  };
  fbt_store_cftx(ts->tld, &cft);
  #endif /* TRACK_CFTX */

  JMP_REL32(transl_addr, (int32_t)transl_target);

  PRINT_DEBUG_FUNCTION_END("-> close, transl_length=%i",
                           transl_addr - ts->transl_instr);
  ts->transl_instr = transl_addr;
  return CLOSE;
}

enum translation_state action_jmp_indirect(struct translate *ts) {
  unsigned char *addr = ts->cur_instr;
  unsigned char* transl_addr = ts->transl_instr;
  unsigned char *first_byte_after_opcode = ts->first_byte_after_opcode;
  int length = ts->next_instr - ts->cur_instr;

  PRINT_DEBUG_FUNCTION_START("action_jmp_indirect(*addr=%p, *transl_addr=%p, " \
                             "length=%i)", addr, transl_addr, length);

#if defined(FBT_STATISTIC)
  fbt_nr_translated_jmp_ind++;
#endif

  #if defined(SECURITY_METRICS_AND_STATS) && defined(VERIFY_CFTX)
  	struct dso_chain *cur = ts->tld->dso_objects;
  	long ret;
  	
		while (cur != 0) {
			/* is the pointer in the current dso? */
            if (PTR_IN_REGION(addr, cur->baseaddr, cur->endaddr-cur->baseaddr)) {
			    FBT_UNPROT_DATA(cur, sizeof(struct dso_chain), ret, "action_jmp_indirect: unprotect dso failed.");
			    if(cur->nr_ijmps >= ICF_TABLES_MAX_ENTRIES) {
						llprintf("ERROR: ijmps table out of space (fbt_actions.c), nr of entries: %d\n", cur->nr_ijmps);
						fbt_exit_suicide(45);
				}
				
				int i = 0;
				int found = 0;
				/* let's see if we already have this ICF in the list */
			    for(i = 0; i < cur->nr_ijmps; i++) {
					if(addr == cur->ijmps[i]) {
						found = 1;
						break;
					}
				}
				if(!found) {
					cur->ijmps[cur->nr_ijmps] = addr;
					cur->nr_ijmps++;
				}
				
				/* TODO: make this thread safe! */
				//FBT_PROT_DATA(cur, sizeof(struct dso_chain), ret, "action_jmp_indirect: protect dso failed.");
			   break;
			}
			cur = cur->next;
		}
	
  #endif /* defined(SECURITY_METRICS_AND_STATS) && defined(VERIFY_CFTX) */
  
  if (ts->num_prefixes != 0) {
    /* no prefixes allowed */
    fbt_suicide_str("No prefixes handled in action_jmp_indirect! " \
                    "(fbt_actions.c)\n");
  }

  /* this is a fast version of the ind jmp - handoptimized assembler code
   * which does a fast lookup in the hashtable and dispatches if it hits
   * otherwise it recovers to an indirect jump
   */

  /**
   * pushl $target
   * jmpl  tld->ind_jump_trampoline
   */

  /* write: push indirect target */
  *transl_addr++ = 0xFF;

  /*
   * 0xFF expects a ModR/M byte following the opcode
   * The bits 3-5 are part of the opcode (opcode extension into ModR/M byte),
   * so we copy the ModR/M byte, but modify the opcode extension to 110
   */
  *transl_addr++ = (*first_byte_after_opcode & 0xC7) | 0x30;

  //llprintf("action_jmp_indirect: %x\n", addr);

  /* if there follows a displacement copy this to the ccf */
  if (length > 2) {
    fbt_memcpy(transl_addr, (addr + 2), length - 2);
    //llprintf("action_jmp_indirect length > 2: %x\n", addr + 2);
    transl_addr += length - 2;
  }

#if defined(VERIFY_CFTX)

#if defined(VERIFY_CFTX_ENABLE_IJMP_LSYMOPT) || defined(ENABLE_TRANSLATION_TIME_SYMBOL_LOOKUP)
struct sh_symbol* symbol = fbt_find_symbol(ts->tld, addr);
#endif

#if defined(VERIFY_CFTX_ENABLE_IJMP_LSYMOPT)
if(symbol && symbol->start && symbol->size) {

  BEGIN_ASM(transl_addr)
    movl %esp, {ts->tld->stack-2}
    movl ${ts->tld->stack-2}, %esp
Ejemplo n.º 3
0
/*! \brief Lease file parser.  The parser can only read ISC DHCPD
 * dhcpd.leases file format.  */
int parse_leases(void)
{
	FILE *dhcpd_leases;
	char *line, *ipstring, macstring[20];
	union ipaddr_t addr;
	struct stat lease_file_stats;
	bool ethernets = false;
	struct leases_t *lease;

	dhcpd_leases = fopen(config.dhcpdlease_file, "r");
	if (dhcpd_leases == NULL) {
		err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file);
	}
#ifdef HAVE_POSIX_FADVISE
# ifdef POSIX_FADV_WILLNEED
	posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_WILLNEED);
	if (errno) {
		err(EXIT_FAILURE, "parse_leases: fadvise %s",
		    config.dhcpdlease_file);
	}
# endif				/* POSIX_FADV_WILLNEED */
# ifdef POSIX_FADV_SEQUENTIAL
	posix_fadvise(fileno(dhcpd_leases), 0, 0, POSIX_FADV_SEQUENTIAL);
	if (errno) {
		err(EXIT_FAILURE, "parse_leases: fadvise %s",
		    config.dhcpdlease_file);
	}
# endif				/* POSIX_FADV_SEQUENTIAL */
#endif				/* HAVE_POSIX_FADVISE */

	/* I found out that there's one lease address per 300 bytes in
	 * dhcpd.leases file. Malloc is little bit pessimistic and uses 250.
	 * If someone has higher density in lease file I'm interested to
	 * hear about that. */
	if (stat(config.dhcpdlease_file, &lease_file_stats)) {
		err(EXIT_FAILURE, "parse_leases: %s", config.dhcpdlease_file);
	}

	line = xmalloc(sizeof(char) * MAXLEN);
	ipstring = xmalloc(sizeof(char) * MAXLEN);
	if (config.output_format[0] == 'X' || config.output_format[0] == 'J') {
		ethernets = true;
	}

	const char **p = prefixes[config.dhcp_version];
	int *l = prefix_length[config.dhcp_version];

/*! \def HAS_PREFIX(line, type)
 * \brief A macro to match IPv4 and IPv6 lease lines.
 *
 * FIXME: This macro should have better name. The HAS_PREFIX sounds like
 * some sort of prefix length test. */
#define HAS_PREFIX(line, type) xstrstr((line), p[type], l[type])

	while (!feof(dhcpd_leases)) {
		if (!fgets(line, MAXLEN, dhcpd_leases) && ferror(dhcpd_leases)) {
			err(EXIT_FAILURE, "parse_leases: %s",
			    config.dhcpdlease_file);
		}
		/* It's a lease, save IP */
		if (HAS_PREFIX(line, PREFIX_LEASE)) {
			nth_field(ipstring, line + l[PREFIX_LEASE]);
			parse_ipaddr(ipstring, &addr);
			continue;
		}
		if (HAS_PREFIX(line, PREFIX_BINDING_STATE_FREE) ||
		    HAS_PREFIX(line, PREFIX_BINDING_STATE_ABANDONED) ||
		    HAS_PREFIX(line, PREFIX_BINDING_STATE_EXPIRED) ||
		    HAS_PREFIX(line, PREFIX_BINDING_STATE_RELEASED)) {
			/* remove old entry, if exists */
			if ((lease = find_lease(&addr)) != NULL) {
				delete_lease(lease);
			}
			add_lease(&addr, FREE);
			continue;
		}
		/* Copy IP to correct array */
		if (HAS_PREFIX(line, PREFIX_BINDING_STATE_ACTIVE)) {
			/* remove old entry, if exists */
			if ((lease = find_lease(&addr)) != NULL) {
				delete_lease(lease);
			}
			add_lease(&addr, ACTIVE);
			continue;
		}
		if (HAS_PREFIX(line, PREFIX_BINDING_STATE_BACKUP)) {
			/* remove old entry, if exists */
			if ((lease = find_lease(&addr)) != NULL) {
				delete_lease(lease);
			}
			add_lease(&addr, BACKUP);
			config.backups_found = true;
			continue;
		}
		if (ethernets && (xstrstr(line, "  hardware ethernet", 19))) {
			nth_field(macstring, line + 20);
			macstring[17] = '\0';
			if ((lease = find_lease(&addr)) != NULL) {
				lease->ethernet = xstrdup(macstring);
			}
		}
	}
#undef HAS_PREFIX
	free(line);
	free(ipstring);
	fclose(dhcpd_leases);
	return 0;
}