Example #1
0
void onvif_set_UpgradeSystemFirmware_request(struct soap* soap, struct _tds__UpgradeSystemFirmware * req){
	unsigned char* data;
	size_t size = 0;

	printf("enter %s\n", __FUNCTION__);

	memset(req, 0, sizeof(*req));
	CHECK_FIELD(req->Firmware);


	data = load_file_data("1.bin", &size);
	if (data == NULL) {
		printf("empty file\n");
		return;
	}

	printf("file size:%d\n", size);

	soap_set_field_string(soap, &req->Firmware->xmime__contentType, "binary");

	req->Firmware->xop__Include.__size = min(64*1024,size);
	req->Firmware->xop__Include.__ptr = (unsigned char*) data;
	soap_set_field_string(soap, &req->Firmware->xop__Include.id, "id");
	soap_set_field_string(soap, &req->Firmware->xop__Include.options, "option");
	soap_set_field_string(soap, &req->Firmware->xop__Include.type, "text/html");

	free(data);
}
Example #2
0
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

     test for fix selector

     THIS IS THE ONLY EXPORTED ROUTINE

*/
void
apply_fix( tFixDesc* p_fixd, tCC* filname )
{
#define _FT_(n,p) { n, p },
  static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
#undef _FT_
#define FIX_TABLE_CT (ARRAY_SIZE (fix_table)-1)

  tCC* fixname = p_fixd->patch_args[0];
  char* buf;
  int ct = FIX_TABLE_CT;
  fix_entry_t* pfe = fix_table;

  for (;;)
    {
      if (strcmp (pfe->fix_name, fixname) == 0)
        break;
      if (--ct <= 0)
        {
          fprintf (stderr, "fixincl error:  the `%s' fix is unknown\n",
                   fixname );
          exit (EXIT_BROKEN);
        }
      pfe++;
    }

  buf = load_file_data (stdin);
  (*pfe->fix_proc)( filname, buf, p_fixd );
}
Example #3
0
int load_file(char *file_name, char *lib_name) {

    struct object_file *o;
    unsigned char *data;
    static int id = 0;
    char *name;
    int size;


    o = malloc(sizeof(struct object_file));
    name = malloc(strlen(file_name)+1);
    if (o == NULL || name == NULL) {
        if (o != NULL)
            free(o);
        if (name != NULL)
            free(name);
        fprintf(stderr, "LOAD_FILE: Out of memory.\n");
        return FAILED;
    }

    if (load_file_data(file_name, &data, &size, lib_name) == FAILED) {
        free(name);
        free(o);
        return FAILED;
    }

    /* only valid for library files; bank 0 slot 0 base 0 assumed unless library is SUPERFREE */
    o->bank = 0;
    o->slot = 0;
    o->base = 0;
    o->base_defined = OFF;

    /* init the rest of the variables */
    o->source_file_names = NULL;
    o->memorymap = NULL;
    o->exported_defines = NULL;
    o->data_blocks = NULL;
    o->source_file_names_list = NULL;

    if (obj_first == NULL) {
        obj_first = o;
        obj_last = o;
    }
    else {
        obj_last->next = o;
        obj_last = o;
    }

    o->next = NULL;
    o->size = size;
    o->data = data;

    strcpy(name, file_name);
    o->name = name;
    o->id = id++;

    return SUCCEEDED;
}
Example #4
0
int load_file(char *fn, int state, int bank, int slot, int base, int base_defined) {

  struct object_file *o;
  unsigned char *data;
  static int id = 0;
  char *n;
  int size;

  o = malloc(sizeof(struct object_file));
  n = malloc(strlen(fn)+1);
  if (o == NULL || n == NULL) {
    if (o != NULL)
      free(o);
    if (n != NULL)
      free(n);
    fprintf(stderr, "LOAD_FILE: Out of memory.\n");
    return FAILED;
  }

  if (load_file_data(fn, &data, &size) == FAILED) {
    free(n);
    free(o);
    return FAILED;
  }

  /* only valid for library files */
  o->bank = bank;
  o->slot = slot;
  o->base = base;
  o->base_defined = base_defined;

  /* init the rest of the variables */
  o->source_file_names = NULL;
  o->memorymap = NULL;
  o->exported_defines = NULL;
  o->data_blocks = NULL;
  o->source_file_names_list = NULL;

  if (obj_first == NULL) {
    obj_first = o;
    obj_last = o;
  }
  else {
    obj_last->next = o;
    obj_last = o;
  }

  o->next = NULL;
  o->size = size;
  o->data = data;

  strcpy(n, fn);
  o->name = n;
  o->id = id++;

  return SUCCEEDED;
}
Example #5
0
/* * * * * * * * * * * * *

   load_file loads all the contents of a file into malloc-ed memory.
   Its argument is the name of the file to read in; the returned
   result is the NUL terminated contents of the file.  The file
   is presumed to be an ASCII text file containing no NULs.  */
char *
load_file ( const char* fname )
{
  struct stat stbf;
  char* res;

  if (stat (fname, &stbf) != 0)
    {
      if (NOT_SILENT)
        fprintf (stderr, "error %d (%s) stat-ing %s\n",
                 errno, xstrerror (errno), fname );
      return (char *) NULL;
    }
  if (stbf.st_size == 0)
    return (char*)NULL;

  /*  Make the data map size one larger than the file size for documentation
      purposes.  Truth is that there will be a following NUL character if
      the file size is not a multiple of the page size.  If it is a multiple,
      then this adjustment sometimes fails anyway.  */
  data_map_size = stbf.st_size+1;
  data_map_fd   = open (fname, O_RDONLY);
  ttl_data_size += data_map_size-1;

  if (data_map_fd < 0)
    {
      if (NOT_SILENT)
        fprintf (stderr, "error %d (%s) opening %s for read\n",
                 errno, xstrerror (errno), fname);
      return (char*)NULL;
    }

#ifdef HAVE_MMAP_FILE
  curr_data_mapped = BOOL_TRUE;

  /*  IF the file size is a multiple of the page size,
      THEN sometimes you will seg fault trying to access a trailing byte */
  if ((stbf.st_size & (getpagesize()-1)) == 0)
    res = (char*)BAD_ADDR;
  else
    res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
                       MAP_PRIVATE, data_map_fd, 0);
  if (res == (char*)BAD_ADDR)
#endif
    {
      FILE* fp = fdopen (data_map_fd, "r");
      curr_data_mapped = BOOL_FALSE;
      res = load_file_data (fp);
      fclose (fp);
    }

  return res;
}
Example #6
0
/* Sets errno on error (== NULL),
 * Always ensures terminating zero */
char *
load_file_at (int         dirfd,
              const char *path)
{
  int fd;
  char *data;
  int errsv;

  fd = openat (dirfd, path, O_CLOEXEC | O_RDONLY);
  if (fd == -1)
    return NULL;

  data = load_file_data (fd, NULL);

  errsv = errno;
  close (fd);
  errno = errsv;

  return data;
}
Example #7
0
int load_files(char *argv[], int argc) {

  int state = STATE_NONE, i, x, line, bank, slot, base, bank_defined, slot_defined, base_defined, n;
  char tmp[1024], token[1024], tmp_token[MAX_NAME_LENGTH];
  struct label *l;
  FILE *fop, *f;

  
  fop = fopen(argv[argc - 2], "rb");
  if (fop == NULL) {
    fprintf(stderr, "LOAD_FILES: Could not open file \"%s\".\n", argv[argc - 2]);
    return FAILED;
  }

  line = 0;
  while (fgets(tmp, 255, fop) != NULL) {
    line++;
    x = 0;

    if (tmp[0] == ';' || tmp[0] == '*' || tmp[0] == '#' || tmp[0] == 0x0D || tmp[0] == 0x0A)
      continue;

    /* remove garbage from the end */
    for (i = 0; !(tmp[i] == 0x0D || tmp[i] == 0x0A || tmp[i] == 0x00); i++)
      ;
    tmp[i] = 0;

    /* empty line check */
    if (get_next_token(tmp, token, &x) == FAILED)
      continue;

    /* first checks */
    if (token[0] == '[') {
      if (strcmp("[objects]", token) == 0) {
	state = STATE_OBJECT;
	continue;
      }
      else if (strcmp("[libraries]", token) == 0) {
	state = STATE_LIBRARY;
	continue;
      }
      else if (strcmp("[header]", token) == 0) {
	state = STATE_HEADER;
	continue;
      }
      else if (strcmp("[footer]", token) == 0) {
	state = STATE_FOOTER;
	continue;
      }
      else if (strcmp("[definitions]", token) == 0) {
	state = STATE_DEFINITION;
	continue;
      }
      else {
	fprintf(stderr, "%s:%d LOAD_FILES: Unknown group \"%s\".\n", argv[argc - 2], line, token);
	fclose(fop);
	return FAILED;
      }
    }

    if (state == STATE_NONE) {
      fprintf(stderr, "%s:%d: LOAD_FILES: Before file \"%s\" can be loaded you must define a group for it.\n", argv[argc - 2], line, token);
      fclose(fop);
      return FAILED;
    }

    bank_defined = OFF;
    slot_defined = OFF;
    base_defined = OFF;
    bank = 0;
    slot = 0;
    base = 0;

    /* definition loading? */
    if (state == STATE_DEFINITION) {
      l = calloc(1, sizeof(struct label));
      if (l == NULL) {
	fprintf(stderr, "LOAD_FILES: Out of memory.\n");
	return FAILED;
      }
      strcpy(l->name, token);
      l->status = LABEL_STATUS_DEFINE;
      l->bank = 0;
      l->slot = 0;
      l->base = 0;

      if (get_next_number(&tmp[x], &n, &x) == FAILED) {
	fprintf(stderr, "%s:%d: LOAD_FILES: Error in DEFINITION value.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }

      l->address = n;
      add_label(l);
      continue;
    }
    /* header loading? */
    else if (state == STATE_HEADER) {
      if (file_header != NULL) {
	fprintf(stderr, "%s:%d: LOAD_FILES: There can be only one header file.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }

      if (load_file_data(token, &file_header, &file_header_size) == FAILED) {
	fclose(fop);
	return FAILED;
      }
      if (get_next_token(&tmp[x], token, &x) == FAILED)
	continue;

      fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
      fclose(fop);
      return FAILED;
    }
    /* footer loading? */
    else if (state == STATE_FOOTER) {
      if (file_footer != NULL) {
	fprintf(stderr, "%s:%d: LOAD_FILES: There can be only one footer file.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }

      if (load_file_data(token, &file_footer, &file_footer_size) == FAILED) {
	fclose(fop);
	return FAILED;
      }
      if (get_next_token(&tmp[x], token, &x) == FAILED)
	continue;

      fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
      fclose(fop);
      return FAILED;
    }
    /* library loading? */
    else if (state == STATE_LIBRARY) {
      i = SUCCEEDED;
      while (i == SUCCEEDED) {
	if (strcmp(token, "bank") == 0 || strcmp(token, "BANK") == 0) {
	  if (bank_defined == ON) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: BANK defined for the second time for a library file.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	  bank_defined = ON;
	  
	  if (get_next_number(&tmp[x], &bank, &x) == FAILED) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: Error in BANK number.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	}
	else if (strcmp(token, "slot") == 0 || strcmp(token, "SLOT") == 0) {
	  if (slot_defined == ON) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: SLOT defined for the second time for a library file.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	  slot_defined = ON;
	  
	  if (get_next_number(&tmp[x], &slot, &x) == FAILED) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: Error in SLOT number.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	}
	else if (strcmp(token, "base") == 0 || strcmp(token, "BASE") == 0) {
	  if (base_defined == ON) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: BASE defined for the second time for a library file.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	  base_defined = ON;
	  
	  if (get_next_number(&tmp[x], &base, &x) == FAILED) {
	    fprintf(stderr, "%s:%d: LOAD_FILES: Error in BASE number.\n", argv[argc - 2], line);
	    fclose(fop);
	    return FAILED;
	  }
	}
	else
	  break;
	
	i = get_next_token(&tmp[x], token, &x);
      }
      
      if (i == FAILED) {
	fprintf(stderr, "%s:%d: LOAD_FILES: No library to load.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }
      if (slot_defined == OFF) {
	fprintf(stderr, "%s:%d: LOAD_FILES: Library file requires a SLOT.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }
      if (bank_defined == OFF) {
	fprintf(stderr, "%s:%d: LOAD_FILES: Library file requires a BANK.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }
      
      if (use_libdir == YES) {
        f = fopen(token, "rb");
      
        /* use the current working directory if the library isn't found in the ext_libdir directory */
        if (f == NULL)
          sprintf(tmp_token, "%s%s", ext_libdir, token);
        else {
          sprintf(tmp_token, "%s", token);
	  fclose(f);
	}
      }
      else
        sprintf(tmp_token, "%s", token);
      
      if (load_file(tmp_token, bank, slot, base, base_defined) == FAILED) {
	fclose(fop);
	return FAILED;
      }
      
      if (get_next_token(&tmp[x], token, &x) == SUCCEEDED) {
	fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
	fclose(fop);
	return FAILED;
      }
      
      continue;
    }
    /* object file loading */
    else if (load_file(token, 0, 0, 0, OFF) == FAILED) {
      fclose(fop);
      return FAILED;
    }
    if (get_next_token(&tmp[x], token, &x) == FAILED)
      continue;

    fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
    fclose(fop);
    return FAILED;
  }

  fclose(fop);

  return SUCCEEDED;
}
Example #8
0
static void
parse_args_recurse (int *argcp,
		    char ***argvp,
		    bool in_file,
		    int *total_parsed_argc_p)
{
  SetupOp *op;
  int argc = *argcp;
  char **argv = *argvp;
  /* I can't imagine a case where someone wants more than this.
   * If you do...you should be able to pass multiple files
   * via a single tmpfs and linking them there, etc.
   *
   * We're adding this hardening due to precedent from
   * http://googleprojectzero.blogspot.com/2014/08/the-poisoned-nul-byte-2014-edition.html
   *
   * I picked 9000 because the Internet told me to and it was hard to
   * resist.
   */
  static const uint32_t MAX_ARGS = 9000;

  if (*total_parsed_argc_p > MAX_ARGS)
    die ("Exceeded maximum number of arguments %u", MAX_ARGS);

  while (argc > 0)
    {
      const char *arg = argv[0];

      if (strcmp (arg, "--help") == 0)
        usage (EXIT_SUCCESS);
      else if (strcmp (arg, "--version") == 0)
        {
          printf ("%s\n", PACKAGE_STRING);
          exit (0);
        }
      else if (strcmp (arg, "--args") == 0)
        {
          int the_fd;
          char *endptr;
          char *data, *p;
          char *data_end;
          size_t data_len;
          cleanup_free char **data_argv = NULL;
          char **data_argv_copy;
          int data_argc;
          int i;

          if (in_file)
            die ("--args not supported in arguments file");

          if (argc < 2)
            die ("--args takes an argument");

          the_fd = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || the_fd < 0)
            die ("Invalid fd: %s", argv[1]);

          data = load_file_data (the_fd, &data_len);
          if (data == NULL)
            die_with_error ("Can't read --args data");

          data_end = data + data_len;
          data_argc = 0;

          p = data;
          while (p != NULL && p < data_end)
            {
              data_argc++;
	      (*total_parsed_argc_p)++;
	      if (*total_parsed_argc_p > MAX_ARGS)
		die ("Exceeded maximum number of arguments %u", MAX_ARGS);
              p = memchr (p, 0, data_end - p);
              if (p != NULL)
                p++;
            }

          data_argv = xcalloc (sizeof (char *) * (data_argc + 1));

          i = 0;
          p = data;
          while (p != NULL && p < data_end)
            {
              /* Note: load_file_data always adds a nul terminator, so this is safe
               * even for the last string. */
              data_argv[i++] = p;
              p = memchr (p, 0, data_end - p);
              if (p != NULL)
                p++;
            }

          data_argv_copy = data_argv; /* Don't change data_argv, we need to free it */
          parse_args_recurse (&data_argc, &data_argv_copy, TRUE, total_parsed_argc_p);

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--unshare-user") == 0)
        opt_unshare_user = TRUE;
      else if (strcmp (arg, "--unshare-ipc") == 0)
        opt_unshare_ipc = TRUE;
      else if (strcmp (arg, "--unshare-pid") == 0)
        opt_unshare_pid = TRUE;
      else if (strcmp (arg, "--unshare-net") == 0)
        opt_unshare_net = TRUE;
      else if (strcmp (arg, "--unshare-uts") == 0)
        opt_unshare_uts = TRUE;
      else if (strcmp (arg, "--chdir") == 0)
        {
          if (argc < 2)
            die ("--chdir takes one argument");

          opt_chdir_path = argv[1];
          argv++;
          argc--;
        }
      else if (strcmp (arg, "--bind") == 0)
        {
          if (argc < 3)
            die ("--bind takes two arguments");

          op = setup_op_new (SETUP_BIND_MOUNT);
          op->source = canonicalize_file_name (argv[1]);
          if (op->source == NULL)
            die_with_error ("Can't find source path %s", argv[1]);
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--ro-bind") == 0)
        {
          if (argc < 3)
            die ("--ro-bind takes two arguments");

          op = setup_op_new (SETUP_RO_BIND_MOUNT);
          op->source = canonicalize_file_name (argv[1]);
          if (op->source == NULL)
            die_with_error ("Can't find source path %s", argv[1]);
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--dev-bind") == 0)
        {
          if (argc < 3)
            die ("--dev-bind takes two arguments");

          op = setup_op_new (SETUP_DEV_BIND_MOUNT);
          op->source = canonicalize_file_name (argv[1]);
          if (op->source == NULL)
            die_with_error ("Can't find source path %s", argv[1]);
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--proc") == 0)
        {
          if (argc < 2)
            die ("--proc takes an argument");

          op = setup_op_new (SETUP_MOUNT_PROC);
          op->dest = argv[1];

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--exec-label") == 0)
        {
          if (argc < 2)
            die ("--exec-label takes an argument");
          opt_exec_label = argv[1];
          die_unless_label_valid (opt_exec_label);

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--file-label") == 0)
        {
          if (argc < 2)
            die ("--file-label takes an argument");
          opt_file_label = argv[1];
          die_unless_label_valid (opt_file_label);
          if (label_create_file (opt_file_label))
            die_with_error ("--file-label setup failed");

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--dev") == 0)
        {
          if (argc < 2)
            die ("--dev takes an argument");

          op = setup_op_new (SETUP_MOUNT_DEV);
          op->dest = argv[1];
          opt_needs_devpts = TRUE;

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--tmpfs") == 0)
        {
          if (argc < 2)
            die ("--tmpfs takes an argument");

          op = setup_op_new (SETUP_MOUNT_TMPFS);
          op->dest = argv[1];

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--mqueue") == 0)
        {
          if (argc < 2)
            die ("--mqueue takes an argument");

          op = setup_op_new (SETUP_MOUNT_MQUEUE);
          op->dest = argv[1];

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--dir") == 0)
        {
          if (argc < 2)
            die ("--dir takes an argument");

          op = setup_op_new (SETUP_MAKE_DIR);
          op->dest = argv[1];

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--file") == 0)
        {
          int file_fd;
          char *endptr;

          if (argc < 3)
            die ("--file takes two arguments");

          file_fd = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || file_fd < 0)
            die ("Invalid fd: %s", argv[1]);

          op = setup_op_new (SETUP_MAKE_FILE);
          op->fd = file_fd;
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--bind-data") == 0)
        {
          int file_fd;
          char *endptr;

          if (argc < 3)
            die ("--bind-data takes two arguments");

          file_fd = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || file_fd < 0)
            die ("Invalid fd: %s", argv[1]);

          op = setup_op_new (SETUP_MAKE_BIND_FILE);
          op->fd = file_fd;
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--symlink") == 0)
        {
          if (argc < 3)
            die ("--symlink takes two arguments");

          op = setup_op_new (SETUP_MAKE_SYMLINK);
          op->source = argv[1];
          op->dest = argv[2];

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--lock-file") == 0)
        {
          if (argc < 2)
            die ("--lock-file takes an argument");

          (void)lock_file_new (argv[1]);

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--sync-fd") == 0)
        {
          int the_fd;
          char *endptr;

          if (argc < 2)
            die ("--sync-fd takes an argument");

          the_fd = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || the_fd < 0)
            die ("Invalid fd: %s", argv[1]);

          opt_sync_fd = the_fd;

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--seccomp") == 0)
        {
          int the_fd;
          char *endptr;

          if (argc < 2)
            die ("--seccomp takes an argument");

          the_fd = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || the_fd < 0)
            die ("Invalid fd: %s", argv[1]);

          opt_seccomp_fd = the_fd;

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--setenv") == 0)
        {
          if (argc < 3)
            die ("--setenv takes two arguments");

          xsetenv (argv[1], argv[2], 1);

          argv += 2;
          argc -= 2;
        }
      else if (strcmp (arg, "--unsetenv") == 0)
        {
          if (argc < 2)
            die ("--unsetenv takes an argument");

          xunsetenv (argv[1]);

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--uid") == 0)
        {
          int the_uid;
          char *endptr;

          if (argc < 2)
            die ("--uid takes an argument");

          the_uid = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || the_uid < 0)
            die ("Invalid uid: %s", argv[1]);

          opt_sandbox_uid = the_uid;

          argv += 1;
          argc -= 1;
        }
      else if (strcmp (arg, "--gid") == 0)
        {
          int the_gid;
          char *endptr;

          if (argc < 2)
            die ("--gid takes an argument");

          the_gid = strtol (argv[1], &endptr, 10);
          if (argv[1][0] == 0 || endptr[0] != 0 || the_gid < 0)
            die ("Invalid gid: %s", argv[1]);

          opt_sandbox_gid = the_gid;

          argv += 1;
          argc -= 1;
        }
      else if (*arg == '-')
        die ("Unknown option %s", arg);
      else
        break;

      argv++;
      argc--;
    }

  *argcp = argc;
  *argvp = argv;
}
Example #9
0
int
main (int argc,
      char **argv)
{
  mode_t old_umask;
  cleanup_free char *base_path = NULL;
  int clone_flags;
  char *old_cwd = NULL;
  pid_t pid;
  int event_fd = -1;
  const char *new_cwd;
  uid_t ns_uid;
  gid_t ns_gid;

  /* Get the (optional) capabilities we need, drop root */
  acquire_caps ();

  /* Never gain any more privs during exec */
  if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
    die_with_error ("prctl(PR_SET_NO_NEW_CAPS) failed");

  /* The initial code is run with high permissions
     (i.e. CAP_SYS_ADMIN), so take lots of care. */

  argv0 = argv[0];

  if (isatty (1))
    host_tty_dev = ttyname (1);

  argv++;
  argc--;

  if (argc == 0)
    usage (EXIT_FAILURE);

  parse_args (&argc, &argv);

  /* We have to do this if we weren't installed setuid, so let's just DWIM */
  if (!is_privileged)
    opt_unshare_user = TRUE;

  if (argc == 0)
    usage (EXIT_FAILURE);

  __debug__(("Creating root mount point\n"));

  uid = getuid ();
  if (opt_sandbox_uid == -1)
    opt_sandbox_uid = uid;
  gid = getgid ();
  if (opt_sandbox_gid == -1)
    opt_sandbox_gid = gid;

  if (!opt_unshare_user && opt_sandbox_uid != uid)
    die ("Specifying --uid requires --unshare-user");

  if (!opt_unshare_user && opt_sandbox_gid != gid)
    die ("Specifying --gid requires --unshare-user");

  /* We need to read stuff from proc during the pivot_root dance, etc.
     Lets keep a fd to it open */
  proc_fd = open ("/proc", O_RDONLY | O_PATH);
  if (proc_fd == -1)
    die_with_error ("Can't open /proc");

  /* We need *some* mountpoint where we can mount the root tmpfs.
     We first try in /run, and if that fails, try in /tmp. */
  base_path = xasprintf ("/run/user/%d/.bubblewrap", uid);
  if (mkdir (base_path, 0755) && errno != EEXIST)
    {
      free (base_path);
      base_path = xasprintf ("/tmp/.bubblewrap-%d", uid);
      if (mkdir (base_path, 0755) && errno != EEXIST)
        die_with_error ("Creating root mountpoint failed");
    }

  __debug__(("creating new namespace\n"));

  if (opt_unshare_pid)
    {
      event_fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
      if (event_fd == -1)
	die_with_error ("eventfd()");
    }

  /* We block sigchild here so that we can use signalfd in the monitor. */
  block_sigchild ();

  clone_flags = SIGCHLD | CLONE_NEWNS;
  if (opt_unshare_user)
    clone_flags |= CLONE_NEWUSER;
  if (opt_unshare_pid)
    clone_flags |= CLONE_NEWPID;
  if (opt_unshare_net)
    clone_flags |= CLONE_NEWNET;
  if (opt_unshare_ipc)
    clone_flags |= CLONE_NEWIPC;
  if (opt_unshare_uts)
    clone_flags |= CLONE_NEWUTS;

  pid = raw_clone (clone_flags, NULL);
  if (pid == -1)
    {
      if (opt_unshare_user)
        {
          if (errno == EINVAL)
            die ("Creating new namespace failed, likely because the kernel does not support user namespaces.  bwrap must be installed setuid on such systems.");
          else if (errno == EPERM && !is_privileged)
            die ("No permissions to creating new namespace, likely because the kernel does not allow non-privileged user namespaces. On e.g. debian this can be enabled with 'sysctl kernel.unprivileged_userns_clone=1'.");
        }

      die_with_error ("Creating new namespace failed");
    }

  if (pid != 0)
    {
      /* Initial launched process, wait for exec:ed command to exit */

      /* We don't need any caps in the launcher, drop them immediately. */
      drop_caps ();
      monitor_child (event_fd);
      exit (0); /* Should not be reached, but better safe... */
    }

  if (opt_unshare_net && loopback_setup () != 0)
    die ("Can't create loopback device");

  ns_uid = opt_sandbox_uid;
  ns_gid = opt_sandbox_gid;
  if (opt_unshare_user)
    {
      if (opt_needs_devpts)
        {
          /* This is a bit hacky, but we need to first map the real uid/gid to
             0, otherwise we can't mount the devpts filesystem because root is
             not mapped. Later we will create another child user namespace and
             map back to the real uid */
          ns_uid = 0;
          ns_gid = 0;
        }

      write_uid_gid_map (ns_uid, uid,
                         ns_gid, gid,
                         TRUE);
    }

  old_umask = umask (0);

  /* Mark everything as slave, so that we still
   * receive mounts from the real root, but don't
   * propagate mounts to the real root. */
  if (mount (NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
    die_with_error ("Failed to make / slave");

  /* Create a tmpfs which we will use as / in the namespace */
  if (mount ("", base_path, "tmpfs", MS_NODEV|MS_NOSUID, NULL) != 0)
    die_with_error ("Failed to mount tmpfs");

  old_cwd = get_current_dir_name ();

  /* Chdir to the new root tmpfs mount. This will be the CWD during
     the entire setup. Access old or new root via "oldroot" and "newroot". */
  if (chdir (base_path) != 0)
      die_with_error ("chdir base_path");

  /* We create a subdir "$base_path/newroot" for the new root, that
   * way we can pivot_root to base_path, and put the old root at
   * "$base_path/oldroot". This avoids problems accessing the oldroot
   * dir if the user requested to bind mount something over / */

  if (mkdir ("newroot", 0755))
    die_with_error ("Creating newroot failed");

  if (mkdir ("oldroot", 0755))
    die_with_error ("Creating oldroot failed");

  if (pivot_root (base_path, "oldroot"))
    die_with_error ("pivot_root");

  if (chdir ("/") != 0)
    die_with_error ("chdir / (base path)");

  if (is_privileged)
    {
      pid_t child;
      int privsep_sockets[2];

      if (socketpair (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, privsep_sockets) != 0)
        die_with_error ("Can't create privsep socket");

      child = fork ();
      if (child == -1)
        die_with_error ("Can't fork unprivileged helper");

      if (child == 0)
        {
          /* Unprivileged setup process */
          drop_caps ();
          close (privsep_sockets[0]);
          setup_newroot (opt_unshare_pid, privsep_sockets[1]);
          exit (0);
        }
      else
        {
          uint32_t buffer[2048];  /* 8k, but is int32 to guarantee nice alignment */
          uint32_t op, flags;
          const char *arg1, *arg2;
          cleanup_fd int unpriv_socket = -1;

          unpriv_socket = privsep_sockets[0];
          close (privsep_sockets[1]);

          do
            {
              op = read_priv_sec_op (unpriv_socket, buffer, sizeof (buffer),
                                     &flags, &arg1, &arg2);
              privileged_op (-1, op, flags, arg1, arg2);
              if (write (unpriv_socket, buffer, 1) != 1)
                die ("Can't write to op_socket");
            }
          while (op != PRIV_SEP_OP_DONE);

          /* Continue post setup */
        }
    }
  else
    setup_newroot (opt_unshare_pid, -1);

  /* The old root better be rprivate or we will send unmount events to the parent namespace */
  if (mount ("oldroot", "oldroot", NULL, MS_REC|MS_PRIVATE, NULL) != 0)
    die_with_error ("Failed to make old root rprivate");

  if (umount2 ("oldroot", MNT_DETACH))
    die_with_error ("unmount old root");

  if (opt_unshare_user &&
      (ns_uid != opt_sandbox_uid || ns_gid != opt_sandbox_gid))
    {
      /* Now that devpts is mounted and we've no need for mount
         permissions we can create a new userspace and map our uid
         1:1 */

      if (unshare (CLONE_NEWUSER))
        die_with_error ("unshare user ns");

      write_uid_gid_map (opt_sandbox_uid, ns_uid,
                         opt_sandbox_gid, ns_gid,
                         FALSE);
    }

  /* Now make /newroot the real root */
  if (chdir ("/newroot") != 0)
    die_with_error ("chdir newroot");
  if (chroot ("/newroot") != 0)
    die_with_error ("chroot /newroot");
  if (chdir ("/") != 0)
    die_with_error ("chdir /");

  /* Now we have everything we need CAP_SYS_ADMIN for, so drop it */
  drop_caps ();

  if (opt_seccomp_fd != -1)
    {
      cleanup_free char *seccomp_data = NULL;
      size_t seccomp_len;
      struct sock_fprog prog;

      seccomp_data = load_file_data (opt_seccomp_fd, &seccomp_len);
      if (seccomp_data == NULL)
        die_with_error ("Can't read seccomp data");

      if (seccomp_len % 8 != 0)
        die ("Invalide seccomp data, must be multiple of 8");

      prog.len = seccomp_len / 8;
      prog.filter = (struct sock_filter *)seccomp_data;

      close (opt_seccomp_fd);

      if (prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0)
	die_with_error ("prctl(PR_SET_SECCOMP)");
    }

  umask (old_umask);

  new_cwd = "/";
  if (opt_chdir_path)
    {
      if (chdir (opt_chdir_path))
        die_with_error ("Can't chdir to %s", opt_chdir_path);
      new_cwd = opt_chdir_path;
    }
  else if (chdir (old_cwd) == 0)
    {
      /* If the old cwd is mapped in the sandbox, go there */
      new_cwd = old_cwd;
    }
  else
    {
      /* If the old cwd is not mapped, go to home */
      const char *home = getenv ("HOME");
      if (home != NULL &&
          chdir (home) == 0)
        new_cwd = home;
    }
  xsetenv ("PWD", new_cwd, 1);
  free (old_cwd);

  __debug__(("forking for child\n"));

  if (opt_unshare_pid || lock_files != NULL || opt_sync_fd != -1)
    {
      /* We have to have a pid 1 in the pid namespace, because
       * otherwise we'll get a bunch of zombies as nothing reaps
       * them. Alternatively if we're using sync_fd or lock_files we
       * need some process to own these.
       */

      pid = fork ();
      if (pid == -1)
        die_with_error("Can't fork for pid 1");

      if (pid != 0)
        {
          /* Close fds in pid 1, except stdio and optionally event_fd
             (for syncing pid 2 lifetime with monitor_child) and
             opt_sync_fd (for syncing sandbox lifetime with outside
             process).
             Any other fds will been passed on to the child though. */
          {
            int dont_close[3];
            int j = 0;
            if (event_fd != -1)
              dont_close[j++] = event_fd;
            if (opt_sync_fd != -1)
              dont_close[j++] = opt_sync_fd;
            dont_close[j++] = -1;
            fdwalk (proc_fd, close_extra_fds, dont_close);
          }

          return do_init (event_fd, pid);
        }
    }

  __debug__(("launch executable %s\n", argv[0]));

  if (proc_fd != -1)
    close (proc_fd);

  if (opt_sync_fd != -1)
    close (opt_sync_fd);

  /* We want sigchild in the child */
  unblock_sigchild ();

  if (label_exec (opt_exec_label) == -1)
    die_with_error ("label_exec %s", argv[0]);

  if (execvp (argv[0], argv) == -1)
    die_with_error ("execvp %s", argv[0]);

  return 0;
}
Example #10
0
int load_files(char *argv[], int argc, int have_flags) {

  struct label *l;
  int st = STATE_NONE, i, x, line, bank, slot, base, bank_defined, slot_defined, base_defined, n;
  char tmp[1024], ou[1024];
  FILE *fop;

  if (no_std_libraries == OFF) {
    char* stdlibs[] = {
#define LIBDIR PREFIX "/lib"
      LIBDIR "/crt0_snes.obj",
      LIBDIR "/libm.obj",
      LIBDIR "/libtcc.obj",
      LIBDIR "/libc.obj",
      NULL
    };
    char** sl;
    for (sl = stdlibs; *sl; sl++) {
      if (load_file(*sl, STATE_OBJECT, 0, 0, 0, OFF) == FAILED) return FAILED;
    }
  }
  if (object_file_parameters == ON) {
    for (i = (have_flags ? 2 : 1); i < argc - 1 ; i++) {
      if (load_file(argv[i], STATE_OBJECT, 0, 0, 0, OFF) == FAILED) return FAILED;
    }
  }
  else {
    fop = fopen(argv[argc - 2], "rb");
    if (fop == NULL) {
      fprintf(stderr, "LOAD_FILES: Could not open file \"%s\".\n", argv[argc - 2]);
      return FAILED;
    }

    line = 0;
    while (fgets(tmp, 255, fop) != NULL) {
      line++;
      x = 0;

      if (tmp[0] == ';' || tmp[0] == '*' || tmp[0] == '#' || tmp[0] == 0x0D || tmp[0] == 0x0A)
        continue;

      /* remove garbage from the end */
      for (i = 0; !(tmp[i] == 0x0D || tmp[i] == 0x0A); i++);
      tmp[i] = 0;

      /* empty line check */
      if (get_next_token(tmp, ou, &x) == FAILED)
        continue;

      /* first checks */
      if (ou[0] == '[') {
        if (strcmp("[objects]", ou) == 0) {
                                  st = STATE_OBJECT;
                                  continue;
        }
        else if (strcmp("[libraries]", ou) == 0) {
                                  st = STATE_LIBRARY;
                                  continue;
        }
        else if (strcmp("[header]", ou) == 0) {
                                  st = STATE_HEADER;
                                  continue;
        }
        else if (strcmp("[footer]", ou) == 0) {
                                  st = STATE_FOOTER;
                                  continue;
        }
        else if (strcmp("[definitions]", ou) == 0) {
                                  st = STATE_DEFINITION;
                                  continue;
        }
        else {
                                  fprintf(stderr, "%s:%d LOAD_FILES: Unknown group \"%s\".\n", argv[argc - 2], line, ou);
                                  fclose(fop);
                                  return FAILED;
        }
      }

      if (st == STATE_NONE) {
        fprintf(stderr, "%s:%d: LOAD_FILES: Before file \"%s\" can be loaded you must define a group for it.\n", argv[argc - 2], line, ou);
        fclose(fop);
        return FAILED;
      }

      bank_defined = OFF;
      slot_defined = OFF;
      base_defined = OFF;
      bank = 0;
      slot = 0;
      base = 0;

      /* definition loading? */
      if (st == STATE_DEFINITION) {
        l = malloc(sizeof(struct label));
        if (l == NULL) {
                                  fprintf(stderr, "LOAD_FILES: Out of memory.\n");
                                  return FAILED;
        }
        strcpy(l->name, ou);
        l->status = LABEL_STATUS_DEFINE;
        l->bank = 0;
        l->slot = 0;
        l->base = 0;

        if (get_next_number(&tmp[x], &n, &x) == FAILED) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: Error in DEFINITION value.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }

        l->address = n;
        add_label(l);
        continue;
      }
      /* header loading? */
      else if (st == STATE_HEADER) {
        if (file_header != NULL) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: There can be only one header file.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }

        if (load_file_data(ou, &file_header, &file_header_size) == FAILED) {
                                  fclose(fop);
                                  return FAILED;
        }
        if (get_next_token(&tmp[x], ou, &x) == FAILED)
                                  continue;

        fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
        fclose(fop);
        return FAILED;
      }
      /* footer loading? */
      else if (st == STATE_FOOTER) {
        if (file_footer != NULL) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: There can be only one footer file.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }

        if (load_file_data(ou, &file_footer, &file_footer_size) == FAILED) {
                                  fclose(fop);
                                  return FAILED;
        }
        if (get_next_token(&tmp[x], ou, &x) == FAILED)
                                  continue;

        fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
        fclose(fop);
        return FAILED;
      }
      /* library loading? */
      else if (st == STATE_LIBRARY) {
        i = SUCCEEDED;
        while (i == SUCCEEDED) {
                                  if (strcmp(ou, "bank") == 0 || strcmp(ou, "BANK") == 0) {
                                          if (bank_defined == ON) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: BANK defined for the second time for a library file.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                          bank_defined = ON;

                                          if (get_next_number(&tmp[x], &bank, &x) == FAILED) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: Error in BANK number.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                  }
                                  else if (strcmp(ou, "slot") == 0 || strcmp(ou, "SLOT") == 0) {
                                          if (slot_defined == ON) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: SLOT defined for the second time for a library file.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                          slot_defined = ON;

                                          if (get_next_number(&tmp[x], &slot, &x) == FAILED) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: Error in SLOT number.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                  }
                                  else if (strcmp(ou, "base") == 0 || strcmp(ou, "BASE") == 0) {
                                          if (base_defined == ON) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: BASE defined for the second time for a library file.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                          base_defined = ON;

                                          if (get_next_number(&tmp[x], &base, &x) == FAILED) {
                                                  fprintf(stderr, "%s:%d: LOAD_FILES: Error in BASE number.\n", argv[argc - 2], line);
                                                  fclose(fop);
                                                  return FAILED;
                                          }
                                  }
                                  else
                                          break;

                                  i = get_next_token(&tmp[x], ou, &x);
        }

        if (i == FAILED) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: No library to load.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }
        if (slot_defined == OFF) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: Library file requires a SLOT.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }
        if (bank_defined == OFF) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: Library file requires a BANK.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }

        if (load_file(ou, STATE_LIBRARY, bank, slot, base, base_defined) == FAILED) {
                                  fclose(fop);
                                  return FAILED;
        }

        if (get_next_token(&tmp[x], ou, &x) == SUCCEEDED) {
                                  fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
                                  fclose(fop);
                                  return FAILED;
        }

        continue;
      }
      /* object file loading */
      else if (load_file(ou, STATE_OBJECT, 0, 0, 0, OFF) == FAILED) {
        fclose(fop);
        return FAILED;
      }
      if (get_next_token(&tmp[x], ou, &x) == FAILED)
        continue;

      fprintf(stderr, "%s:%d: LOAD_FILES: Syntax error.\n", argv[argc - 2], line);
      fclose(fop);
      return FAILED;
    }

    fclose(fop);
  }

  return SUCCEEDED;
}