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; }
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; }
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; }
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; }