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 ssize_t scribe_do_read(struct file *file, char __user *buf, ssize_t len, loff_t *ppos) { struct scribe_ps *scribe = current->scribe; int force_block = 0; ssize_t ret; if (!is_scribed(scribe)) return do_read(file, buf, len, ppos, force_block); if (is_kernel_copy()) goto out; if (!should_scribe_data(scribe)) goto out; scribe_need_syscall_ret(scribe); if (is_replaying(scribe)) { len = scribe->orig_ret; if (len <= 0) return len; force_block = 1; } if (is_deterministic(file)) goto out; scribe_data_non_det(); if (is_recording(scribe)) goto out; return scribe_emul_copy_to_user(scribe, buf, len); out: scribe->in_read_write = true; ret = do_read(file, buf, len, ppos, force_block); scribe->in_read_write = false; return ret; }
static int scribe_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct scribe_ps *scribe = current->scribe; int ret, err; scribe_data_non_det_need_info(); err = scribe_result( ret, sock->real_ops->getsockopt(sock, level, optname, optval, optlen)); if (err) return err; if (ret < 0) return ret; if (is_replaying(scribe)) scribe_emul_copy_to_user(scribe, NULL, INT_MAX); return ret; }
static ssize_t io_scribe_emul_copy_to_user(struct file *filp, char __user *buf, size_t len, loff_t *ppos) { return scribe_emul_copy_to_user(current->scribe, buf, len); }