Пример #1
0
static int tee_supp_fs_readdir(struct tee_fs_rpc *fsrpc)
{
	DIR *dir = handle_lookup(&dir_handle_db, fsrpc->arg);
	struct dirent *dirent;
	size_t len;

	do
		dirent = readdir(dir);
	while (dirent != NULL && dirent->d_name[0] == '.');

	if (dirent == NULL) {
		fsrpc->len = 0;
		return -1;
	}

	len = strlen(dirent->d_name);
	if (len > PATH_MAX)
		return -1;

	len++;
	memcpy((char *)(fsrpc + 1), dirent->d_name, len);
	fsrpc->len = len;

	return 0;
}
void KVServer::run()
{
	while (1) {
		socklen_t remote_addr_len = sizeof(remote_addr);
		printf("Waiting for a packet ...\n");
		fflush(stdout);
		int rc = recvfrom(sock, buffer, MAX_KV_SIZE, 0, (sockaddr*)&remote_addr, &remote_addr_len);
		if (-1 == rc) {
			fprintf(stderr, "(KeyValueServer) Failed to receive packet!\n");
			exit(1);
		}
		lite_assert(rc<MAX_KV_SIZE);	// darn -- MAX_KV_SIZE too small for actual usage.

		lite_assert(rc>=(int)sizeof(KVRequest));
		KVRequest* request = (KVRequest*)buffer;

		switch (request->type) {
			case TYPE_LOOKUP:
				handle_lookup(request);
				break;
			case TYPE_INSERT:
				handle_insert(request);
				break;
			default:
				fprintf(stderr, "(KeyValueServer) Dropping malformed request with type %04x.\n", request->type);
				continue;
		}
	}

	// TODO:Doesn't clean-up after itself yet
	hash_table_free_discard(&db);
}
Пример #3
0
void web_handler( int rc, int sock ) {
	size_t clientfd;
	IP clientaddr;
	socklen_t addrlen_ret;
	char request_buf[1024];
	char reply_buf[(MAX_ADDRS+1)*FULL_ADDSTRLEN+2];
	char *cmd, *params;
	char *space, *delim;
	size_t n;

	addrlen_ret = sizeof(IP);
	clientfd = accept( sock, (struct sockaddr*)&clientaddr, &addrlen_ret );
	n = recv( clientfd, request_buf, sizeof(request_buf) - 1, 0 );

	/* Only handle GET requests. */
	if( n < 6 || strncmp( "GET /", request_buf, 5 ) != 0 ) {
		goto done;
	} else {
		cmd = request_buf + 5;
	}

	/* Safety first */
	request_buf[n] = '\0';

	space = strchr( cmd, ' ' );
	if( space == NULL ) {
		goto done;
	} else {
		*space = '\0';
	}

	delim = strchr( cmd, '?' );
	if( delim == NULL ) {
		goto done;
	} else {
		*delim = '\0';
		params = delim + 1;
	}

	log_debug( "WEB: cmd: '%s', params: '%s'\n", cmd, params);

	reply_buf[0] = '\n';
	reply_buf[1] = '\0';

	if( match( cmd, "lookup" ) ) {
		handle_lookup( reply_buf, params );
	} else if( match( cmd, "announce" ) ) {
		handle_announce( reply_buf, params );
	} else if( match( cmd, "blacklist" ) ) {
		handle_blacklist( reply_buf, params );
	} else {
		reply_buf[0] = '\0';
	}

	sendto( clientfd, reply_buf, strlen( reply_buf ), 0, (struct sockaddr*) &clientaddr, sizeof(IP) );

	done:;

	close( clientfd );
}
Пример #4
0
int tee_fs_write(int fd, const void *buf, size_t len)
{
	int res = -1;
	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
	struct tee_fs_rpc head = { 0 };

	if (len == 0) {
		res = 0;
		goto exit;
	}

	if (buf == NULL) {
		res = -1;
		goto exit;
	}

	if (fdp == NULL) {
		res = -1;
		goto exit;
	}

	/* fill in parameters */
	head.op = TEE_FS_WRITE;
	head.fd = fdp->nw_fd;
	head.len = len;

	res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_IN);
	if (res)
		goto exit;

	res = head.res;

exit:
	return res;
}
Пример #5
0
int tee_fs_read(int fd, void *buf, size_t len)
{
	int res = -1;
	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
	struct tee_fs_rpc head = { 0 };

	if (len == 0) {
		res = 0;
		goto exit;
	}

	if (fdp == NULL || buf == NULL) {
		res = -1;
		goto exit;
	}

	/* fill in parameters */
	head.op = TEE_FS_READ;
	head.fd = fdp->nw_fd;
	head.len = (uint32_t) len;

	res = tee_fs_send_cmd(&head, (void *)buf, len, TEE_FS_MODE_OUT);
	if (res)
		goto exit;

	res = head.res;

exit:
	return res;
}
Пример #6
0
static tee_fs_off_t sql_fs_lseek(TEE_Result *errno, int fd,
				 tee_fs_off_t offset, int whence)
{
	struct sql_fs_fd *fdp;
	tee_fs_off_t ret = -1;
	tee_fs_off_t raw_pos;
	tee_fs_off_t pos;

	DMSG("(fd: %d, offset: %" PRId64 ", whence: %d)...", fd, offset,
	     whence);

	mutex_lock(&sql_fs_mutex);

	*errno = TEE_ERROR_GENERIC;

	fdp = handle_lookup(&fs_db, fd);
	if (!fdp)
		goto exit_ret;

	sql_fs_begin_transaction_rpc();

	switch (whence) {
	case TEE_FS_SEEK_SET:
		pos = offset;
		break;

	case TEE_FS_SEEK_CUR:
		pos = fdp->pos + offset;
		break;

	case TEE_FS_SEEK_END:
		pos = fdp->meta.length + offset;
		break;

	default:
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit;
	}

	raw_pos = pos_to_raw(pos);
	if (raw_pos < 0)
		goto exit;
	raw_pos = tee_fs_rpc_lseek(OPTEE_MSG_RPC_CMD_SQL_FS, fd, raw_pos,
				   TEE_FS_SEEK_SET);
	if (raw_pos < 0)
		goto exit;
	ret = raw_to_pos(raw_pos);
	if (ret < 0)
		goto exit;

exit:
	sql_fs_end_transaction_rpc(ret < 0);
	fdp->pos = ret;
exit_ret:
	mutex_unlock(&sql_fs_mutex);
	DMSG("...%" PRId64, ret);
	return ret;
}
Пример #7
0
static int sql_fs_close(int fd)
{
	struct sql_fs_fd *fdp;
	int ret = -1;

	DMSG("(fd: %d)...", fd);

	mutex_lock(&sql_fs_mutex);

	fdp = handle_lookup(&fs_db, fd);
	if (!fdp)
		goto exit;

	tee_fs_rpc_close(OPTEE_MSG_RPC_CMD_SQL_FS, fd);
	put_fdp(fdp);

	ret = 0;
exit:
	mutex_unlock(&sql_fs_mutex);
	DMSG("...%d", ret);
	return ret;
}
Пример #8
0
tee_fs_off_t tee_fs_lseek(int fd, tee_fs_off_t offset, int whence)
{
	tee_fs_off_t res = -1;
	struct tee_fs_fd *fdp = handle_lookup(&fs_handle_db, fd);
	struct tee_fs_rpc head = { 0 };

	if (!fdp)
		goto exit;

	/* fill in parameters */
	head.op = TEE_FS_SEEK;
	head.fd = fdp->nw_fd;
	head.arg = offset;
	head.flags = whence;

	res = tee_fs_send_cmd(&head, NULL, 0, TEE_FS_MODE_NONE);
	if (res)
		goto exit;

	res = head.res;

exit:
	return res;
}
Пример #9
0
int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
                      uint64_t file_size, uint32_t block_size)
{
    int result;
    uint64_t mem = 0;
    uint64_t avail = 0;

    // If something's already mounted on our mountpoint, try to remove
    // it.  (Mostly in case of a previous abnormal exit.)
    umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_FORCE);

    if (block_size < 1024) {
        fprintf(stderr, "block size (%u) is too small\n", block_size);
        return -1;
    }
    if (block_size > (1<<22)) {   // 4 MiB
        fprintf(stderr, "block size (%u) is too large\n", block_size);
        return -1;
    }

    struct fuse_data fd;
    memset(&fd, 0, sizeof(fd));
    fd.vtab = vtab;
    fd.cookie = cookie;
    fd.file_size = file_size;
    fd.block_size = block_size;
    fd.file_blocks = (file_size == 0) ? 0 : (((file_size-1) / block_size) + 1);

    if (fd.file_blocks > (1<<18)) {
        fprintf(stderr, "file has too many blocks (%u)\n", fd.file_blocks);
        result = -1;
        goto done;
    }

    fd.hashes = (uint8_t*)calloc(fd.file_blocks, SHA256_DIGEST_SIZE);
    if (fd.hashes == NULL) {
        fprintf(stderr, "failed to allocate %d bites for hashes\n",
                fd.file_blocks * SHA256_DIGEST_SIZE);
        result = -1;
        goto done;
    }

    fd.uid = getuid();
    fd.gid = getgid();

    fd.curr_block = -1;
    fd.block_data = (uint8_t*)malloc(block_size);
    if (fd.block_data == NULL) {
        fprintf(stderr, "failed to allocate %d bites for block_data\n", block_size);
        result = -1;
        goto done;
    }
    fd.extra_block = (uint8_t*)malloc(block_size);
    if (fd.extra_block == NULL) {
        fprintf(stderr, "failed to allocate %d bites for extra_block\n", block_size);
        result = -1;
        goto done;
    }

    fd.block_cache_max_size = 0;
    fd.block_cache_size = 0;
    fd.block_cache = NULL;
    mem = free_memory();
    avail = mem - (INSTALL_REQUIRED_MEMORY + fd.file_blocks * sizeof(uint8_t*));
    if (mem > avail) {
        uint32_t max_size = avail / fd.block_size;
        if (max_size > fd.file_blocks) {
            max_size = fd.file_blocks;
        }
        // The cache must be at least 1% of the file size or two blocks,
        // whichever is larger.
        if (max_size >= fd.file_blocks/100 && max_size >= 2) {
            fd.block_cache_max_size = max_size;
            fd.block_cache = (uint8_t**)calloc(fd.file_blocks, sizeof(uint8_t*));
        }
    }

    signal(SIGTERM, sig_term);

    fd.ffd = open("/dev/fuse", O_RDWR);
    if (fd.ffd < 0) {
        perror("open /dev/fuse");
        result = -1;
        goto done;
    }

    char opts[256];
    snprintf(opts, sizeof(opts),
             ("fd=%d,user_id=%d,group_id=%d,max_read=%u,"
              "allow_other,rootmode=040000"),
             fd.ffd, fd.uid, fd.gid, block_size);

    result = mount("/dev/fuse", FUSE_SIDELOAD_HOST_MOUNTPOINT,
                   "fuse", MS_NOSUID | MS_NODEV | MS_RDONLY | MS_NOEXEC, opts);
    if (result < 0) {
        perror("mount");
        goto done;
    }
    uint8_t request_buffer[sizeof(struct fuse_in_header) + PATH_MAX*8];
    while (!terminated) {
        fd_set fds;
        struct timeval tv;
        FD_ZERO(&fds);
        FD_SET(fd.ffd, &fds);
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        int rc = select(fd.ffd+1, &fds, NULL, NULL, &tv);
        if (rc <= 0) {
            continue;
        }
        ssize_t len = TEMP_FAILURE_RETRY(read(fd.ffd, request_buffer, sizeof(request_buffer)));
        if (len < 0) {
            if (errno != EINTR) {
                perror("read request");
                if (errno == ENODEV) {
                    result = -1;
                    break;
                }
            }
            continue;
        }

        if ((size_t)len < sizeof(struct fuse_in_header)) {
            fprintf(stderr, "request too short: len=%zu\n", (size_t)len);
            continue;
        }

        struct fuse_in_header* hdr = (struct fuse_in_header*) request_buffer;
        void* data = request_buffer + sizeof(struct fuse_in_header);

        result = -ENOSYS;

        switch (hdr->opcode) {
             case FUSE_INIT:
                result = handle_init(data, &fd, hdr);
                break;

             case FUSE_LOOKUP:
                result = handle_lookup(data, &fd, hdr);
                break;

            case FUSE_GETATTR:
                result = handle_getattr(data, &fd, hdr);
                break;

            case FUSE_OPEN:
                result = handle_open(data, &fd, hdr);
                break;

            case FUSE_READ:
                result = handle_read(data, &fd, hdr);
                break;

            case FUSE_FLUSH:
                result = handle_flush(data, &fd, hdr);
                break;

            case FUSE_RELEASE:
                result = handle_release(data, &fd, hdr);
                break;

            default:
                fprintf(stderr, "unknown fuse request opcode %d\n", hdr->opcode);
                break;
        }

        if (result != NO_STATUS) {
            struct fuse_out_header outhdr;
            outhdr.len = sizeof(outhdr);
            outhdr.error = result;
            outhdr.unique = hdr->unique;
            TEMP_FAILURE_RETRY(write(fd.ffd, &outhdr, sizeof(outhdr)));
        }
    }

  done:
    fd.vtab->close(fd.cookie);

    result = umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_DETACH);
    if (result < 0) {
        printf("fuse_sideload umount failed: %s\n", strerror(errno));
    }

    if (fd.ffd) close(fd.ffd);
    if (fd.block_cache) {
        uint32_t n;
        for (n = 0; n < fd.file_blocks; ++n) {
            free(fd.block_cache[n]);
        }
        free(fd.block_cache);
    }
    free(fd.hashes);
    free(fd.block_data);
    free(fd.extra_block);

    return result;
}
Пример #10
0
/*
 * The actual main function.
 */
int
sntp_main (
	int argc,
	char **argv,
	const char *sntpVersion
	)
{
	int			i;
	int			exitcode;
	int			optct;
	struct event_config *	evcfg;

	/* Initialize logging system - sets up progname */
	sntp_init_logging(argv[0]);

	if (!libevent_version_ok())
		exit(EX_SOFTWARE);

	init_lib();
	init_auth();

	optct = ntpOptionProcess(&sntpOptions, argc, argv);
	argc -= optct;
	argv += optct;


	debug = OPT_VALUE_SET_DEBUG_LEVEL;

	TRACE(2, ("init_lib() done, %s%s\n",
		  (ipv4_works)
		      ? "ipv4_works "
		      : "",
		  (ipv6_works)
		      ? "ipv6_works "
		      : ""));
	ntpver = OPT_VALUE_NTPVERSION;
	steplimit = OPT_VALUE_STEPLIMIT / 1e3;
	gap.tv_usec = max(0, OPT_VALUE_GAP * 1000);
	gap.tv_usec = min(gap.tv_usec, 999999);

	if (HAVE_OPT(LOGFILE))
		open_logfile(OPT_ARG(LOGFILE));

	msyslog(LOG_INFO, "%s", sntpVersion);

	if (0 == argc && !HAVE_OPT(BROADCAST) && !HAVE_OPT(CONCURRENT)) {
		printf("%s: Must supply at least one of -b hostname, -c hostname, or hostname.\n",
		       progname);
		exit(EX_USAGE);
	}


	/*
	** Eventually, we probably want:
	** - separate bcst and ucst timeouts (why?)
	** - multiple --timeout values in the commandline
	*/

	response_timeout = OPT_VALUE_TIMEOUT;
	response_tv.tv_sec = response_timeout;
	response_tv.tv_usec = 0;

	/* IPv6 available? */
	if (isc_net_probeipv6() != ISC_R_SUCCESS) {
		ai_fam_pref = AF_INET;
		TRACE(1, ("No ipv6 support available, forcing ipv4\n"));
	} else {
		/* Check for options -4 and -6 */
		if (HAVE_OPT(IPV4))
			ai_fam_pref = AF_INET;
		else if (HAVE_OPT(IPV6))
			ai_fam_pref = AF_INET6;
	}

	/* TODO: Parse config file if declared */

	/*
	** Init the KOD system.
	** For embedded systems with no writable filesystem,
	** -K /dev/null can be used to disable KoD storage.
	*/
	kod_init_kod_db(OPT_ARG(KOD), FALSE);

	// HMS: Should we use arg-defalt for this too?
	if (HAVE_OPT(KEYFILE))
		auth_init(OPT_ARG(KEYFILE), &keys);

	/*
	** Considering employing a variable that prevents functions of doing
	** anything until everything is initialized properly
	**
	** HMS: What exactly does the above mean?
	*/
	event_set_log_callback(&sntp_libevent_log_cb);
	if (debug > 0)
		event_enable_debug_mode();
#ifdef WORK_THREAD
	evthread_use_pthreads();
	/* we use libevent from main thread only, locks should be academic */
	if (debug > 0)
		evthread_enable_lock_debuging();
#endif
	evcfg = event_config_new();
	if (NULL == evcfg) {
		printf("%s: event_config_new() failed!\n", progname);
		return -1;
	}
#ifndef HAVE_SOCKETPAIR
	event_config_require_features(evcfg, EV_FEATURE_FDS);
#endif
	/* all libevent calls are from main thread */
	/* event_config_set_flag(evcfg, EVENT_BASE_FLAG_NOLOCK); */
	base = event_base_new_with_config(evcfg);
	event_config_free(evcfg);
	if (NULL == base) {
		printf("%s: event_base_new() failed!\n", progname);
		return -1;
	}

	/* wire into intres resolver */
	worker_per_query = TRUE;
	addremove_io_fd = &sntp_addremove_fd;

	open_sockets();

	if (HAVE_OPT(BROADCAST)) {
		int		cn = STACKCT_OPT(  BROADCAST );
		const char **	cp = STACKLST_OPT( BROADCAST );

		while (cn-- > 0) {
			handle_lookup(*cp, CTX_BCST);
			cp++;
		}
	}

	if (HAVE_OPT(CONCURRENT)) {
		int		cn = STACKCT_OPT( CONCURRENT );
		const char **	cp = STACKLST_OPT( CONCURRENT );

		while (cn-- > 0) {
			handle_lookup(*cp, CTX_UCST | CTX_CONC);
			cp++;
		}
	}

	for (i = 0; i < argc; ++i)
		handle_lookup(argv[i], CTX_UCST);

	gettimeofday_cached(base, &start_tv);
	event_base_dispatch(base);
	event_base_free(base);

	if (!time_adjusted &&
	    (ENABLED_OPT(STEP) || ENABLED_OPT(SLEW)))
		exitcode = 1;
	else
		exitcode = 0;

	return exitcode;
}
Пример #11
0
static int handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler,
        const struct fuse_in_header *hdr, const void *data, size_t data_len)
{
    switch (hdr->opcode) {
    case FUSE_LOOKUP: { /* bytez[] -> entry_out */
        const char* name = data;
        return handle_lookup(fuse, handler, hdr, name);
    }

    case FUSE_FORGET: {
        const struct fuse_forget_in *req = data;
        return handle_forget(fuse, handler, hdr, req);
    }

    case FUSE_GETATTR: { /* getattr_in -> attr_out */
        const struct fuse_getattr_in *req = data;
        return handle_getattr(fuse, handler, hdr, req);
    }

    case FUSE_SETATTR: { /* setattr_in -> attr_out */
        const struct fuse_setattr_in *req = data;
        return handle_setattr(fuse, handler, hdr, req);
    }

//    case FUSE_READLINK:
//    case FUSE_SYMLINK:
    case FUSE_MKNOD: { /* mknod_in, bytez[] -> entry_out */
        const struct fuse_mknod_in *req = data;
        const char *name = ((const char*) data) + sizeof(*req);
        return handle_mknod(fuse, handler, hdr, req, name);
    }

    case FUSE_MKDIR: { /* mkdir_in, bytez[] -> entry_out */
        const struct fuse_mkdir_in *req = data;
        const char *name = ((const char*) data) + sizeof(*req);
        return handle_mkdir(fuse, handler, hdr, req, name);
    }

    case FUSE_UNLINK: { /* bytez[] -> */
        const char* name = data;
        return handle_unlink(fuse, handler, hdr, name);
    }

    case FUSE_RMDIR: { /* bytez[] -> */
        const char* name = data;
        return handle_rmdir(fuse, handler, hdr, name);
    }

    case FUSE_RENAME: { /* rename_in, oldname, newname ->  */
        const struct fuse_rename_in *req = data;
        const char *old_name = ((const char*) data) + sizeof(*req);
        const char *new_name = old_name + strlen(old_name) + 1;
        return handle_rename(fuse, handler, hdr, req, old_name, new_name);
    }

//    case FUSE_LINK:
    case FUSE_OPEN: { /* open_in -> open_out */
        const struct fuse_open_in *req = data;
        return handle_open(fuse, handler, hdr, req);
    }

    case FUSE_READ: { /* read_in -> byte[] */
        const struct fuse_read_in *req = data;
        return handle_read(fuse, handler, hdr, req);
    }

    case FUSE_WRITE: { /* write_in, byte[write_in.size] -> write_out */
        const struct fuse_write_in *req = data;
        const void* buffer = (const __u8*)data + sizeof(*req);
        return handle_write(fuse, handler, hdr, req, buffer);
    }

    case FUSE_STATFS: { /* getattr_in -> attr_out */
        return handle_statfs(fuse, handler, hdr);
    }

    case FUSE_RELEASE: { /* release_in -> */
        const struct fuse_release_in *req = data;
        return handle_release(fuse, handler, hdr, req);
    }

    case FUSE_FSYNC: {
        const struct fuse_fsync_in *req = data;
        return handle_fsync(fuse, handler, hdr, req);
    }

//    case FUSE_SETXATTR:
//    case FUSE_GETXATTR:
//    case FUSE_LISTXATTR:
//    case FUSE_REMOVEXATTR:
    case FUSE_FLUSH: {
        return handle_flush(fuse, handler, hdr);
    }

    case FUSE_OPENDIR: { /* open_in -> open_out */
        const struct fuse_open_in *req = data;
        return handle_opendir(fuse, handler, hdr, req);
    }

    case FUSE_READDIR: {
        const struct fuse_read_in *req = data;
        return handle_readdir(fuse, handler, hdr, req);
    }

    case FUSE_RELEASEDIR: { /* release_in -> */
        const struct fuse_release_in *req = data;
        return handle_releasedir(fuse, handler, hdr, req);
    }

//    case FUSE_FSYNCDIR:
    case FUSE_INIT: { /* init_in -> init_out */
        const struct fuse_init_in *req = data;
        return handle_init(fuse, handler, hdr, req);
    }

    default: {
        TRACE("[%d] NOTIMPL op=%d uniq=%llx nid=%llx\n",
                handler->token, hdr->opcode, hdr->unique, hdr->nodeid);
        return -ENOSYS;
    }
    }
}
Пример #12
0
static int sql_fs_write(TEE_Result *errno, int fd, const void *buf, size_t len)
{
	struct sql_fs_fd *fdp;
	size_t remain_bytes = len;
	const uint8_t *data_ptr = buf;
	int start_block_num;
	int end_block_num;
	int res = -1;
	int ret;

	DMSG("(fd: %d, buf: %p, len: %zu)...", fd, (void *)buf, len);

	mutex_lock(&sql_fs_mutex);

	*errno = TEE_ERROR_GENERIC;

	fdp = handle_lookup(&fs_db, fd);
	if (!fdp) {
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit_ret;
	}

	if (!len) {
		res = 0;
		goto exit_ret;
	}

	if (!buf) {
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit_ret;
	}

	if (fdp->flags & TEE_FS_O_RDONLY) {
		*errno = TEE_ERROR_ACCESS_CONFLICT;
		goto exit_ret;
	}

	sql_fs_begin_transaction_rpc();

	if (fdp->meta.length < (size_t)fdp->pos) {
		/* Fill hole */
		res = sql_fs_ftruncate_internal(errno, fd, fdp->pos);
		if (res < 0)
			goto exit;
	}

	start_block_num = block_num(fdp->pos);
	end_block_num = block_num(fdp->pos + len - 1);

	while (start_block_num <= end_block_num) {
		tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
		size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE);

		if (size_to_write + offset > BLOCK_SIZE)
			size_to_write = BLOCK_SIZE - offset;

		res = write_block_partial(errno, fdp, start_block_num,
					  data_ptr, size_to_write, offset);
		if (res < 0)
			goto exit;

		data_ptr += size_to_write;
		remain_bytes -= size_to_write;
		fdp->pos += size_to_write;

		start_block_num++;
	}

	fdp->meta.length = fdp->pos;
	res = write_meta(errno, fdp);
exit:
	sql_fs_end_transaction_rpc(res < 0);
exit_ret:
	mutex_unlock(&sql_fs_mutex);
	ret = (res < 0) ? res : (int)len;
	DMSG("...%d", ret);
	return ret;
}
Пример #13
0
static int sql_fs_read(TEE_Result *errno, int fd, void *buf, size_t len)
{
	struct sql_fs_fd *fdp;
	size_t remain_bytes = len;
	uint8_t *data_ptr = buf;
	uint8_t *block = NULL;
	int start_block_num;
	int end_block_num;
	int res = -1;
	int ret;

	DMSG("(fd: %d, buf: %p, len: %zu)...", fd, (void *)buf, len);

	mutex_lock(&sql_fs_mutex);

	*errno = TEE_ERROR_GENERIC;

	fdp = handle_lookup(&fs_db, fd);
	if (!fdp) {
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit_ret;
	}

	if ((fdp->pos + len) < len || fdp->pos > (tee_fs_off_t)fdp->meta.length)
		len = 0;
	else if (fdp->pos + len > fdp->meta.length)
		len = fdp->meta.length - fdp->pos;

	if (!len) {
		res = 0;
		goto exit_ret;
	}

	if (!buf) {
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit_ret;
	}

	if (fdp->flags & TEE_FS_O_WRONLY) {
		*errno = TEE_ERROR_ACCESS_CONFLICT;
		goto exit_ret;
	}

	start_block_num = block_num(fdp->pos);
	end_block_num = block_num(fdp->pos + len - 1);

	block = malloc(BLOCK_SIZE);
	if (!block) {
		*errno = TEE_ERROR_OUT_OF_MEMORY;
		goto exit_ret;
	}

	sql_fs_begin_transaction_rpc();

	while (start_block_num <= end_block_num) {
		tee_fs_off_t offset = fdp->pos % BLOCK_SIZE;
		size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE);

		if (size_to_read + offset > BLOCK_SIZE)
			size_to_read = BLOCK_SIZE - offset;

		/*
		 * REVISIT: implement read_block_partial() since we have
		 * write_block_partial()?
		 */
		res = read_block(errno, fdp, start_block_num, block);
		if (res < 0)
			goto exit;

		memcpy(data_ptr, block + offset, size_to_read);

		data_ptr += size_to_read;
		remain_bytes -= size_to_read;
		fdp->pos += size_to_read;

		start_block_num++;
	}
	res = 0;
exit:
	sql_fs_end_transaction_rpc(res < 0);
	free(block);
exit_ret:
	mutex_unlock(&sql_fs_mutex);
	ret = (res < 0) ? res : (int)len;
	DMSG("...%d", ret);
	return ret;
}
Пример #14
0
static int sql_fs_ftruncate_internal(TEE_Result *errno, int fd,
				     tee_fs_off_t new_length)
{
	struct sql_fs_fd *fdp;
	tee_fs_off_t old_length;
	int rc = -1;

	DMSG("(fd: %d, new_length: %" PRId64 ")...", fd, new_length);

	*errno = TEE_ERROR_GENERIC;

	fdp = handle_lookup(&fs_db, fd);
	if (!fdp) {
		*errno = TEE_ERROR_BAD_PARAMETERS;
		goto exit_ret;
	}

	old_length = (tee_fs_off_t)fdp->meta.length;

	if (new_length == old_length) {
		rc = 0;
		goto exit_ret;
	}

	sql_fs_begin_transaction_rpc();

	if (new_length < old_length) {
		/* Trim unused blocks */
		int old_last_block = block_num(old_length);
		int last_block = block_num(new_length);
		tee_fs_off_t off;

		if (last_block < old_last_block) {
			off = block_pos_raw(last_block);
			rc = tee_fs_rpc_ftruncate(OPTEE_MSG_RPC_CMD_SQL_FS,
						  fd, off);
			if (rc < 0)
				goto exit;
		}
	} else {
		/* Extend file with zeroes */
		tee_fs_off_t off = old_length % BLOCK_SIZE;
		size_t bnum = block_num(old_length);
		size_t end_bnum = block_num(new_length);

		while (bnum <= end_bnum) {
			size_t len = (size_t)BLOCK_SIZE - (size_t)off;

			rc = write_block_partial(errno, fdp, bnum, NULL, len,
						 off);
			if (rc < 0)
				goto exit;
			off = 0;
			bnum++;
		}
	}

	fdp->meta.length = new_length;
	rc = write_meta(errno, fdp);

exit:
	sql_fs_end_transaction_rpc(rc < 0);
exit_ret:
	DMSG("...%d", rc);
	return rc;
}
Пример #15
0
struct tee_fs_fd *tee_fs_fd_lookup(int fd)
{
	return handle_lookup(&fs_handle_db, fd);
}
Пример #16
0
int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
                      uint64_t file_size, uint32_t block_size)
{
    int result;

    // If something's already mounted on our mountpoint, try to remove
    // it.  (Mostly in case of a previous abnormal exit.)
    umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_FORCE);

    if (block_size < 1024) {
        fprintf(stderr, "block size (%u) is too small\n", block_size);
        return -1;
    }
    if (block_size > (1<<22)) {   // 4 MiB
        fprintf(stderr, "block size (%u) is too large\n", block_size);
        return -1;
    }

    struct fuse_data fd;
    memset(&fd, 0, sizeof(fd));
    fd.vtab = vtab;
    fd.cookie = cookie;
    fd.file_size = file_size;
    fd.block_size = block_size;
    fd.file_blocks = (file_size == 0) ? 0 : (((file_size-1) / block_size) + 1);

    if (fd.file_blocks > (1<<18)) {
        fprintf(stderr, "file has too many blocks (%u)\n", fd.file_blocks);
        result = -1;
        goto done;
    }

    fd.hashes = (uint8_t*)calloc(fd.file_blocks, SHA256_DIGEST_SIZE);
    if (fd.hashes == NULL) {
        fprintf(stderr, "failed to allocate %d bites for hashes\n",
                fd.file_blocks * SHA256_DIGEST_SIZE);
        result = -1;
        goto done;
    }

    fd.uid = getuid();
    fd.gid = getgid();

    fd.curr_block = -1;
    fd.block_data = (uint8_t*)malloc(block_size);
    if (fd.block_data == NULL) {
        fprintf(stderr, "failed to allocate %d bites for block_data\n", block_size);
        result = -1;
        goto done;
    }
    fd.extra_block = (uint8_t*)malloc(block_size);
    if (fd.extra_block == NULL) {
        fprintf(stderr, "failed to allocate %d bites for extra_block\n", block_size);
        result = -1;
        goto done;
    }

    fd.ffd = open("/dev/fuse", O_RDWR);
    if (fd.ffd < 0) {
        perror("open /dev/fuse");
        result = -1;
        goto done;
    }

    char opts[256];
    snprintf(opts, sizeof(opts),
             ("fd=%d,user_id=%d,group_id=%d,max_read=%zu,"
              "allow_other,rootmode=040000"),
             fd.ffd, fd.uid, fd.gid, block_size);

    result = mount("/dev/fuse", FUSE_SIDELOAD_HOST_MOUNTPOINT,
                   "fuse", MS_NOSUID | MS_NODEV | MS_RDONLY | MS_NOEXEC, opts);
    if (result < 0) {
        perror("mount");
        goto done;
    }
    uint8_t request_buffer[sizeof(struct fuse_in_header) + PATH_MAX*8];
    for (;;) {
        ssize_t len = read(fd.ffd, request_buffer, sizeof(request_buffer));
        if (len < 0) {
            if (errno != EINTR) {
                perror("read request");
                if (errno == ENODEV) {
                    result = -1;
                    break;
                }
            }
            continue;
        }

        if ((size_t)len < sizeof(struct fuse_in_header)) {
            fprintf(stderr, "request too short: len=%zu\n", (size_t)len);
            continue;
        }

        struct fuse_in_header* hdr = (struct fuse_in_header*) request_buffer;
        void* data = request_buffer + sizeof(struct fuse_in_header);

        result = -ENOSYS;

        switch (hdr->opcode) {
             case FUSE_INIT:
                result = handle_init(data, &fd, hdr);
                break;

             case FUSE_LOOKUP:
                result = handle_lookup(data, &fd, hdr);
                break;

            case FUSE_GETATTR:
                result = handle_getattr(data, &fd, hdr);
                break;

            case FUSE_OPEN:
                result = handle_open(data, &fd, hdr);
                break;

            case FUSE_READ:
                result = handle_read(data, &fd, hdr);
                break;

            case FUSE_FLUSH:
                result = handle_flush(data, &fd, hdr);
                break;

            case FUSE_RELEASE:
                result = handle_release(data, &fd, hdr);
                break;

            default:
                fprintf(stderr, "unknown fuse request opcode %d\n", hdr->opcode);
                break;
        }

        if (result == NO_STATUS_EXIT) {
            result = 0;
            break;
        }

        if (result != NO_STATUS) {
            struct fuse_out_header outhdr;
            outhdr.len = sizeof(outhdr);
            outhdr.error = result;
            outhdr.unique = hdr->unique;
            write(fd.ffd, &outhdr, sizeof(outhdr));
        }
    }

  done:
    fd.vtab->close(fd.cookie);

    result = umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_DETACH);
    if (result < 0) {
        printf("fuse_sideload umount failed: %s\n", strerror(errno));
    }

    if (fd.ffd) close(fd.ffd);
    free(fd.hashes);
    free(fd.block_data);
    free(fd.extra_block);

    return result;
}