/* I've named the args so it is easy to tell whose space the pointers are in. */ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, struct sockaddr_storage *kern_address, int mode) { int tot_len; if (kern_msg->msg_namelen) { if (mode == VERIFY_READ) { int err = move_addr_to_kernel(kern_msg->msg_name, kern_msg->msg_namelen, kern_address); if (err < 0) return err; } kern_msg->msg_name = kern_address; } else kern_msg->msg_name = NULL; tot_len = iov_from_user_compat_to_kern(kern_iov, (struct compat_iovec __user *)kern_msg->msg_iov, kern_msg->msg_iovlen); if (tot_len >= 0) kern_msg->msg_iov = kern_iov; return tot_len; }
int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode) { int size, err, ct; if (m->msg_namelen) { if (mode == VERIFY_READ) { err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address); if (err < 0) return err; } m->msg_name = address; } else { m->msg_name = NULL; } size = m->msg_iovlen * sizeof(struct iovec); if (copy_from_user(iov, m->msg_iov, size)) return -EFAULT; m->msg_iov = iov; err = 0; for (ct = 0; ct < m->msg_iovlen; ct++) { size_t len = iov[ct].iov_len; if (len > INT_MAX - err) { len = INT_MAX - err; iov[ct].iov_len = len; } err += len; } return err; }
int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) { int size, err, ct; if(m->msg_namelen) { if(mode==VERIFY_READ) { err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); if(err<0) goto out; } m->msg_name = address; } else m->msg_name = NULL; err = -EFAULT; size = m->msg_iovlen * sizeof(struct iovec); if (copy_from_user(iov, m->msg_iov, size)) goto out; m->msg_iov=iov; for (err = 0, ct = 0; ct < m->msg_iovlen; ct++) err += iov[ct].iov_len; out: return err; }
/* I've named the args so it is easy to tell whose space the pointers are in. */ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, char *kern_address, int mode) { int tot_len; if(kern_msg->msg_namelen) { if(mode==VERIFY_READ) { int err = move_addr_to_kernel(kern_msg->msg_name, kern_msg->msg_namelen, kern_address); if(err < 0) return err; } kern_msg->msg_name = kern_address; } else kern_msg->msg_name = NULL; if(kern_msg->msg_iovlen > UIO_FASTIOV) { kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), GFP_KERNEL); if(!kern_iov) return -ENOMEM; } tot_len = iov_from_user_compat_to_kern(kern_iov, (struct compat_iovec __user *)kern_msg->msg_iov, kern_msg->msg_iovlen); if(tot_len >= 0) kern_msg->msg_iov = kern_iov; else if(kern_msg->msg_iovlen > UIO_FASTIOV) kfree(kern_iov); return tot_len; }
int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) { int size, err, ct; if(m->msg_namelen) { if(mode==VERIFY_READ) { err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); if(err<0) goto out; } m->msg_name = address; } else m->msg_name = NULL; err = -EFAULT; size = m->msg_iovlen * sizeof(struct iovec); if (copy_from_user(iov, m->msg_iov, size)) goto out; m->msg_iov=iov; for (err = 0, ct = 0; ct < m->msg_iovlen; ct++) { err += iov[ct].iov_len; /* Goal is not to verify user data, but to prevent returning negative value, which is interpreted as errno. Overflow is still possible, but it is harmless. */ if (err < 0) return -EMSGSIZE; } out: return err; }
int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg, struct sockaddr __user **save_addr, struct iovec **iov) { compat_uptr_t uaddr, uiov, tmp3; compat_size_t nr_segs; ssize_t err; if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || __get_user(uaddr, &umsg->msg_name) || __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || __get_user(uiov, &umsg->msg_iov) || __get_user(nr_segs, &umsg->msg_iovlen) || __get_user(tmp3, &umsg->msg_control) || __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; if (!uaddr) kmsg->msg_namelen = 0; if (kmsg->msg_namelen < 0) return -EINVAL; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) kmsg->msg_namelen = sizeof(struct sockaddr_storage); kmsg->msg_control = compat_ptr(tmp3); if (save_addr) *save_addr = compat_ptr(uaddr); if (uaddr && kmsg->msg_namelen) { if (!save_addr) { err = move_addr_to_kernel(compat_ptr(uaddr), kmsg->msg_namelen, kmsg->msg_name); if (err < 0) return err; } } else { kmsg->msg_name = NULL; kmsg->msg_namelen = 0; } if (nr_segs > UIO_MAXIOV) return -EMSGSIZE; kmsg->msg_iocb = NULL; return compat_import_iovec(save_addr ? READ : WRITE, compat_ptr(uiov), nr_segs, UIO_FASTIOV, iov, &kmsg->msg_iter); }
ssize_t get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg, struct sockaddr __user **save_addr, struct iovec **iov) { compat_uptr_t uaddr, uiov, tmp3; ssize_t err; if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || __get_user(uaddr, &umsg->msg_name) || __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || __get_user(uiov, &umsg->msg_iov) || __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || __get_user(tmp3, &umsg->msg_control) || __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) kmsg->msg_namelen = sizeof(struct sockaddr_storage); kmsg->msg_control = compat_ptr(tmp3); if (save_addr) *save_addr = compat_ptr(uaddr); if (uaddr && kmsg->msg_namelen) { if (!save_addr) { err = move_addr_to_kernel(compat_ptr(uaddr), kmsg->msg_namelen, kmsg->msg_name); if (err < 0) return err; } } else { kmsg->msg_name = NULL; kmsg->msg_namelen = 0; } if (kmsg->msg_iovlen > UIO_MAXIOV) return -EMSGSIZE; err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, compat_ptr(uiov), kmsg->msg_iovlen, UIO_FASTIOV, *iov, iov); if (err >= 0) kmsg->msg_iov = *iov; return err; }
static int efab_tcp_helper_bind_os_sock_rsop(ci_private_t* priv, void *arg) { oo_tcp_bind_os_sock_t *op = arg; struct sockaddr_storage k_address_buf; int addrlen = op->addrlen; ci_uint16 port; int rc; if (priv->thr == NULL) return -EINVAL; rc = move_addr_to_kernel(CI_USER_PTR_GET(op->address), addrlen, (struct sockaddr *)&k_address_buf); if( rc < 0 ) return rc; rc = efab_tcp_helper_bind_os_sock(priv->thr, op->sock_id, (struct sockaddr *)&k_address_buf, addrlen, &port); if( rc < 0 ) return rc; op->addrlen = port; return 0; }