Example #1
0
/* consumestr: consumes a C string from a buffer @buf of length @length
 * @buf    Buffer to consume
 * @length Length of buffer
 *
 * Returns a pointer to the base of the string, or NULL for errors.
 */
char *consumestr(char **buf, size_t *buflength)
{
	size_t len = strnlen(*buf, *buflength);
	if (len == *buflength)
		/* There's no null-terminator */
		return NULL;
	return consumebytes(len + 1, buf, buflength);
}
Example #2
0
// Gets the next "bytes" bytes, regardless of whether they are available in the
// current buffer or not.  Returns a status code as described in decoder.int.h.
FORCEINLINE int32_t getbytes(upb_pbdecoder *d, void *buf, size_t bytes) {
  if (curbufleft(d) >= bytes) {
    // Buffer has enough data to satisfy.
    consumebytes(d, buf, bytes);
    return DECODE_OK;
  } else {
    return getbytes_slow(d, buf, bytes);
  }
}
Example #3
0
// Slow path for getting the next "bytes" bytes, regardless of whether they are
// available in the current buffer or not.  Returns a status code as described
// in decoder.int.h.
static NOINLINE int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
                                      size_t bytes) {
  const size_t avail = curbufleft(d);
  consumebytes(d, buf, avail);
  bytes -= avail;
  assert(bytes > 0);
  if (in_residual_buf(d, d->ptr)) {
    advancetobuf(d, d->buf_param, d->size_param);
  }
  if (curbufleft(d) >= bytes) {
    consumebytes(d, buf + avail, bytes);
    return DECODE_OK;
  } else if (d->data_end == d->delim_end) {
    seterr(d, "Submessage ended in the middle of a value or group");
    return upb_pbdecoder_suspend(d);
  } else {
    return suspend_save(d);
  }
}
Example #4
0
int minijail_unmarshal(struct minijail *j, char *serialized, size_t length)
{
	int i;
	int count;
	int ret = -EINVAL;

	if (length < sizeof(*j))
		goto out;
	memcpy((void *)j, serialized, sizeof(*j));
	serialized += sizeof(*j);
	length -= sizeof(*j);

	/* Potentially stale pointers not used as signals. */
	j->bindings_head = NULL;
	j->bindings_tail = NULL;
	j->filter_prog = NULL;

	if (j->user) {		/* stale pointer */
		char *user = consumestr(&serialized, &length);
		if (!user)
			goto clear_pointers;
		j->user = strdup(user);
		if (!j->user)
			goto clear_pointers;
	}

	if (j->chrootdir) {	/* stale pointer */
		char *chrootdir = consumestr(&serialized, &length);
		if (!chrootdir)
			goto bad_chrootdir;
		j->chrootdir = strdup(chrootdir);
		if (!j->chrootdir)
			goto bad_chrootdir;
	}

	if (j->chdir) {	/* stale pointer */
		char *chdirstr = consumestr(&serialized, &length);
		if (!chdirstr)
			goto bad_chdir;
		j->chdir = strdup(chdirstr);
		if (!j->chdir)
			goto bad_chdir;
	}

	if (j->flags.seccomp_filter && j->filter_len > 0) {
		size_t ninstrs = j->filter_len;
		if (ninstrs > (SIZE_MAX / sizeof(struct sock_filter)) ||
		    ninstrs > USHRT_MAX)
			goto bad_filters;

		size_t program_len = ninstrs * sizeof(struct sock_filter);
		void *program = consumebytes(program_len, &serialized, &length);
		if (!program)
			goto bad_filters;

		j->filter_prog = malloc(sizeof(struct sock_fprog));
		j->filter_prog->len = ninstrs;
		j->filter_prog->filter = malloc(program_len);
		memcpy(j->filter_prog->filter, program, program_len);
	}

	if (j->meta_file) {
		j->meta_file = NULL;
	}

	count = j->binding_count;
	j->binding_count = 0;
	for (i = 0; i < count; ++i) {
		int *writeable;
		const char *dest;
		const char *src = consumestr(&serialized, &length);
		if (!src)
			goto bad_bindings;
		dest = consumestr(&serialized, &length);
		if (!dest)
			goto bad_bindings;
		writeable = consumebytes(sizeof(*writeable), &serialized, &length);
		if (!writeable)
			goto bad_bindings;
		if (minijail_bind(j, src, dest, *writeable))
			goto bad_bindings;
	}

	close(j->syscall_pipe_fds[0]); /* read endpoint */
	j->syscall_pipe_fds[0] = -1;
	signum_fd = j->syscall_pipe_fds[1];

	return 0;

bad_bindings:
	if (j->flags.seccomp_filter && j->filter_len > 0) {
		free(j->filter_prog->filter);
		free(j->filter_prog);
	}
bad_filters:
	if (j->chrootdir)
		free(j->chrootdir);
bad_chdir:
	if (j->chdir)
		free(j->chdir);
bad_chrootdir:
	if (j->user)
		free(j->user);
clear_pointers:
	j->user = NULL;
	j->chrootdir = NULL;
	j->chdir = NULL;
out:
	return ret;
}