コード例 #1
0
SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
		struct old_linux_dirent __user *, dirent, unsigned int, count)
{
	int error;
	struct file * file;
	struct readdir_callback buf;

	if (scribe_track_next_file_read()) {
		scribe_kill(current->scribe->ctx, -ENOMEM);
		return -ENOMEM;
	}

	error = -EBADF;
	file = fget(fd);
	if (!file)
		goto out;

	buf.result = 0;
	buf.dirent = dirent;

	error = vfs_readdir(file, fillonedir, &buf);
	if (buf.result)
		error = buf.result;

	fput(file);
out:
	return error;
}
コード例 #2
0
static int scribe_getname(struct socket *sock, struct sockaddr *addr,
			  int *sockaddr_len, int peer)
{
	struct scribe_ps *scribe = current->scribe;
	int ret, err;

	if (!is_scribed(scribe))
		return sock->real_ops->getname(sock, addr, sockaddr_len, peer);

	err = scribe_result(
		ret, sock->real_ops->getname(sock, addr, sockaddr_len, peer));
	if (err)
		goto out;
	if (ret < 0)
		goto out;

	err = scribe_value(sockaddr_len);
	if (err)
		goto out;

	err = scribe_buffer(addr, *sockaddr_len);

out:
	if (err) {
		scribe_kill(scribe->ctx, err);
		return err;
	}
	return ret;
}
コード例 #3
0
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
		struct linux_dirent64 __user *, dirent, unsigned int, count)
{
	struct file * file;
	struct linux_dirent64 __user * lastdirent;
	struct getdents_callback64 buf;
	int error;

	error = -EFAULT;
	if (!access_ok(VERIFY_WRITE, dirent, count))
		goto out;

	if (scribe_track_next_file_read()) {
		scribe_kill(current->scribe->ctx, -ENOMEM);
		return -ENOMEM;
	}

	error = -EBADF;
	file = fget(fd);
	if (!file)
		goto out;

	buf.current_dir = dirent;
	buf.previous = NULL;
	buf.count = count;
	buf.error = 0;

	error = vfs_readdir(file, filldir64, &buf);
	if (error >= 0)
		error = buf.error;
	lastdirent = buf.previous;
	if (lastdirent) {
		typeof(lastdirent->d_off) d_off = file->f_pos;
		if (__put_user(d_off, &lastdirent->d_off))
			error = -EFAULT;
		else
			error = count - buf.count;
	}
	fput(file);
out:
	return error;
}
コード例 #4
0
static int get_data_event(struct scribe_ps *scribe, struct data_desc *desc)
{
	union scribe_event_data_union event;

	if (is_recording(scribe)) {
		event = scribe->prepared_data_event;
		if (event.generic) {
			scribe->prepared_data_event.generic = NULL;

			if (desc->do_info) {
				/* we're good */
			} else if (desc->do_extra) {
				BUG_ON(event.extra->h.size < desc->size);
				event.extra->h.size = desc->size;
			} else {
				BUG_ON(event.regular->h.size < desc->size);
				event.regular->h.size = desc->size;
			}
			goto out;
		}

		if (desc->do_info)
			event.info = scribe_alloc_event(
					SCRIBE_EVENT_DATA_INFO);
		else if (desc->do_extra)
			event.extra = scribe_alloc_event_sized(
					SCRIBE_EVENT_DATA_EXTRA, desc->size);
		else
			event.regular = scribe_alloc_event_sized(
					SCRIBE_EVENT_DATA, desc->size);
		if (!event.generic) {
			scribe_kill(scribe->ctx, -ENOMEM);
			return -ENOMEM;
		}
		goto out;
	} else /* replaying */ {
		event = scribe->prepared_data_event;
		if (event.generic) {
			scribe->prepared_data_event.generic = NULL;
			goto out;
		}

		/*
		 * Not using scribe_dequeue_event_sized() because we don't
		 * really know the size (maybe we are in
		 * scribe_prepare_data_event() and @desc->size would only be the
		 * maximum size).
		 */

		/*
		 * XXX XXX We cannot dequeue in the middle of the stream
		 * because our data event may act as a fence.
		 * So we'll peek, which means that we'll have to dequeue it
		 * eventually.
		 */

		if (desc->do_info)
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA_INFO);
		else if (desc->do_extra)
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA_EXTRA);
		else
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA);
		if (IS_ERR(event.generic))
			return PTR_ERR(event.generic);
	}
out:
	desc->event = event;
	return 0;
}