예제 #1
0
static int scribe_recvmsg(struct kiocb *iocb, struct socket *sock,
			  struct msghdr *m, size_t total_len,
			  int flags)
{
	struct scribe_ps *scribe = current->scribe;
	int ret, err;

	if (scribe_is_deterministic(sock) || !is_scribed(scribe)) {
		if (is_replaying(scribe)) {
			flags &= ~MSG_DONTWAIT;
			flags |= MSG_WAITALL;

			if (!scribe_is_in_read_write(scribe))
				total_len = scribe->orig_ret;
			if ((ssize_t)total_len <= 0)
				return total_len;
		}
		scribe_data_det();
		ret = sock->real_ops->recvmsg(iocb, sock, m, total_len, flags),
		scribe_data_pop_flags();
		return ret;
	}

	scribe_data_non_det_need_info();

	err = scribe_result_cond(
		ret, sock->real_ops->recvmsg(iocb, sock, m, total_len, flags),
		!scribe_is_in_read_write(scribe) || ret > 0);
	if (err)
		goto out;
	if (ret <= 0)
		goto out;

	if (is_replaying(scribe))
		scribe_emul_copy_to_user(scribe, NULL, INT_MAX);

	err = scribe_value(&m->msg_namelen);
	if (err)
		goto out;
	err = scribe_buffer(m->msg_name, m->msg_namelen);

out:
	scribe_data_pop_flags();
	return err ?: ret;
}
예제 #2
0
static int scribe_ioctl(struct socket *sock, unsigned int cmd,
			unsigned long arg)
{
	int ret;
	scribe_data_non_det();
	ret = sock->real_ops->ioctl(sock, cmd, arg);
	scribe_data_pop_flags();
	return ret;
}
예제 #3
0
static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
		   u64 ino, unsigned int d_type)
{
	struct linux_dirent __user * dirent;
	struct getdents_callback * buf = (struct getdents_callback *) __buf;
	unsigned long d_ino;
	int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(long));
	int ret;

	buf->error = -EINVAL;	/* only used if we fail.. */
	if (reclen > buf->count)
		return -EINVAL;
	d_ino = ino;
	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
		buf->error = -EOVERFLOW;
		return -EOVERFLOW;
	}
	dirent = buf->previous;
	if (dirent) {
		if (__put_user(offset, &dirent->d_off))
			goto efault;
	}
	dirent = buf->current_dir;

	scribe_data_non_det();
	ret = __put_user(d_ino, &dirent->d_ino);
	scribe_data_pop_flags();
	if (ret)
		goto efault;

	if (__put_user(reclen, &dirent->d_reclen))
		goto efault;
	if (copy_to_user(dirent->d_name, name, namlen))
		goto efault;
	if (__put_user(0, dirent->d_name + namlen))
		goto efault;
	if (__put_user(d_type, (char __user *) dirent + reclen - 1))
		goto efault;
	buf->previous = dirent;
	dirent = (void __user *)dirent + reclen;
	buf->current_dir = dirent;
	buf->count -= reclen;
	return 0;
efault:
	buf->error = -EFAULT;
	return -EFAULT;
}
예제 #4
0
static int scribe_sendmsg(struct kiocb *iocb, struct socket *sock,
			  struct msghdr *m, size_t total_len)
{
	struct scribe_ps *scribe = current->scribe;
	int ret, err;

	if (scribe_is_deterministic(sock) || !is_scribed(scribe)) {
		if (is_replaying(scribe)) {
			m->msg_flags &= ~MSG_DONTWAIT;

			if (!scribe_is_in_read_write(scribe))
				total_len = scribe->orig_ret;
			if ((ssize_t)total_len <= 0)
				return total_len;
		}
		ret = sock->real_ops->sendmsg(iocb, sock, m, total_len);
		return ret;
	}

	scribe_data_need_info();

	err = scribe_result_cond(
		ret, sock->real_ops->sendmsg(iocb, sock, m, total_len),
		!scribe_is_in_read_write(scribe) || ret > 0);
	if (err)
		goto out;
	if (ret <= 0)
		goto out;

	if (is_replaying(scribe))
		scribe_emul_copy_from_user(scribe, NULL, INT_MAX);

out:
	scribe_data_pop_flags();
	return err ?: ret;
}