Exemplo n.º 1
0
int
dna_helper_enqueue(struct subscriber *source, mdp_port_t source_port, const char *did)
{
  if (config.debug.dnahelper)
    DEBUGF("DNAHELPER request did=%s sid=%s", did, alloca_tohex_sid_t(source->sid));
  if (dna_helper_pid == 0)
    return 0;
  // Only try to restart a DNA helper process if the previous one is well and truly gone.
  if (dna_helper_pid == -1 && dna_helper_stdin == -1 && dna_helper_stdout == -1 && dna_helper_stderr == -1) {
    if (dna_helper_start() == -1) {
      /* Something broke, bail out */
      return WHY("DNAHELPER start failed");
    }
  }
  /* Write request to dna helper.
     Request takes form:  SID-of-Requestor|DID|\n
     By passing the requestor's SID to the helper, we don't need to maintain
     any state, as all we have to do is wait for responses from the helper,
     which will include the requestor's SID.
  */
  if (dna_helper_stdin == -1)
    return 0;
  if (request_bufptr && request_bufptr != request_buffer) {
    WARNF("DNAHELPER currently sending request %s -- dropping new request", request_buffer);
    return 0;
  }
  if (awaiting_reply) {
    WARN("DNAHELPER currently awaiting reply -- dropping new request");
    return 0;
  }
  char buffer[sizeof request_buffer];
  strbuf b = strbuf_local(request_bufptr == request_buffer ? buffer : request_buffer, sizeof buffer);
  strbuf_tohex(b, SID_STRLEN, source->sid.binary);
  strbuf_putc(b, '|');
  strbuf_puts(b, did);
  strbuf_putc(b, '|');
  strbuf_putc(b, '\n');
  if (strbuf_overrun(b)) {
    WHYF("DNAHELPER request buffer overrun: %s -- request not sent", strbuf_str(b));
    request_bufptr = request_bufend = NULL;
  } else {
    if (strbuf_str(b) != request_buffer) {
      if (strcmp(strbuf_str(b), request_buffer) != 0)
	WARNF("DNAHELPER overwriting unsent request %s", request_buffer);
      strcpy(request_buffer, strbuf_str(b));
    }
    request_bufptr = request_buffer;
    request_bufend = request_buffer + strbuf_len(b);
    request_source = source;
    request_port = source_port;
    strncpy(request_did, did, sizeof request_did);
    request_did[sizeof request_did - 1] = '\0';
  }
  if (dna_helper_started) {
    sched_requests.poll.fd = dna_helper_stdin;
    watch(&sched_requests);
  }
  return 1;
}
Exemplo n.º 2
0
FILE *open_logging()
{
#ifdef ANDROID
    return NULL;
#endif
    if (!logfile) {
        const char *logpath = getenv("SERVALD_LOG_FILE");
        if (!logpath) {
            // If the configuration is locked (eg, it called WHY() or DEBUG() while initialising, which
            // led back to here) then return NULL to indicate the message cannot be logged.
            if (confLocked())
                return NULL;
            logpath = confValueGet("log.file", NULL);
        }
        if (!logpath) {
            logfile = stderr;
            INFO("No logfile configured -- logging to stderr");
        } else if ((logfile = fopen(logpath, "a"))) {
            setlinebuf(logfile);
            INFOF("Logging to %s (fd %d)", logpath, fileno(logfile));
        } else {
            logfile = stderr;
            WARN_perror("fopen");
            WARNF("Cannot append to %s -- falling back to stderr", logpath);
        }
    }
    return logfile;
}
Exemplo n.º 3
0
Class* Java_java_lang_Class_classForName(Env* env, Class* cls, Object* className, jboolean initializeBoolean,
            ClassLoader* classLoader) {

    if (!className) {
        rvmThrowNullPointerException(env);
        return NULL;
    }
    char* classNameUTF = toBinaryName(env, className);
    if (!classNameUTF) return NULL;
    Class* clazz = rvmFindClassUsingLoader(env, classNameUTF, classLoader);
    if (!clazz) {
        char* p = classNameUTF;
        while (*p != '\0') {
            if (*p == '/') *p = '.';
            p++;
        }
        WARNF("Class.forName() failed to load '%s'. "
              "Use the -forcelinkclasses command line option "
              "or add <forceLinkClasses><pattern>%s</pattern></forceLinkClasses> "
              "to your robovm.xml file to link it in.",
              classNameUTF, classNameUTF);
        return NULL;
    }
    if (initializeBoolean) {
        rvmInitialize(env, clazz);
        if (rvmExceptionCheck(env)) return NULL;
    }
    return clazz;
}
Exemplo n.º 4
0
void handle_reply_line(const char *bufp, size_t len)
{
  if (!dna_helper_started) {
    if (len == 8 && strncmp(bufp, "STARTED\n", 8) == 0) {
      if (config.debug.dnahelper)
	DEBUGF("DNAHELPER got STARTED ACK");
      dna_helper_started = 1;
      // Start sending request if there is one pending.
      if (request_bufptr) {
	sched_requests.poll.fd = dna_helper_stdin;
	watch(&sched_requests);
      }
    } else {
      WHYF("DNAHELPER malformed start ACK %s", alloca_toprint(-1, bufp, len));
      dna_helper_kill();
    }
  } else if (awaiting_reply) {
    if (len == 5 && strncmp(bufp, "DONE\n", 5) == 0) {
      if (config.debug.dnahelper)
	DEBUG("DNAHELPER reply DONE");
      unschedule(&sched_timeout);
      awaiting_reply = 0;
    } else {
      char sidhex[SID_STRLEN + 1];
      char did[DID_MAXSIZE + 1];
      char name[64];
      char uri[512];
      const char *replyend = NULL;
      if (!parseDnaReply(bufp, len, sidhex, did, name, uri, &replyend))
	WHYF("DNAHELPER reply %s invalid -- ignored", alloca_toprint(-1, bufp, len));
      else if (uri[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty URI -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_uri(uri))
	WHYF("DNAHELPER reply %s contains invalid URI -- ignored", alloca_toprint(-1, bufp, len));
      else if (sidhex[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty token -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_subscriber_id(sidhex))
	WHYF("DNAHELPER reply %s contains invalid token -- ignored", alloca_toprint(-1, bufp, len));
      else if (strncmp(sidhex, request_buffer, SID_STRLEN) != 0)
	WHYF("DNAHELPER reply %s contains mismatched token -- ignored", alloca_toprint(-1, bufp, len));
      else if (did[0] == '\0')
	WHYF("DNAHELPER reply %s contains empty DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (!str_is_did(did))
	WHYF("DNAHELPER reply %s contains invalid DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (strcmp(did, request_did) != 0)
	WHYF("DNAHELPER reply %s contains mismatched DID -- ignored", alloca_toprint(-1, bufp, len));
      else if (*replyend != '\n')
	WHYF("DNAHELPER reply %s contains spurious trailing chars -- ignored", alloca_toprint(-1, bufp, len));
      else {
	if (config.debug.dnahelper)
	  DEBUGF("DNAHELPER reply %s", alloca_toprint(-1, bufp, len));
	overlay_mdp_dnalookup_reply(request_source, request_port, my_subscriber, uri, did, name);
      }
    }
  } else {
    WARNF("DNAHELPER spurious output %s -- ignored", alloca_toprint(-1, bufp, len));
  }
}
Exemplo n.º 5
0
int64_t confValueGetInt64Range(const char *var, int64_t defaultValue, int64_t rangemin, int64_t rangemax)
{
    int64_t value = confValueGetInt64(var, defaultValue);
    if (value >= rangemin || value <= rangemax)
        return value;
    WARNF("Config option %s: configured value %lld out of range [%lld,%lld], using default value %lld",
          var, (long long) value, (long long) rangemin, (long long) rangemax, (long long) defaultValue);
    return defaultValue;
}
Exemplo n.º 6
0
int confParseBoolean(const char *text, const char *option_name)
{
    if (!strcasecmp(text, "on") || !strcasecmp(text, "yes") || !strcasecmp(text, "true") || !strcmp(text, "1"))
        return 1;
    if (!strcasecmp(text, "off") || !strcasecmp(text, "no") || !strcasecmp(text, "false") || !strcmp(text, "0"))
        return 0;
    WARNF("Config option %s: invalid boolean value '%s'", option_name, text);
    return -1;
}
Exemplo n.º 7
0
int confValueGetBoolean(const char *var, int defaultValue)
{
    const char *value = confValueGet(var, NULL);
    if (!value)
        return defaultValue;
    int flag = confParseBoolean(value, var);
    if (flag >= 0)
        return flag;
    WARNF("Config option %s: using default value %s", var, defaultValue ? "true" : "false");
    return defaultValue;
}
Exemplo n.º 8
0
int overlay_mdp_recv(overlay_mdp_frame *mdp, int port, int *ttl) 
{
  char mdp_socket_name[101];
  unsigned char recvaddrbuffer[1024];
  struct sockaddr *recvaddr=(struct sockaddr *)recvaddrbuffer;
  unsigned int recvaddrlen=sizeof(recvaddrbuffer);
  struct sockaddr_un *recvaddr_un;
  
  if (!FORM_SERVAL_INSTANCE_PATH(mdp_socket_name, "mdp.socket"))
    return WHY("Could not find mdp socket");
  mdp->packetTypeAndFlags=0;
  
  /* Check if reply available */
  set_nonblock(mdp_client_socket);
  ssize_t len = recvwithttl(mdp_client_socket,(unsigned char *)mdp, sizeof(overlay_mdp_frame),ttl,recvaddr,&recvaddrlen);
  set_block(mdp_client_socket);
  
  recvaddr_un=(struct sockaddr_un *)recvaddr;
  /* Null terminate received address so that the stat() call below can succeed */
  if (recvaddrlen<1024) recvaddrbuffer[recvaddrlen]=0;
  if (len>0) {
    /* Make sure recvaddr matches who we sent it to */
    if (strncmp(mdp_socket_name, recvaddr_un->sun_path, sizeof(recvaddr_un->sun_path))) {
      /* Okay, reply was PROBABLY not from the server, but on OSX if the path
       has a symlink in it, it is resolved in the reply path, but might not
       be in the request path (mdp_socket_name), thus we need to stat() and
       compare inode numbers etc */
      struct stat sb1,sb2;
      if (stat(mdp_socket_name,&sb1)) return WHY("stat(mdp_socket_name) failed, so could not verify that reply came from MDP server");
      if (stat(recvaddr_un->sun_path,&sb2)) return WHY("stat(ra->sun_path) failed, so could not verify that reply came from MDP server");
      if ((sb1.st_ino!=sb2.st_ino)||(sb1.st_dev!=sb2.st_dev))
	return WHY("Reply did not come from server");
    }
    
    // silently drop incoming packets for the wrong port number
    if (port>0 && port != mdp->in.dst.port){
      WARNF("Ignoring packet for port %d",mdp->in.dst.port);
      return -1;
    }
    
    int expected_len = overlay_mdp_relevant_bytes(mdp);
    
    if (len < expected_len){
      return WHYF("Expected packet length of %d, received only %lld bytes", expected_len, (long long) len);
    }
    
    /* Valid packet received */
    return 0;
  } else 
  /* no packet received */
    return -1;
  
}
Exemplo n.º 9
0
int64_t confValueGetInt64(const char *var, int64_t defaultValue)
{
    const char *start = confValueGet(var, NULL);
    if (!start)
        return defaultValue;
    const char *end = start;
    long long value = strtoll(start, (char **)&end, 10);
    if (*start && !*end && end != start)
        return value;
    WARNF("Config option %s: '%s' is not an integer, using default value %lld", var, start, (long long) defaultValue);
    return defaultValue;
}
Exemplo n.º 10
0
const char *confValueGet(const char *var, const char *defaultValue)
{
    if (var == NULL) {
        WHYF("NULL var name, returning default value: %s", defaultValue ? defaultValue : "NULL");
        return defaultValue;
    }
    if (!config_buffer && read_config() == -1) {
        if (defaultValue)
            WARNF("Config option %s: using default value: %s", var, defaultValue);
        return defaultValue;
    }
    unsigned int i;
    for (i = 0; i != confc; ++i)
        if (strcasecmp(confvar[i], var) == 0)
            return confvalue[i];
    return defaultValue;
}
Exemplo n.º 11
0
void confSetDebugFlags()
{
    if (config_buffer || read_config() != -1) {
        unsigned int setmask = 0;
        unsigned int clearmask = 0;
        int setall = 0;
        int clearall = 0;
        unsigned int i;
        for (i = 0; i != confc; ++i) {
            char *var = confvar[i];
            if (strncasecmp(var, "debug.", 6) == 0) {
                unsigned int mask = debugFlagMask(var + 6);
                if (mask == 0)
                    WARNF("Unsupported debug option '%s'", var);
                else {
                    int flag = confParseBoolean(confvalue[i], var);
                    if (flag != -1) {
                        if (mask == DEBUG_ALL) {
                            if (flag) {
                                //DEBUGF("Set all debug flags");
                                setall = 1;
                            } else {
                                //DEBUGF("Clear all debug flags");
                                clearall = 1;
                            }
                        } else {
                            if (flag) {
                                //DEBUGF("Set %s", var);
                                setmask |= mask;
                            } else {
                                //DEBUGF("Clear %s", var);
                                clearmask |= mask;
                            }
                        }
                    }
                }
            }
        }
        if (setall)
            debug = DEBUG_ALL;
        else if (clearall)
            debug = 0;
        debug &= ~clearmask;
        debug |= setmask;
    }
}
Exemplo n.º 12
0
void
srandomdev(void)
{
  unsigned int seed;
  int seeded = 0;
#ifndef WIN32
  FILE *fd;
  fd = fopen("/dev/urandom", "r");
  if (NULL != fd) {
    if (fread(&seed, sizeof seed, 1, fd) != 1)
      WARNF("fread(\"/dev/urandom\") failed -- falling back to gettimeofday()");
    else
      seeded = 1;
    fclose(fd);
  }
#endif
  if (!seeded) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    seed = (getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec;
  }
  srandom(seed);
}
Exemplo n.º 13
0
static void add_instrumentation(void) {

  static u8 line[MAX_AS_LINE];

  FILE* inf;
  FILE* outf;
  s32 outfd;
  u32 ins_lines = 0;

  u8  instr_ok = 0, skip_csect = 0, skip_next_label = 0,
      skip_intel = 0, skip_app = 0;

#ifdef __APPLE__

  u8* colon_pos;

#endif /* __APPLE__ */

  if (input_file) {

    inf = fopen(input_file, "r");
    if (!inf) PFATAL("Unable to read '%s'", input_file);

  } else inf = stdin;

  outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);

  if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);

  outf = fdopen(outfd, "w");

  if (!outf) PFATAL("fdopen() failed");  

  while (fgets(line, MAX_AS_LINE, inf)) {

    fputs(line, outf);

    if (pass_thru) continue;

    /* We only want to instrument the .text section. So, let's keep track
       of that in processed files. */

    if (line[0] == '\t' && line[1] == '.') {

      /* OpenBSD puts jump tables directly inline with the code, which is
         a bit annoying. They use a specific format of p2align directives
         around them, so we use that as a signal. */

      if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) &&
          isdigit(line[10]) && line[11] == '\n') skip_next_label = 1;

      if (!strncmp(line + 2, "text\n", 5) ||
          !strncmp(line + 2, "section\t.text", 13) ||
          !strncmp(line + 2, "section\t__TEXT,__text", 21) ||
          !strncmp(line + 2, "section __TEXT,__text", 21)) {
        instr_ok = 1;
        continue; 
      }

      if (!strncmp(line + 2, "section\t", 8) ||
          !strncmp(line + 2, "section ", 8) ||
          !strncmp(line + 2, "bss\n", 4) ||
          !strncmp(line + 2, "data\n", 5)) {
        instr_ok = 0;
        continue;
      }

    }

    /* Detect off-flavor assembly (rare, happens in gdb). */

    if (strstr(line, ".code")) {

      if (strstr(line, ".code32")) skip_csect = use_64bit;
      if (strstr(line, ".code64")) skip_csect = !use_64bit;

    }

    /* Detect syntax changes. */

    if (strstr(line, ".intel_syntax")) skip_intel = 1;
    if (strstr(line, ".att_syntax")) skip_intel = 0;

    /* Detect and skip ad-hoc __asm__ blocks. */

    if (line[0] == '#' || line[1] == '#') {

      if (strstr(line, "#APP")) skip_app = 1;
      if (strstr(line, "#NO_APP")) skip_app = 0;

    }

    /* If we're in the right mood for instrumenting, check for function
       names or conditional labels. This is a bit messy, but in essence,
       we want to catch:

         ^main:      - function entry point (always instrumented)
         ^.L0:       - GCC branch label
         ^.LBB0_0:   - clang branch label (but only in clang mode)
         ^\tjnz foo  - conditional branches

       ...but not:

         ^# BB#0:    - clang comments
         ^ # BB#0:   - ditto
         ^.Ltmp0:    - clang non-branch labels
         ^.LC0       - GCC non-branch labels
         ^.LBB0_0:   - ditto (when in GCC mode)
         ^\tjmp foo  - non-conditional jumps

       Additionally, clang and GCC on MacOS X follow a different convention
       with no leading dots on labels, hence the weird maze of #ifdefs
       later on.

     */

    if (skip_intel || skip_app || skip_csect || !instr_ok ||
        line[0] == '#' || line[0] == ' ') continue;

    /* Conditional branch instruction (jnz, etc). */

    if (line[0] == '\t') {

      if (line[1] == 'j' && line[2] != 'm' && R(100) < inst_ratio) {

        fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
                R(MAP_SIZE));

        ins_lines++;

      }

      continue;

    }

    /* Label of some sort. */

#ifdef __APPLE__

    /* Apple: L<whatever><digit>: */

    if ((colon_pos = strstr(line, ":"))) {

      if (line[0] == 'L' && isdigit(*(colon_pos - 1))) {

#else

    /* Everybody else: .L<whatever>: */

    if (strstr(line, ":")) {

      if (line[0] == '.') {

#endif /* __APPLE__ */

        /* .L0: or LBB0_0: style jump destination */

#ifdef __APPLE__

        /* Apple: L<num> / LBB<num> */

        if ((isdigit(line[1]) || (clang_mode && !strncmp(line, "LBB", 3)))
            && R(100) < inst_ratio) {

#else

        /* Apple: .L<num> / .LBB<num> */

        if ((isdigit(line[2]) || (clang_mode && !strncmp(line + 1, "LBB", 3)))
            && R(100) < inst_ratio) {

#endif /* __APPLE__ */

          /* An optimization is possible here by adding the code only if the
             label is mentioned in the code in contexts other than call / jmp.
             That said, this complicates the code by requiring two-pass
             processing (messy with stdin), and results in a speed gain
             typically under 10%. */

          if (!skip_next_label) {

            fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
                    R(MAP_SIZE));

            ins_lines++;

          } else skip_next_label = 0;

        }

      } else {

        /* Function label (always instrumented) */

        fprintf(outf, use_64bit ? trampoline_fmt_64 : trampoline_fmt_32,
                R(MAP_SIZE));

        ins_lines++;
    
      }

    }

  }

  if (ins_lines)
    fputs(use_64bit ? main_payload_64 : main_payload_32, outf);

  if (input_file) fclose(inf);
  fclose(outf);

  if (!be_quiet) {

    if (!ins_lines) WARNF("No instrumentation targets found.");
    else OKF("Instrumented %u locations (%s-bit, %s mode, ratio %u%%).",
             ins_lines, use_64bit ? "64" : "32",
             getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
             inst_ratio);
 
  }

}


/* Main entry point */

int main(int argc, char** argv) {

  s32 pid;
  u32 rand_seed;
  int status;
  u8* inst_ratio_str = getenv("AFL_INST_RATIO");

  struct timeval tv;
  struct timezone tz;

  clang_mode = !!getenv(CLANG_ENV_VAR);

  if (isatty(2) && !getenv("AFL_QUIET")) {

    SAYF(cCYA "afl-as " cBRI VERSION cRST " (" __DATE__ " " __TIME__ 
         ") by <*****@*****.**>\n");
 
  } else be_quiet = 1;

  if (argc < 2) {

    SAYF("\n"
         "This is a helper application for afl-fuzz. It is a wrapper around GNU 'as',\n"
         "executed by the toolchain whenever using afl-gcc or afl-clang. You probably\n"
         "don't want to run this program directly.\n\n"

         "Rarely, when dealing with extremely complex projects, it may be advisable to\n"
         "set AFL_INST_RATIO to a value less than 100 in order to reduce the odds of\n"
         "instrumenting every discovered branch.\n\n");

    exit(1);

  }

  gettimeofday(&tv, &tz);

  rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();

  srandom(rand_seed);

  edit_params(argc, argv);

  if (inst_ratio_str) {

    if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) 
      FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)");

  }

  if (getenv(AS_LOOP_ENV_VAR))
    FATAL("Endless loop when calling 'as' (remove '.' from your PATH)");

  setenv(AS_LOOP_ENV_VAR, "1", 1);

  /* When compiling with ASAN, we don't have a particularly elegant way to skip
     ASAN-specific branches. But we can probabilistically compensate for
     that... */

  if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) inst_ratio /= 3;

  if (!just_version) add_instrumentation();

  if (!(pid = fork())) {

    execvp(as_params[0], (char**)as_params);
    FATAL("Oops, failed to execute '%s' - check your PATH", as_params[0]);

  }

  if (pid < 0) PFATAL("fork() failed");

  if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed");

  if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file);

  exit(WEXITSTATUS(status));

}
Exemplo n.º 14
0
static void gcWarnProc(char* msg, GC_word arg) {
    WARNF(msg, arg);
}
Exemplo n.º 15
0
void overlay_mdp_poll(struct sched_ent *alarm)
{
  if (alarm->poll.revents & POLLIN) {
    unsigned char buffer[16384];
    int ttl;
    unsigned char recvaddrbuffer[1024];
    struct sockaddr *recvaddr=(struct sockaddr *)&recvaddrbuffer[0];
    socklen_t recvaddrlen=sizeof(recvaddrbuffer);
    struct sockaddr_un *recvaddr_un=NULL;

    ttl=-1;
    bzero((void *)recvaddrbuffer,sizeof(recvaddrbuffer));
    
    ssize_t len = recvwithttl(alarm->poll.fd,buffer,sizeof(buffer),&ttl, recvaddr, &recvaddrlen);
    recvaddr_un=(struct sockaddr_un *)recvaddr;

    if (len>0) {
      /* Look at overlay_mdp_frame we have received */
      overlay_mdp_frame *mdp=(overlay_mdp_frame *)&buffer[0];      
      unsigned int mdp_type = mdp->packetTypeAndFlags & MDP_TYPE_MASK;

      switch (mdp_type) {
      case MDP_GOODBYE:
	if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_GOODBYE");
	overlay_mdp_releasebindings(recvaddr_un,recvaddrlen);
	return;
      case MDP_NODEINFO:
	if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_NODEINFO");
	overlay_route_node_info(mdp,recvaddr_un,recvaddrlen);
	return;
      case MDP_GETADDRS:
	if (debug & DEBUG_MDPREQUESTS)
	  DEBUGF("MDP_GETADDRS first_sid=%u last_sid=%u frame_sid_count=%u mode=%d",
	      mdp->addrlist.first_sid,
	      mdp->addrlist.last_sid,
	      mdp->addrlist.frame_sid_count,
	      mdp->addrlist.mode
	    );
	{
	  overlay_mdp_frame mdpreply;
	  
	  /* Work out which SIDs to get ... */
	  int sid_num=mdp->addrlist.first_sid;
	  int max_sid=mdp->addrlist.last_sid;
	  int max_sids=mdp->addrlist.frame_sid_count;
	  /* ... and constrain list for sanity */
	  if (sid_num<0) sid_num=0;
	  if (max_sids>MDP_MAX_SID_REQUEST) max_sids=MDP_MAX_SID_REQUEST;
	  if (max_sids<0) max_sids=0;
	  
	  /* Prepare reply packet */
	  mdpreply.packetTypeAndFlags = MDP_ADDRLIST;
	  mdpreply.addrlist.mode = mdp->addrlist.mode;
	  mdpreply.addrlist.first_sid = sid_num;
	  mdpreply.addrlist.last_sid = max_sid;
	  mdpreply.addrlist.frame_sid_count = max_sids;
	  
	  /* Populate with SIDs */
	  struct search_state state={
	    .mdp=mdp,
	    .mdpreply=&mdpreply,
	    .first=sid_num,
	    .max=max_sid,
	  };
	  
	  enum_subscribers(NULL, search_subscribers, &state);
	  
	  mdpreply.addrlist.frame_sid_count = state.index;
	  mdpreply.addrlist.last_sid = sid_num + state.index - 1;
	  mdpreply.addrlist.server_sid_count = state.count;

	  if (debug & DEBUG_MDPREQUESTS)
	    DEBUGF("reply MDP_ADDRLIST first_sid=%u last_sid=%u frame_sid_count=%u server_sid_count=%u",
		mdpreply.addrlist.first_sid,
		mdpreply.addrlist.last_sid,
		mdpreply.addrlist.frame_sid_count,
		mdpreply.addrlist.server_sid_count
	      );

	  /* Send back to caller */
	  overlay_mdp_reply(alarm->poll.fd,
			    (struct sockaddr_un *)recvaddr,recvaddrlen,
			    &mdpreply);
	  return;
	}
	break;
	  
      case MDP_TX: /* Send payload (and don't treat it as system privileged) */
	if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_TX");
	overlay_mdp_dispatch(mdp,1,(struct sockaddr_un*)recvaddr,recvaddrlen);
	return;
	break;
	  
      case MDP_BIND: /* Bind to port */
	{
	  if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_BIND");
	  
	  struct subscriber *subscriber=NULL;
	  /* Make sure source address is either all zeros (listen on all), or a valid
	   local address */
	  
	  if (!is_sid_any(mdp->bind.sid)){
	    subscriber = find_subscriber(mdp->bind.sid, SID_SIZE, 0);
	    if ((!subscriber) || subscriber->reachable != REACHABLE_SELF){
	      WHYF("Invalid bind request for sid=%s", alloca_tohex_sid(mdp->bind.sid));
	      /* Source address is invalid */
	      overlay_mdp_reply_error(alarm->poll.fd, recvaddr_un, recvaddrlen, 7,
					     "Bind address is not valid (must be a local MDP address, or all zeroes).");
	      return;
	    }
	    
	  }
	  if (overlay_mdp_process_bind_request(alarm->poll.fd, subscriber, mdp->bind.port,
					       mdp->packetTypeAndFlags, recvaddr_un, recvaddrlen))
	    overlay_mdp_reply_error(alarm->poll.fd,recvaddr_un,recvaddrlen,3, "Port already in use");
	  else
	    overlay_mdp_reply_ok(alarm->poll.fd,recvaddr_un,recvaddrlen,"Port bound");
	  return;
	}
	break;
	  
      default:
	/* Client is not allowed to send any other frame type */
	WARNF("Unsupported MDP frame type: %d", mdp_type);
	mdp->packetTypeAndFlags=MDP_ERROR;
	mdp->error.error=2;
	snprintf(mdp->error.message,128,"Illegal request type.  Clients may use only MDP_TX or MDP_BIND.");
	int len=4+4+strlen(mdp->error.message)+1;
	errno=0;
	/* We ignore the result of the following, because it is just sending an
	   error message back to the client.  If this fails, where would we report
	   the error to? My point exactly. */
	sendto(alarm->poll.fd,mdp,len,0,(struct sockaddr *)recvaddr,recvaddrlen);
      }
    }
Exemplo n.º 16
0
int upper7_decode(struct slip_decode_state *state,unsigned char byte)
{
  IN()
    u7d_calls++;
  if (config.debug.slipdecode)
    snprintf(crash_handler_clue,1024,
	     "upper7_decode() call #%d: state=%d, byte=0x%02x, rssi_len=%u, dst_offset=%u",
	     u7d_calls,state->state,byte,state->rssi_len,state->dst_offset);
  if (config.debug.slipbytestream)
    WHYF("call #%d: state=%d, byte=0x%02x, rssi_len=%u, dst_offset=%u",
	 u7d_calls,state->state,byte,state->rssi_len,state->dst_offset);

  // Parse out inline RSSI reports
  if (byte=='{') {
    state->state=UPPER7_STATE_L1; 
    state->packet_length=0;
    RETURN(0);
  } else if (byte=='}') {
    // End of packet marker -- report end of received packet to caller
    // for CRC verification etc.
    state->state=UPPER7_STATE_NOTINPACKET; RETURN(1);
  } else if (byte>=' '&&byte<=0x7f) {
    if (state->rssi_len<RSSI_TEXT_SIZE) 
      state->rssi_text[state->rssi_len++]=byte;
    RETURN(0);
  } else if (byte=='\r'||byte=='\n') {
    if (state->rssi_len>=RSSI_TEXT_SIZE) state->rssi_len=RSSI_TEXT_SIZE-1;
    state->rssi_text[state->rssi_len]=0;
    parse_rfd900_rssi(state->rssi_text);
    state->rssi_len=0;
  }

  // Non-data bytes (none currently used, but we need to catch them before
  // moving onto processing data bytes)
  if (byte<0x80) {
    RETURN(0);   
  }

  // Data bytes and packet fields
  byte&=0x7f;
  if (state->packet_length>=OVERLAY_INTERFACE_RX_BUFFER_SIZE
      ||(state->dst_offset+7)>=OVERLAY_INTERFACE_RX_BUFFER_SIZE
  ) {
      WARNF("state=%p, state->dst_offset=%u, ->packet_length=%u, ->state=%d. State reset.",
	    state,state->dst_offset,state->packet_length,state->state);
      state->state=UPPER7_STATE_NOTINPACKET;
      state->dst_offset=0;
      state->packet_length=0;
      RETURN(0);
    }
  switch(state->state) {
  case UPPER7_STATE_NOTINPACKET: RETURN(0);
  case UPPER7_STATE_L1: state->packet_length=byte<<7; state->state++; RETURN(0);
  case UPPER7_STATE_L2: state->packet_length|=byte;
    // Make sure packet length can fit in RX buffer, including that we might
    // need upto 7 bytes extra temporary space due to blocking
    if ((state->packet_length+7)<OVERLAY_INTERFACE_RX_BUFFER_SIZE) {
      state->state++; 
      state->dst_offset=0;
    } else {
      if (config.debug.packetradio) 
	DEBUGF("Ignoring jumbo packet of %u bytes",state->packet_length);
      state->state=UPPER7_STATE_NOTINPACKET;
    }
    RETURN(0);
  case UPPER7_STATE_C1: state->crc=byte<<25; state->state++; RETURN(0);
  case UPPER7_STATE_C2: state->crc|=byte<<(25-7); state->state++; RETURN(0);
  case UPPER7_STATE_C3: state->crc|=byte<<(25-7-7); state->state++; RETURN(0);
  case UPPER7_STATE_C4: state->crc|=byte<<(25-7-7-7); state->state++; RETURN(0);
  case UPPER7_STATE_C5: state->crc|=byte<<0; state->state++; RETURN(0);
  case UPPER7_STATE_D0:
    if (state->packet_length>=OVERLAY_INTERFACE_RX_BUFFER_SIZE
	||(state->dst_offset+7)>=OVERLAY_INTERFACE_RX_BUFFER_SIZE
    ) {
	WARNF("state->dst_offset=%u, ->packet_length=%u, ->state=%d. State reset (again).",
	      state->dst_offset,state->packet_length,state->state);
	state->state=UPPER7_STATE_NOTINPACKET;
	state->dst_offset=0;
	state->packet_length=0;
	RETURN(0);
      }
    state->dst[state->dst_offset]=byte<<1;   
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D1:
    state->dst[state->dst_offset+0]|=(byte>>6)&0x01;
    state->dst[state->dst_offset+1]=(byte<<2);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D2:
    state->dst[state->dst_offset+1]|=(byte>>5)&0x03;
    state->dst[state->dst_offset+2]=(byte<<3);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D3:
    state->dst[state->dst_offset+2]|=(byte>>4)&0x07;
    state->dst[state->dst_offset+3]=(byte<<4);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D4:
    state->dst[state->dst_offset+3]|=(byte>>3)&0x0f;
    state->dst[state->dst_offset+4]=(byte<<5);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D5:
    state->dst[state->dst_offset+4]|=(byte>>2)&0x1f;
    state->dst[state->dst_offset+5]=(byte<<6);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D6:
    state->dst[state->dst_offset+5]|=(byte>>1)&0x3f;
    state->dst[state->dst_offset+6]=(byte<<7);
    state->state++;
    RETURN(0);
  case UPPER7_STATE_D7:
    state->dst[state->dst_offset+6]|=(byte>>0)&0x7f;
    state->dst_offset+=7;
    state->state=UPPER7_STATE_D0;
    RETURN(0);
  default:
    state->state=UPPER7_STATE_NOTINPACKET;
    RETURN(0);
  }
  OUT();
}
Exemplo n.º 17
0
static void add_instrumentation(void) {

  static u8 line[MAX_AS_LINE];

  FILE* inf;
  FILE* outf;
  s32 outfd;
  u32 ins_lines = 0;
  u8  now_instr = 0;
  u8  output_next = 0;

  if (input_file) {

    inf = fopen(input_file, "r");
    if (!inf) PFATAL("Unable to read '%s'", input_file);

  } else inf = stdin;

  outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600);

  if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file);

  outf = fdopen(outfd, "w");

  if (!outf) PFATAL("fdopen() failed");

  while (fgets(line, MAX_AS_LINE, inf)) {

    u8* label;

    /* Oh boy. The ARM version is extremely messy compared to Intel,
       because of the very limited range of immediate pointers within
       opcodes. When we inject the instrumentation, it's possible to
       push some labels / literal pools outside the range they were
       in when GCC first generated the code. This means several things:

       - We need to rewrite instructions such as ldr to movw + movt +
         ldr.

       - We need to do a similar but different hack for fld* / fst*.

       - We need to inject additional .ltorg sections and jump over
         them to ensure sufficient density of literal pools.

       - We need to be careful to not accidentally instrument .word
         literals that appear in the code segment.

       Whoever complains that x86 assembly is counterintuitive and ARM
       is user-friendly is probably at least a bit high.

     */

    /* Output instrumentation unless we're hitting a block of .word
       literals. */

    if (output_next) {

      if (strncmp(line, "\t.word", 6)) {
        fprintf(outf, trampoline_fmt, R(MAP_SIZE));
        ins_lines++;
      }

      output_next = 0;

    }

    /* Rewrite label-referencing ldr instructions. */

    if (now_instr && !strncmp(line, "\tldr", 4) && 
        (label = strstr(line, ", .L"))) {

      u8* reg = strchr(line + 4, '\t');

      label[0] = 0;

      fprintf(outf, "%s, =%s\n", line, label + 2);
      fprintf(outf, "%s, [%s]\n", line, reg);

      continue;

    }

    /* Do not-exactly-the-same for fld* and fst*. */

    if (now_instr &&
        (!strncmp(line, "\tfld", 4) || !strncmp(line, "\tfst", 4)) &&
        (label = strstr(line, ", .L"))) {

      label[0] = 0;

      fprintf(outf, "push {r12}\n");
      fprintf(outf, "ldr r12, =%s\n", label + 2);
      fprintf(outf, "%s, [r12]\n", line);
      fprintf(outf, "pop {r12}\n");

      continue;

    }

    fputs(line, outf);

    /* We only want to instrument the .text section. So, let's keep track
       of that in processed files. */

    if (line[0] == '\t' && line[1] == '.') {

      if (!strncmp(line + 2, "text\n", 5)) {
        now_instr = 1; 
        continue; 
      }

      if (!strncmp(line + 2, "section\t", 8) ||
          !strncmp(line + 2, "bss\n", 4) ||
          !strncmp(line + 2, "data\n", 5)) {
        now_instr = 0;
        continue;
      }

    }

    /* If we're in the right mood for instrumenting, check for function
       names or conditional labels, decide what to do next. */

    if (now_instr && (
        (strstr(line, ":\n") && (line[0] == '.' ? isdigit(line[2]) : 1)) ||
        (line[0] == '\t' && line[1] == 'b' && line[2] == 'e'))) {

      output_next = 1;

    }


  }

  fputs(main_payload, outf);

  if (input_file) fclose(inf);
  fclose(outf);

  if (!ins_lines) WARNF("No instrumentation targets found.");
  else OKF("Successfully instrumented %u locations (seed = 0x%08x).",
           ins_lines, rand_seed);

}
Exemplo n.º 18
0
/* state->src and state->src_size contain the freshly read bytes
   we must accumulate any partial state between calls.
*/
int slip_decode(struct slip_decode_state *state)
{
  switch(state->encapsulator) {
  case SLIP_FORMAT_SLIP:
    {
      /*
       Examine received bytes for end of packet marker.
       The challenge is that we need to make sure that the packet encapsulation
       is self-synchronising in the event that a data error occurs (including
       failure to receive an arbitrary number of bytes).
       */
      while(state->src_offset < state->src_size){
	// clear the valid bit flag if we hit the end of the destination buffer
	if (state->dst_offset >= sizeof state->dst)
	  state->state&=~DC_VALID;
	
	if (state->state&DC_ESC){
	  // clear escape bit
	  state->state&=~DC_ESC;
	  switch(state->src[state->src_offset]) {
	    case SLIP_ESC_END: // escaped END byte
	      state->dst[state->dst_offset++]=SLIP_END;
	      break;
	    case SLIP_ESC_ESC: // escaped escape character
	      state->dst[state->dst_offset++]=SLIP_ESC;
	      break;
	    case SLIP_ESC_0a:
	      state->dst[state->dst_offset++]=SLIP_0a;
	      break;
	    case SLIP_ESC_0d:
	      state->dst[state->dst_offset++]=SLIP_0d;
	      break;
	    case SLIP_ESC_0f:
	      state->dst[state->dst_offset++]=SLIP_0f;
	      break;
	    case SLIP_ESC_1b:
	      state->dst[state->dst_offset++]=SLIP_1b;
	      break;
	    default: /* Unknown escape character. This is an error. */
	      if (config.debug.packetradio)
		WARNF("Packet radio stream contained illegal escaped byte 0x%02x -- resetting parser.",state->src[state->src_offset]);
	      state->dst_offset=0;
	      // skip everything until the next SLIP_END
	      state->state=0;
	  }
	}else{
	  // non-escape character
	  switch(state->src[state->src_offset]) {
	    case SLIP_ESC:
	      // set escape bit
	      state->state|=DC_ESC; 
	      break;
	    case SLIP_END:
	      if (state->dst_offset>4){
		
		uint32_t src_crc = read_uint32(state->dst + state->dst_offset -4);
		uint32_t crc=Crc32_ComputeBuf( 0, state->dst, state->dst_offset -4);
		
		if (src_crc != crc){
		  DEBUGF("Dropping frame due to CRC failure (%08x vs %08x)", src_crc, crc);
		  dump("frame", state->dst, state->dst_offset);
		  state->dst_offset=0;
		  state->state=0;
		  break;
		}
		// return once we've successfully parsed a valid packet that isn't empty
		state->packet_length=state->dst_offset -4;
		return 1;
	      }
	      // set the valid flag to begin parsing the next packet
	      state->state=DC_VALID;
	      break;
	    default:
	      if (state->state&DC_VALID)
		state->dst[state->dst_offset++]=state->src[state->src_offset];
	  }
	}
	state->src_offset++;
      }
      return 0;
    }
  case SLIP_FORMAT_UPPER7:
    {
      if (config.debug.slip) {
	if (state->rssi_len>=RSSI_TEXT_SIZE) state->rssi_len=RSSI_TEXT_SIZE-1;
	state->rssi_text[state->rssi_len]=0;
	DEBUGF("RX state=%d, rssi_len=%u, rssi_text='%s',src=%p, src_size=%u",
	       state->state,state->rssi_len,state->rssi_text,
	       state->src,state->src_size);
      }
     while(state->src_offset<state->src_size) {
	if (upper7_decode(state,state->src[state->src_offset++])==1) {
	  if (config.debug.slip) {
	    dump("de-slipped packet",state->dst,state->packet_length);
          }
	 
	  // Check that CRC matches
	  uint32_t crc=Crc32_ComputeBuf( 0, state->dst, state->packet_length);
	  if (crc!=state->crc) {
	    if (config.debug.packetradio||config.debug.rejecteddata)
	      DEBUGF("Rejected packet of %u bytes due to CRC mis-match (%08x vs %08x)",
		     state->packet_length,crc,state->crc);
	    if (config.debug.rejecteddata) {
	      dump("bad packet",state->dst,state->packet_length);
	    }
	  } else {
	    if (config.debug.packetradio) 
	      DEBUGF("Accepted packet of %u bytes (CRC ok)",state->packet_length);
	    return 1;
	  }
	}
      }
    }
    return 0;
  default:
    return WHYF("Unknown SLIP encapsulation format #%d",state->encapsulator);
  }
}
Exemplo n.º 19
0
int lpgdv_protocol_split_url(const char* url,
			     const LpgdvProtocol* prot,
			     LpgdvSplittedUrl* su)
{
  ENTER("lpgdv_protocol_split_url");
  char* url_copy = 0;
  char* p;
  char* login = 0;
  char* host = 0;
  int err = 1;

  if(su) memset(su, 0, sizeof(LpgdvSplittedUrl));
  if(su==0 || url==0 || strlen(url)==0) goto done;

  if(prot && prot->has_host) {
    if(strncmp(url, "//", 2))  goto done; /* invalid url */
    else if(strlen(url)>=2) url+=2;
    else goto done; /* invalid url */
  }

  url_copy = strdup(url);
  if(url_copy==0) {
    WARNF("warning: strdup(url) failed\n");
    goto done;
  }

  err = 0;

  /* extract arguments */
  p = (prot==0 || prot->has_arguments) ? strchr(url_copy, '?') : 0;
  if(p) {
    *p = '\0';
    su->arguments = strdup(p+1);
    if(su->arguments==0) err |= 1;
  }

  /* extract path */
  if(prot && !prot->has_host && !prot->has_login) p = url_copy;
  else p = strchr(url_copy, '/');
  if(p) {
    char* z = p;
    if(!strncmp(p, "//", 2)) p+=2;
    su->path = strdup(p);
    *z = '\0';
    if(su->path==0) err |= 1;
  }

  /* split login from host */
  if(prot==0 || prot->has_login) {
    p = strchr(url_copy, '@');
    if(p) {
      *p = '\0';
      login = url_copy;
      host = p+1;
    }
    else {
      login = 0;
      host = url_copy;
    }
  }

  /* extract host name and port */
  su->port = prot ? prot->default_port : 0;
  if(host) {
    p = strchr(host, ':');
    if(p) {
      *p = '\0';
      su->port = atoi(p+1);
    }
    if(strlen(host)) {
      su->host = strdup(host);
      if(su->host==0) err |= 1;
    }
  }

  /* extract user name and password */
  if(login) {
    p = strchr(login, ':');
    if(p) {
      *p = '\0';
      su->password = strdup(p+1);
      if(su->password==0) err |= 1;
    }
    su->username = strdup(login);
    if(su->username==0) err |= 1;
  }

  /* done */
 done:
  if(err) lpgdv_protocol_free_url(su);
  if(url_copy) free(url_copy);
  LEAVE;
  return !err;
  
}