Merge branch 'for-davem-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

More iov_iter work for the networking from Al Viro.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-12-10 13:17:23 -05:00
commit 6e5f59aacb
48 changed files with 635 additions and 1045 deletions

View File

@ -42,7 +42,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
struct alg_sock *ask = alg_sk(sk); struct alg_sock *ask = alg_sk(sk);
struct hash_ctx *ctx = ask->private; struct hash_ctx *ctx = ask->private;
unsigned long iovlen; unsigned long iovlen;
struct iovec *iov; const struct iovec *iov;
long copied = 0; long copied = 0;
int err; int err;
@ -58,7 +58,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
ctx->more = 0; ctx->more = 0;
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
iovlen--, iov++) { iovlen--, iov++) {
unsigned long seglen = iov->iov_len; unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base; char __user *from = iov->iov_base;

View File

@ -429,13 +429,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
struct skcipher_sg_list *sgl; struct skcipher_sg_list *sgl;
struct scatterlist *sg; struct scatterlist *sg;
unsigned long iovlen; unsigned long iovlen;
struct iovec *iov; const struct iovec *iov;
int err = -EAGAIN; int err = -EAGAIN;
int used; int used;
long copied = 0; long copied = 0;
lock_sock(sk); lock_sock(sk);
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
iovlen--, iov++) { iovlen--, iov++) {
unsigned long seglen = iov->iov_len; unsigned long seglen = iov->iov_len;
char __user *from = iov->iov_base; char __user *from = iov->iov_base;

View File

@ -27,6 +27,7 @@
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/skbuff.h>
#include "vmci_handle_array.h" #include "vmci_handle_array.h"
#include "vmci_queue_pair.h" #include "vmci_queue_pair.h"
@ -429,11 +430,11 @@ static int __qp_memcpy_from_queue(void *dest,
to_copy = size - bytes_copied; to_copy = size - bytes_copied;
if (is_iovec) { if (is_iovec) {
struct iovec *iov = (struct iovec *)dest; struct msghdr *msg = dest;
int err; int err;
/* The iovec will track bytes_copied internally. */ /* The iovec will track bytes_copied internally. */
err = memcpy_toiovec(iov, (u8 *)va + page_offset, err = memcpy_to_msg(msg, (u8 *)va + page_offset,
to_copy); to_copy);
if (err != 0) { if (err != 0) {
if (kernel_if->host) if (kernel_if->host)
@ -3264,13 +3265,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_enquev);
* of bytes dequeued or < 0 on error. * of bytes dequeued or < 0 on error.
*/ */
ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
void *iov, struct msghdr *msg,
size_t iov_size, size_t iov_size,
int buf_type) int buf_type)
{ {
ssize_t result; ssize_t result;
if (!qpair || !iov) if (!qpair)
return VMCI_ERROR_INVALID_ARGS; return VMCI_ERROR_INVALID_ARGS;
qp_lock(qpair); qp_lock(qpair);
@ -3279,7 +3280,7 @@ ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
result = qp_dequeue_locked(qpair->produce_q, result = qp_dequeue_locked(qpair->produce_q,
qpair->consume_q, qpair->consume_q,
qpair->consume_q_size, qpair->consume_q_size,
iov, iov_size, msg, iov_size,
qp_memcpy_from_queue_iov, qp_memcpy_from_queue_iov,
true); true);
@ -3308,13 +3309,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_dequev);
* of bytes peeked or < 0 on error. * of bytes peeked or < 0 on error.
*/ */
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
void *iov, struct msghdr *msg,
size_t iov_size, size_t iov_size,
int buf_type) int buf_type)
{ {
ssize_t result; ssize_t result;
if (!qpair || !iov) if (!qpair)
return VMCI_ERROR_INVALID_ARGS; return VMCI_ERROR_INVALID_ARGS;
qp_lock(qpair); qp_lock(qpair);
@ -3323,7 +3324,7 @@ ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
result = qp_dequeue_locked(qpair->produce_q, result = qp_dequeue_locked(qpair->produce_q,
qpair->consume_q, qpair->consume_q,
qpair->consume_q_size, qpair->consume_q_size,
iov, iov_size, msg, iov_size,
qp_memcpy_from_queue_iov, qp_memcpy_from_queue_iov,
false); false);

View File

@ -1095,9 +1095,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len) struct msghdr *m, size_t total_len)
{ {
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
struct iov_iter from; return macvtap_get_user(q, m, &m->msg_iter, m->msg_flags & MSG_DONTWAIT);
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len);
return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT);
} }
static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
@ -1105,12 +1103,10 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
int flags) int flags)
{ {
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
struct iov_iter to;
int ret; int ret;
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
return -EINVAL; return -EINVAL;
iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); ret = macvtap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT);
ret = macvtap_do_read(q, &to, flags & MSG_DONTWAIT);
if (ret > total_len) { if (ret > total_len) {
m->msg_flags |= MSG_TRUNC; m->msg_flags |= MSG_TRUNC;
ret = flags & MSG_TRUNC ? ret : total_len; ret = flags & MSG_TRUNC ? ret : total_len;

View File

@ -417,6 +417,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
ssize_t ret; ssize_t ret;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct iovec iov; struct iovec iov;
struct iov_iter to;
ret = count; ret = count;
@ -462,7 +463,8 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
ret = -EFAULT; ret = -EFAULT;
iov.iov_base = buf; iov.iov_base = buf;
iov.iov_len = count; iov.iov_len = count;
if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len)) iov_iter_init(&to, READ, &iov, 1, count);
if (skb_copy_datagram_iter(skb, 0, &to, skb->len))
goto outf; goto outf;
ret = skb->len; ret = skb->len;

View File

@ -1449,13 +1449,11 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
int ret; int ret;
struct tun_file *tfile = container_of(sock, struct tun_file, socket); struct tun_file *tfile = container_of(sock, struct tun_file, socket);
struct tun_struct *tun = __tun_get(tfile); struct tun_struct *tun = __tun_get(tfile);
struct iov_iter from;
if (!tun) if (!tun)
return -EBADFD; return -EBADFD;
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter,
ret = tun_get_user(tun, tfile, m->msg_control, &from,
m->msg_flags & MSG_DONTWAIT); m->msg_flags & MSG_DONTWAIT);
tun_put(tun); tun_put(tun);
return ret; return ret;
@ -1467,7 +1465,6 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
{ {
struct tun_file *tfile = container_of(sock, struct tun_file, socket); struct tun_file *tfile = container_of(sock, struct tun_file, socket);
struct tun_struct *tun = __tun_get(tfile); struct tun_struct *tun = __tun_get(tfile);
struct iov_iter to;
int ret; int ret;
if (!tun) if (!tun)
@ -1482,8 +1479,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
SOL_PACKET, TUN_TX_TIMESTAMP); SOL_PACKET, TUN_TX_TIMESTAMP);
goto out; goto out;
} }
iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT);
ret = tun_do_read(tun, tfile, &to, flags & MSG_DONTWAIT);
if (ret > total_len) { if (ret > total_len) {
m->msg_flags |= MSG_TRUNC; m->msg_flags |= MSG_TRUNC;
ret = flags & MSG_TRUNC ? ret : total_len; ret = flags & MSG_TRUNC ? ret : total_len;

View File

@ -1326,21 +1326,19 @@ static int iscsit_do_rx_data(
struct iscsi_conn *conn, struct iscsi_conn *conn,
struct iscsi_data_count *count) struct iscsi_data_count *count)
{ {
int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; int data = count->data_length, rx_loop = 0, total_rx = 0;
struct kvec *iov_p;
struct msghdr msg; struct msghdr msg;
if (!conn || !conn->sock || !conn->conn_ops) if (!conn || !conn->sock || !conn->conn_ops)
return -1; return -1;
memset(&msg, 0, sizeof(struct msghdr)); memset(&msg, 0, sizeof(struct msghdr));
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC,
iov_p = count->iov; count->iov, count->iov_count, data);
iov_len = count->iov_count;
while (total_rx < data) { while (total_rx < data) {
rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, rx_loop = sock_recvmsg(conn->sock, &msg,
(data - total_rx), MSG_WAITALL); (data - total_rx), MSG_WAITALL);
if (rx_loop <= 0) { if (rx_loop <= 0) {
pr_debug("rx_loop: %d total_rx: %d\n", pr_debug("rx_loop: %d total_rx: %d\n",
rx_loop, total_rx); rx_loop, total_rx);

View File

@ -342,7 +342,6 @@ static void handle_tx(struct vhost_net *net)
.msg_namelen = 0, .msg_namelen = 0,
.msg_control = NULL, .msg_control = NULL,
.msg_controllen = 0, .msg_controllen = 0,
.msg_iov = vq->iov,
.msg_flags = MSG_DONTWAIT, .msg_flags = MSG_DONTWAIT,
}; };
size_t len, total_len = 0; size_t len, total_len = 0;
@ -396,8 +395,8 @@ static void handle_tx(struct vhost_net *net)
} }
/* Skip header. TODO: support TSO. */ /* Skip header. TODO: support TSO. */
s = move_iovec_hdr(vq->iov, nvq->hdr, hdr_size, out); s = move_iovec_hdr(vq->iov, nvq->hdr, hdr_size, out);
msg.msg_iovlen = out;
len = iov_length(vq->iov, out); len = iov_length(vq->iov, out);
iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len);
/* Sanity check */ /* Sanity check */
if (!len) { if (!len) {
vq_err(vq, "Unexpected header len for TX: " vq_err(vq, "Unexpected header len for TX: "
@ -562,7 +561,6 @@ static void handle_rx(struct vhost_net *net)
.msg_namelen = 0, .msg_namelen = 0,
.msg_control = NULL, /* FIXME: get and handle RX aux data. */ .msg_control = NULL, /* FIXME: get and handle RX aux data. */
.msg_controllen = 0, .msg_controllen = 0,
.msg_iov = vq->iov,
.msg_flags = MSG_DONTWAIT, .msg_flags = MSG_DONTWAIT,
}; };
struct virtio_net_hdr_mrg_rxbuf hdr = { struct virtio_net_hdr_mrg_rxbuf hdr = {
@ -600,7 +598,7 @@ static void handle_rx(struct vhost_net *net)
break; break;
/* On overrun, truncate and discard */ /* On overrun, truncate and discard */
if (unlikely(headcount > UIO_MAXIOV)) { if (unlikely(headcount > UIO_MAXIOV)) {
msg.msg_iovlen = 1; iov_iter_init(&msg.msg_iter, READ, vq->iov, 1, 1);
err = sock->ops->recvmsg(NULL, sock, &msg, err = sock->ops->recvmsg(NULL, sock, &msg,
1, MSG_DONTWAIT | MSG_TRUNC); 1, MSG_DONTWAIT | MSG_TRUNC);
pr_debug("Discarded rx packet: len %zd\n", sock_len); pr_debug("Discarded rx packet: len %zd\n", sock_len);
@ -626,7 +624,7 @@ static void handle_rx(struct vhost_net *net)
/* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF: /* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF:
* needed because recvmsg can modify msg_iov. */ * needed because recvmsg can modify msg_iov. */
copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in); copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in);
msg.msg_iovlen = in; iov_iter_init(&msg.msg_iter, READ, vq->iov, in, sock_len);
err = sock->ops->recvmsg(NULL, sock, &msg, err = sock->ops->recvmsg(NULL, sock, &msg,
sock_len, MSG_DONTWAIT | MSG_TRUNC); sock_len, MSG_DONTWAIT | MSG_TRUNC);
/* Userspace might have consumed the packet meanwhile: /* Userspace might have consumed the packet meanwhile:

View File

@ -306,8 +306,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
_debug("- range %u-%u%s", _debug("- range %u-%u%s",
offset, to, msg->msg_flags ? " [more]" : ""); offset, to, msg->msg_flags ? " [more]" : "");
msg->msg_iov = (struct iovec *) iov; iov_iter_init(&msg->msg_iter, WRITE,
msg->msg_iovlen = 1; (struct iovec *) iov, 1, to - offset);
/* have to change the state *before* sending the last /* have to change the state *before* sending the last
* packet as RxRPC might give us the reply before it * packet as RxRPC might give us the reply before it
@ -384,8 +384,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_iov = (struct iovec *) iov; iov_iter_init(&msg.msg_iter, WRITE, (struct iovec *)iov, 1,
msg.msg_iovlen = 1; call->request_size);
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = (call->send_pages ? MSG_MORE : 0); msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
@ -778,8 +778,7 @@ void afs_send_empty_reply(struct afs_call *call)
iov[0].iov_len = 0; iov[0].iov_len = 0;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_iov = iov; iov_iter_init(&msg.msg_iter, WRITE, iov, 0, 0); /* WTF? */
msg.msg_iovlen = 0;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = 0; msg.msg_flags = 0;
@ -815,8 +814,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
iov[0].iov_len = len; iov[0].iov_len = len;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_namelen = 0; msg.msg_namelen = 0;
msg.msg_iov = iov; iov_iter_init(&msg.msg_iter, WRITE, iov, 1, len);
msg.msg_iovlen = 1;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_flags = 0; msg.msg_flags = 0;

View File

@ -2644,24 +2644,17 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
int *err); int *err);
unsigned int datagram_poll(struct file *file, struct socket *sock, unsigned int datagram_poll(struct file *file, struct socket *sock,
struct poll_table_struct *wait); struct poll_table_struct *wait);
int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
struct iovec *to, int size); struct iov_iter *to, int size);
static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset, static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
struct msghdr *msg, int size) struct msghdr *msg, int size)
{ {
return skb_copy_datagram_iovec(from, offset, msg->msg_iov, size); return skb_copy_datagram_iter(from, offset, &msg->msg_iter, size);
}
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
struct iovec *iov);
static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
struct msghdr *msg)
{
return skb_copy_and_csum_datagram_iovec(skb, hlen, msg->msg_iov);
} }
int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
struct msghdr *msg);
int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
struct iov_iter *from, int len); struct iov_iter *from, int len);
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
struct iov_iter *to, int size);
int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm);
void skb_free_datagram(struct sock *sk, struct sk_buff *skb); void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb); void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb);
@ -2689,12 +2682,13 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len) static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
{ {
return memcpy_fromiovec(data, msg->msg_iov, len); /* XXX: stripping const */
return memcpy_fromiovec(data, (struct iovec *)msg->msg_iter.iov, len);
} }
static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len) static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
{ {
return memcpy_toiovec(msg->msg_iov, data, len); return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
} }
struct skb_checksum_ops { struct skb_checksum_ops {

View File

@ -47,8 +47,7 @@ struct linger {
struct msghdr { struct msghdr {
void *msg_name; /* ptr to socket address structure */ void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */ int msg_namelen; /* size of socket address structure */
struct iovec *msg_iov; /* scatter/gather array */ struct iov_iter msg_iter; /* data */
__kernel_size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data */ void *msg_control; /* ancillary data */
__kernel_size_t msg_controllen; /* ancillary data buffer length */ __kernel_size_t msg_controllen; /* ancillary data buffer length */
unsigned int msg_flags; /* flags on received message */ unsigned int msg_flags; /* flags on received message */

View File

@ -162,7 +162,7 @@ struct tcp_sock {
struct { struct {
struct sk_buff_head prequeue; struct sk_buff_head prequeue;
struct task_struct *task; struct task_struct *task;
struct iovec *iov; struct msghdr *msg;
int memory; int memory;
int len; int len;
} ucopy; } ucopy;

View File

@ -31,6 +31,7 @@ struct iov_iter {
size_t count; size_t count;
union { union {
const struct iovec *iov; const struct iovec *iov;
const struct kvec *kvec;
const struct bio_vec *bvec; const struct bio_vec *bvec;
}; };
unsigned long nr_segs; unsigned long nr_segs;
@ -82,10 +83,13 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
struct iov_iter *i); struct iov_iter *i);
size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i);
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i);
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i);
size_t iov_iter_zero(size_t bytes, struct iov_iter *); size_t iov_iter_zero(size_t bytes, struct iov_iter *);
unsigned long iov_iter_alignment(const struct iov_iter *i); unsigned long iov_iter_alignment(const struct iov_iter *i);
void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov,
unsigned long nr_segs, size_t count); unsigned long nr_segs, size_t count);
void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *iov,
unsigned long nr_segs, size_t count);
ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages,
size_t maxsize, unsigned maxpages, size_t *start); size_t maxsize, unsigned maxpages, size_t *start);
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages,
@ -123,9 +127,10 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
{ {
i->count = count; i->count = count;
} }
size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
int offset, int len); int offset, int len);
int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,

View File

@ -24,6 +24,7 @@
#define VMCI_KERNEL_API_VERSION_2 2 #define VMCI_KERNEL_API_VERSION_2 2
#define VMCI_KERNEL_API_VERSION VMCI_KERNEL_API_VERSION_2 #define VMCI_KERNEL_API_VERSION VMCI_KERNEL_API_VERSION_2
struct msghdr;
typedef void (vmci_device_shutdown_fn) (void *device_registration, typedef void (vmci_device_shutdown_fn) (void *device_registration,
void *user_data); void *user_data);
@ -75,8 +76,8 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair, void *buf, size_t buf_size,
ssize_t vmci_qpair_enquev(struct vmci_qp *qpair, ssize_t vmci_qpair_enquev(struct vmci_qp *qpair,
void *iov, size_t iov_size, int mode); void *iov, size_t iov_size, int mode);
ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
void *iov, size_t iov_size, int mode); struct msghdr *msg, size_t iov_size, int mode);
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, void *iov, size_t iov_size, ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, struct msghdr *msg, size_t iov_size,
int mode); int mode);
#endif /* !__VMW_VMCI_API_H__ */ #endif /* !__VMW_VMCI_API_H__ */

View File

@ -608,10 +608,6 @@ struct l2cap_ops {
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long hdr_len, unsigned long hdr_len,
unsigned long len, int nb); unsigned long len, int nb);
int (*memcpy_fromiovec) (struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len);
}; };
struct l2cap_conn { struct l2cap_conn {
@ -905,31 +901,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
return 0; return 0;
} }
static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov,
int len)
{
/* Following is safe since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment
*/
struct kvec *vec = (struct kvec *)iov;
while (len > 0) {
if (vec->iov_len) {
int copy = min_t(unsigned int, len, vec->iov_len);
memcpy(kdata, vec->iov_base, copy);
len -= copy;
kdata += copy;
vec->iov_base += copy;
vec->iov_len -= copy;
}
vec++;
}
return 0;
}
extern bool disable_ertm; extern bool disable_ertm;
int l2cap_init_sockets(void); int l2cap_init_sockets(void);

View File

@ -19,7 +19,9 @@ extern struct udp_table udplite_table;
static __inline__ int udplite_getfrag(void *from, char *to, int offset, static __inline__ int udplite_getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb) int len, int odd, struct sk_buff *skb)
{ {
return memcpy_fromiovecend(to, (struct iovec *) from, offset, len); struct msghdr *msg = from;
/* XXX: stripping const */
return memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len);
} }
/* Designate sk as UDP-Lite socket */ /* Designate sk as UDP-Lite socket */

View File

@ -27,31 +27,6 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
} }
EXPORT_SYMBOL(memcpy_fromiovec); EXPORT_SYMBOL(memcpy_fromiovec);
/*
* Copy kernel to iovec. Returns -EFAULT on error.
*
* Note: this modifies the original iovec.
*/
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
{
while (len > 0) {
if (iov->iov_len) {
int copy = min_t(unsigned int, iov->iov_len, len);
if (copy_to_user(iov->iov_base, kdata, copy))
return -EFAULT;
kdata += copy;
len -= copy;
iov->iov_len -= copy;
iov->iov_base += copy;
}
iov++;
}
return 0;
}
EXPORT_SYMBOL(memcpy_toiovec);
/* /*
* Copy kernel to iovec. Returns -EFAULT on error. * Copy kernel to iovec. Returns -EFAULT on error.
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -577,9 +577,6 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
struct atm_vcc *vcc; struct atm_vcc *vcc;
struct sk_buff *skb; struct sk_buff *skb;
int eff, error; int eff, error;
struct iov_iter from;
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, size);
lock_sock(sk); lock_sock(sk);
if (sock->state != SS_CONNECTED) { if (sock->state != SS_CONNECTED) {
@ -634,7 +631,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
goto out; goto out;
skb->dev = NULL; /* for paths shared with net_device interfaces */ skb->dev = NULL; /* for paths shared with net_device interfaces */
ATM_SKB(skb)->atm_options = vcc->atm_options; ATM_SKB(skb)->atm_options = vcc->atm_options;
if (copy_from_iter(skb_put(skb, size), size, &from) != size) { if (copy_from_iter(skb_put(skb, size), size, &m->msg_iter) != size) {
kfree_skb(skb); kfree_skb(skb);
error = -EFAULT; error = -EFAULT;
goto out; goto out;

View File

@ -537,12 +537,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
*/ */
chan->data = skb; chan->data = skb;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *) &iv;
msg.msg_iovlen = 1;
iv.iov_base = skb->data; iv.iov_base = skb->data;
iv.iov_len = skb->len; iv.iov_len = skb->len;
memset(&msg, 0, sizeof(msg));
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len);
err = l2cap_chan_send(chan, &msg, skb->len); err = l2cap_chan_send(chan, &msg, skb->len);
if (err > 0) { if (err > 0) {
netdev->stats.tx_bytes += err; netdev->stats.tx_bytes += err;
@ -1050,7 +1050,6 @@ static const struct l2cap_ops bt_6lowpan_chan_ops = {
.suspend = chan_suspend_cb, .suspend = chan_suspend_cb,
.get_sndtimeo = chan_get_sndtimeo_cb, .get_sndtimeo = chan_get_sndtimeo_cb,
.alloc_skb = chan_alloc_skb_cb, .alloc_skb = chan_alloc_skb_cb,
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
.teardown = l2cap_chan_no_teardown, .teardown = l2cap_chan_no_teardown,
.defer = l2cap_chan_no_defer, .defer = l2cap_chan_no_defer,

View File

@ -60,8 +60,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *) &iv; iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len);
msg.msg_iovlen = 1;
l2cap_chan_send(chan, &msg, total_len); l2cap_chan_send(chan, &msg, total_len);
@ -720,7 +719,6 @@ static const struct l2cap_ops a2mp_chan_ops = {
.resume = l2cap_chan_no_resume, .resume = l2cap_chan_no_resume,
.set_shutdown = l2cap_chan_no_set_shutdown, .set_shutdown = l2cap_chan_no_set_shutdown,
.get_sndtimeo = l2cap_chan_no_get_sndtimeo, .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
}; };
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)

View File

@ -2103,8 +2103,7 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
struct sk_buff **frag; struct sk_buff **frag;
int sent = 0; int sent = 0;
if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count), if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count)
msg->msg_iov, count))
return -EFAULT; return -EFAULT;
sent += count; sent += count;
@ -2124,8 +2123,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
*frag = tmp; *frag = tmp;
if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count), if (copy_from_iter(skb_put(*frag, count), count,
msg->msg_iov, count)) &msg->msg_iter) != count)
return -EFAULT; return -EFAULT;
sent += count; sent += count;

View File

@ -1336,13 +1336,6 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
return skb; return skb;
} }
static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan,
unsigned char *kdata,
struct iovec *iov, int len)
{
return memcpy_fromiovec(kdata, iov, len);
}
static void l2cap_sock_ready_cb(struct l2cap_chan *chan) static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
{ {
struct sock *sk = chan->data; struct sock *sk = chan->data;
@ -1427,7 +1420,6 @@ static const struct l2cap_ops l2cap_chan_ops = {
.set_shutdown = l2cap_sock_set_shutdown_cb, .set_shutdown = l2cap_sock_set_shutdown_cb,
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb, .get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb, .alloc_skb = l2cap_sock_alloc_skb_cb,
.memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb,
}; };
static void l2cap_sock_destruct(struct sock *sk) static void l2cap_sock_destruct(struct sock *sk)

View File

@ -539,8 +539,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *) &iv; iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len);
msg.msg_iovlen = 2;
l2cap_chan_send(chan, &msg, 1 + len); l2cap_chan_send(chan, &msg, 1 + len);
@ -2865,7 +2864,6 @@ static const struct l2cap_ops smp_chan_ops = {
.suspend = l2cap_chan_no_suspend, .suspend = l2cap_chan_no_suspend,
.set_shutdown = l2cap_chan_no_set_shutdown, .set_shutdown = l2cap_chan_no_set_shutdown,
.get_sndtimeo = l2cap_chan_no_get_sndtimeo, .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
}; };
static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
@ -2914,7 +2912,6 @@ static const struct l2cap_ops smp_root_chan_ops = {
.resume = l2cap_chan_no_resume, .resume = l2cap_chan_no_resume,
.set_shutdown = l2cap_chan_no_set_shutdown, .set_shutdown = l2cap_chan_no_set_shutdown,
.get_sndtimeo = l2cap_chan_no_get_sndtimeo, .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
}; };
static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)

View File

@ -535,7 +535,7 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto err; goto err;
ret = -EINVAL; ret = -EINVAL;
if (unlikely(msg->msg_iov->iov_base == NULL)) if (unlikely(msg->msg_iter.iov->iov_base == NULL))
goto err; goto err;
noblock = msg->msg_flags & MSG_DONTWAIT; noblock = msg->msg_flags & MSG_DONTWAIT;

View File

@ -37,13 +37,14 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
struct iovec **iov) struct iovec **iov)
{ {
compat_uptr_t uaddr, uiov, tmp3; compat_uptr_t uaddr, uiov, tmp3;
compat_size_t nr_segs;
ssize_t err; ssize_t err;
if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
__get_user(uaddr, &umsg->msg_name) || __get_user(uaddr, &umsg->msg_name) ||
__get_user(kmsg->msg_namelen, &umsg->msg_namelen) || __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
__get_user(uiov, &umsg->msg_iov) || __get_user(uiov, &umsg->msg_iov) ||
__get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || __get_user(nr_segs, &umsg->msg_iovlen) ||
__get_user(tmp3, &umsg->msg_control) || __get_user(tmp3, &umsg->msg_control) ||
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
__get_user(kmsg->msg_flags, &umsg->msg_flags)) __get_user(kmsg->msg_flags, &umsg->msg_flags))
@ -68,14 +69,15 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
kmsg->msg_namelen = 0; kmsg->msg_namelen = 0;
} }
if (kmsg->msg_iovlen > UIO_MAXIOV) if (nr_segs > UIO_MAXIOV)
return -EMSGSIZE; return -EMSGSIZE;
err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE,
compat_ptr(uiov), kmsg->msg_iovlen, compat_ptr(uiov), nr_segs,
UIO_FASTIOV, *iov, iov); UIO_FASTIOV, *iov, iov);
if (err >= 0) if (err >= 0)
kmsg->msg_iov = *iov; iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
*iov, nr_segs, err);
return err; return err;
} }

View File

@ -309,90 +309,6 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
} }
EXPORT_SYMBOL(skb_kill_datagram); EXPORT_SYMBOL(skb_kill_datagram);
/**
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
* @skb: buffer to copy
* @offset: offset in the buffer to start copying from
* @to: io vector to copy to
* @len: amount of data to copy from buffer to iovec
*
* Note: the iovec is modified during the copy.
*/
int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
struct iovec *to, int len)
{
int start = skb_headlen(skb);
int i, copy = start - offset;
struct sk_buff *frag_iter;
trace_skb_copy_datagram_iovec(skb, len);
/* Copy header. */
if (copy > 0) {
if (copy > len)
copy = len;
if (memcpy_toiovec(to, skb->data + offset, copy))
goto fault;
if ((len -= copy) == 0)
return 0;
offset += copy;
}
/* Copy paged appendix. Hmm... why does this look so complicated? */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
int end;
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
WARN_ON(start > offset + len);
end = start + skb_frag_size(frag);
if ((copy = end - offset) > 0) {
int err;
u8 *vaddr;
struct page *page = skb_frag_page(frag);
if (copy > len)
copy = len;
vaddr = kmap(page);
err = memcpy_toiovec(to, vaddr + frag->page_offset +
offset - start, copy);
kunmap(page);
if (err)
goto fault;
if (!(len -= copy))
return 0;
offset += copy;
}
start = end;
}
skb_walk_frags(skb, frag_iter) {
int end;
WARN_ON(start > offset + len);
end = start + frag_iter->len;
if ((copy = end - offset) > 0) {
if (copy > len)
copy = len;
if (skb_copy_datagram_iovec(frag_iter,
offset - start,
to, copy))
goto fault;
if ((len -= copy) == 0)
return 0;
offset += copy;
}
start = end;
}
if (!len)
return 0;
fault:
return -EFAULT;
}
EXPORT_SYMBOL(skb_copy_datagram_iovec);
/** /**
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator. * skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
* @skb: buffer to copy * @skb: buffer to copy
@ -615,27 +531,25 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
EXPORT_SYMBOL(zerocopy_sg_from_iter); EXPORT_SYMBOL(zerocopy_sg_from_iter);
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
u8 __user *to, int len, struct iov_iter *to, int len,
__wsum *csump) __wsum *csump)
{ {
int start = skb_headlen(skb); int start = skb_headlen(skb);
int i, copy = start - offset; int i, copy = start - offset;
struct sk_buff *frag_iter; struct sk_buff *frag_iter;
int pos = 0; int pos = 0;
int n;
/* Copy header. */ /* Copy header. */
if (copy > 0) { if (copy > 0) {
int err = 0;
if (copy > len) if (copy > len)
copy = len; copy = len;
*csump = csum_and_copy_to_user(skb->data + offset, to, copy, n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
*csump, &err); if (n != copy)
if (err)
goto fault; goto fault;
if ((len -= copy) == 0) if ((len -= copy) == 0)
return 0; return 0;
offset += copy; offset += copy;
to += copy;
pos = copy; pos = copy;
} }
@ -647,26 +561,22 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
end = start + skb_frag_size(frag); end = start + skb_frag_size(frag);
if ((copy = end - offset) > 0) { if ((copy = end - offset) > 0) {
__wsum csum2; __wsum csum2 = 0;
int err = 0;
u8 *vaddr;
struct page *page = skb_frag_page(frag); struct page *page = skb_frag_page(frag);
u8 *vaddr = kmap(page);
if (copy > len) if (copy > len)
copy = len; copy = len;
vaddr = kmap(page); n = csum_and_copy_to_iter(vaddr + frag->page_offset +
csum2 = csum_and_copy_to_user(vaddr + offset - start, copy,
frag->page_offset + &csum2, to);
offset - start,
to, copy, 0, &err);
kunmap(page); kunmap(page);
if (err) if (n != copy)
goto fault; goto fault;
*csump = csum_block_add(*csump, csum2, pos); *csump = csum_block_add(*csump, csum2, pos);
if (!(len -= copy)) if (!(len -= copy))
return 0; return 0;
offset += copy; offset += copy;
to += copy;
pos += copy; pos += copy;
} }
start = end; start = end;
@ -691,7 +601,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
if ((len -= copy) == 0) if ((len -= copy) == 0)
return 0; return 0;
offset += copy; offset += copy;
to += copy;
pos += copy; pos += copy;
} }
start = end; start = end;
@ -744,20 +653,19 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb)
EXPORT_SYMBOL(__skb_checksum_complete); EXPORT_SYMBOL(__skb_checksum_complete);
/** /**
* skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec. * skb_copy_and_csum_datagram_msg - Copy and checksum skb to user iovec.
* @skb: skbuff * @skb: skbuff
* @hlen: hardware length * @hlen: hardware length
* @iov: io vector * @msg: destination
* *
* Caller _must_ check that skb will fit to this iovec. * Caller _must_ check that skb will fit to this iovec.
* *
* Returns: 0 - success. * Returns: 0 - success.
* -EINVAL - checksum failure. * -EINVAL - checksum failure.
* -EFAULT - fault during copy. Beware, in this case iovec * -EFAULT - fault during copy.
* can be modified!
*/ */
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
int hlen, struct iovec *iov) int hlen, struct msghdr *msg)
{ {
__wsum csum; __wsum csum;
int chunk = skb->len - hlen; int chunk = skb->len - hlen;
@ -765,28 +673,20 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
if (!chunk) if (!chunk)
return 0; return 0;
/* Skip filled elements. if (iov_iter_count(&msg->msg_iter) < chunk) {
* Pretty silly, look at memcpy_toiovec, though 8)
*/
while (!iov->iov_len)
iov++;
if (iov->iov_len < chunk) {
if (__skb_checksum_complete(skb)) if (__skb_checksum_complete(skb))
goto csum_error; goto csum_error;
if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
goto fault; goto fault;
} else { } else {
csum = csum_partial(skb->data, hlen, skb->csum); csum = csum_partial(skb->data, hlen, skb->csum);
if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter,
chunk, &csum)) chunk, &csum))
goto fault; goto fault;
if (csum_fold(csum)) if (csum_fold(csum))
goto csum_error; goto csum_error;
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
netdev_rx_csum_fault(skb->dev); netdev_rx_csum_fault(skb->dev);
iov->iov_len -= chunk;
iov->iov_base += chunk;
} }
return 0; return 0;
csum_error: csum_error:
@ -794,7 +694,7 @@ csum_error:
fault: fault:
return -EFAULT; return -EFAULT;
} }
EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg);
/** /**
* datagram_poll - generic datagram poll * datagram_poll - generic datagram poll

View File

@ -752,14 +752,16 @@ EXPORT_SYMBOL(ip_fragment);
int int
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
{ {
struct iovec *iov = from; struct msghdr *msg = from;
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (memcpy_fromiovecend(to, iov, offset, len) < 0) /* XXX: stripping const */
if (memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len) < 0)
return -EFAULT; return -EFAULT;
} else { } else {
__wsum csum = 0; __wsum csum = 0;
if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0) /* XXX: stripping const */
if (csum_partial_copy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len, &csum) < 0)
return -EFAULT; return -EFAULT;
skb->csum = csum_block_add(skb->csum, csum, odd); skb->csum = csum_block_add(skb->csum, csum, odd);
} }

View File

@ -811,7 +811,8 @@ back_from_confirm:
pfh.icmph.checksum = 0; pfh.icmph.checksum = 0;
pfh.icmph.un.echo.id = inet->inet_sport; pfh.icmph.un.echo.id = inet->inet_sport;
pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
pfh.iov = msg->msg_iov; /* XXX: stripping const */
pfh.iov = (struct iovec *)msg->msg_iter.iov;
pfh.wcheck = 0; pfh.wcheck = 0;
pfh.family = AF_INET; pfh.family = AF_INET;

View File

@ -82,7 +82,7 @@
#include <linux/uio.h> #include <linux/uio.h>
struct raw_frag_vec { struct raw_frag_vec {
struct iovec *iov; struct msghdr *msg;
union { union {
struct icmphdr icmph; struct icmphdr icmph;
char c[1]; char c[1];
@ -440,7 +440,7 @@ static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4)
/* We only need the first two bytes. */ /* We only need the first two bytes. */
rfv->hlen = 2; rfv->hlen = 2;
err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen); err = memcpy_from_msg(rfv->hdr.c, rfv->msg, rfv->hlen);
if (err) if (err)
return err; return err;
@ -478,7 +478,7 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
offset -= rfv->hlen; offset -= rfv->hlen;
return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb); return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
} }
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@ -600,7 +600,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
daddr, saddr, 0, 0); daddr, saddr, 0, 0);
if (!inet->hdrincl) { if (!inet->hdrincl) {
rfv.iov = msg->msg_iov; rfv.msg = msg;
rfv.hlen = 0; rfv.hlen = 0;
err = raw_probe_proto_opt(&rfv, &fl4); err = raw_probe_proto_opt(&rfv, &fl4);
@ -625,7 +625,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
back_from_confirm: back_from_confirm:
if (inet->hdrincl) if (inet->hdrincl)
err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len, /* XXX: stripping const */
err = raw_send_hdrinc(sk, &fl4, (struct iovec *)msg->msg_iter.iov, len,
&rt, msg->msg_flags); &rt, msg->msg_flags);
else { else {

View File

@ -1067,7 +1067,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t size) size_t size)
{ {
struct iovec *iov; const struct iovec *iov;
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
int iovlen, flags, err, copied = 0; int iovlen, flags, err, copied = 0;
@ -1118,8 +1118,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
mss_now = tcp_send_mss(sk, &size_goal, flags); mss_now = tcp_send_mss(sk, &size_goal, flags);
/* Ok commence sending. */ /* Ok commence sending. */
iovlen = msg->msg_iovlen; iovlen = msg->msg_iter.nr_segs;
iov = msg->msg_iov; iov = msg->msg_iter.iov;
copied = 0; copied = 0;
err = -EPIPE; err = -EPIPE;
@ -1711,7 +1711,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) { if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
user_recv = current; user_recv = current;
tp->ucopy.task = user_recv; tp->ucopy.task = user_recv;
tp->ucopy.iov = msg->msg_iov; tp->ucopy.msg = msg;
} }
tp->ucopy.len = len; tp->ucopy.len = len;

View File

@ -4421,7 +4421,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
local_bh_enable(); local_bh_enable();
if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) { if (!skb_copy_datagram_msg(skb, 0, tp->ucopy.msg, chunk)) {
tp->ucopy.len -= chunk; tp->ucopy.len -= chunk;
tp->copied_seq += chunk; tp->copied_seq += chunk;
eaten = (chunk == skb->len); eaten = (chunk == skb->len);
@ -4941,10 +4941,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
local_bh_enable(); local_bh_enable();
if (skb_csum_unnecessary(skb)) if (skb_csum_unnecessary(skb))
err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk); err = skb_copy_datagram_msg(skb, hlen, tp->ucopy.msg, chunk);
else else
err = skb_copy_and_csum_datagram_iovec(skb, hlen, err = skb_copy_and_csum_datagram_msg(skb, hlen, tp->ucopy.msg);
tp->ucopy.iov);
if (!err) { if (!err) {
tp->ucopy.len -= chunk; tp->ucopy.len -= chunk;

View File

@ -3073,7 +3073,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
syn_data->ip_summed = CHECKSUM_PARTIAL; syn_data->ip_summed = CHECKSUM_PARTIAL;
memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
fo->data->msg_iov, 0, space))) { fo->data->msg_iter.iov, 0, space))) {
kfree_skb(syn_data); kfree_skb(syn_data);
goto fallback; goto fallback;
} }

View File

@ -1049,7 +1049,7 @@ back_from_confirm:
/* Lockless fast path for the non-corking case. */ /* Lockless fast path for the non-corking case. */
if (!corkreq) { if (!corkreq) {
skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen, skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
sizeof(struct udphdr), &ipc, &rt, sizeof(struct udphdr), &ipc, &rt,
msg->msg_flags); msg->msg_flags);
err = PTR_ERR(skb); err = PTR_ERR(skb);
@ -1080,7 +1080,7 @@ back_from_confirm:
do_append_data: do_append_data:
up->len += ulen; up->len += ulen;
err = ip_append_data(sk, fl4, getfrag, msg->msg_iov, ulen, err = ip_append_data(sk, fl4, getfrag, msg, ulen,
sizeof(struct udphdr), &ipc, &rt, sizeof(struct udphdr), &ipc, &rt,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
if (err) if (err)

View File

@ -163,7 +163,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
pfh.icmph.checksum = 0; pfh.icmph.checksum = 0;
pfh.icmph.un.echo.id = inet->inet_sport; pfh.icmph.un.echo.id = inet->inet_sport;
pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence;
pfh.iov = msg->msg_iov; /* XXX: stripping const */
pfh.iov = (struct iovec *)msg->msg_iter.iov;
pfh.wcheck = 0; pfh.wcheck = 0;
pfh.family = AF_INET6; pfh.family = AF_INET6;

View File

@ -672,65 +672,62 @@ error:
return err; return err;
} }
static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) struct raw6_frag_vec {
struct msghdr *msg;
int hlen;
char c[4];
};
static int rawv6_probe_proto_opt(struct raw6_frag_vec *rfv, struct flowi6 *fl6)
{ {
struct iovec *iov; int err = 0;
u8 __user *type = NULL; switch (fl6->flowi6_proto) {
u8 __user *code = NULL; case IPPROTO_ICMPV6:
u8 len = 0; rfv->hlen = 2;
int probed = 0; err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen);
int i; if (!err) {
fl6->fl6_icmp_type = rfv->c[0];
if (!msg->msg_iov) fl6->fl6_icmp_code = rfv->c[1];
return 0;
for (i = 0; i < msg->msg_iovlen; i++) {
iov = &msg->msg_iov[i];
if (!iov)
continue;
switch (fl6->flowi6_proto) {
case IPPROTO_ICMPV6:
/* check if one-byte field is readable or not. */
if (iov->iov_base && iov->iov_len < 1)
break;
if (!type) {
type = iov->iov_base;
/* check if code field is readable or not. */
if (iov->iov_len > 1)
code = type + 1;
} else if (!code)
code = iov->iov_base;
if (type && code) {
if (get_user(fl6->fl6_icmp_type, type) ||
get_user(fl6->fl6_icmp_code, code))
return -EFAULT;
probed = 1;
}
break;
case IPPROTO_MH:
if (iov->iov_base && iov->iov_len < 1)
break;
/* check if type field is readable or not. */
if (iov->iov_len > 2 - len) {
u8 __user *p = iov->iov_base;
if (get_user(fl6->fl6_mh_type, &p[2 - len]))
return -EFAULT;
probed = 1;
} else
len += iov->iov_len;
break;
default:
probed = 1;
break;
} }
if (probed) break;
break; case IPPROTO_MH:
rfv->hlen = 4;
err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen);
if (!err)
fl6->fl6_mh_type = rfv->c[2];
} }
return 0; return err;
}
static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
struct sk_buff *skb)
{
struct raw6_frag_vec *rfv = from;
if (offset < rfv->hlen) {
int copy = min(rfv->hlen - offset, len);
if (skb->ip_summed == CHECKSUM_PARTIAL)
memcpy(to, rfv->c + offset, copy);
else
skb->csum = csum_block_add(
skb->csum,
csum_partial_copy_nocheck(rfv->c + offset,
to, copy, 0),
odd);
odd = 0;
offset += copy;
to += copy;
len -= copy;
if (!len)
return 0;
}
offset -= rfv->hlen;
return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
} }
static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@ -745,6 +742,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
struct ipv6_txoptions *opt = NULL; struct ipv6_txoptions *opt = NULL;
struct ip6_flowlabel *flowlabel = NULL; struct ip6_flowlabel *flowlabel = NULL;
struct dst_entry *dst = NULL; struct dst_entry *dst = NULL;
struct raw6_frag_vec rfv;
struct flowi6 fl6; struct flowi6 fl6;
int addr_len = msg->msg_namelen; int addr_len = msg->msg_namelen;
int hlimit = -1; int hlimit = -1;
@ -848,7 +846,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
opt = ipv6_fixup_options(&opt_space, opt); opt = ipv6_fixup_options(&opt_space, opt);
fl6.flowi6_proto = proto; fl6.flowi6_proto = proto;
err = rawv6_probe_proto_opt(&fl6, msg); rfv.msg = msg;
rfv.hlen = 0;
err = rawv6_probe_proto_opt(&rfv, &fl6);
if (err) if (err)
goto out; goto out;
@ -886,10 +886,11 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
back_from_confirm: back_from_confirm:
if (inet->hdrincl) if (inet->hdrincl)
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags); /* XXX: stripping const */
err = rawv6_send_hdrinc(sk, (struct iovec *)msg->msg_iter.iov, len, &fl6, &dst, msg->msg_flags);
else { else {
lock_sock(sk); lock_sock(sk);
err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, err = ip6_append_data(sk, raw6_getfrag, &rfv,
len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst,
msg->msg_flags, dontfrag); msg->msg_flags, dontfrag);

View File

@ -1312,7 +1312,7 @@ do_append_data:
dontfrag = np->dontfrag; dontfrag = np->dontfrag;
up->len += ulen; up->len += ulen;
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, err = ip6_append_data(sk, getfrag, msg, ulen,
sizeof(struct udphdr), hlimit, tclass, opt, &fl6, sizeof(struct udphdr), hlimit, tclass, opt, &fl6,
(struct rt6_info *)dst, (struct rt6_info *)dst,
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag);

View File

@ -619,7 +619,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
back_from_confirm: back_from_confirm:
lock_sock(sk); lock_sock(sk);
err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, err = ip6_append_data(sk, ip_generic_getfrag, msg,
ulen, transhdrlen, hlimit, tclass, opt, ulen, transhdrlen, hlimit, tclass, opt,
&fl6, (struct rt6_info *)dst, &fl6, (struct rt6_info *)dst,
msg->msg_flags, dontfrag); msg->msg_flags, dontfrag);

View File

@ -2305,7 +2305,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
} }
if (netlink_tx_is_mmaped(sk) && if (netlink_tx_is_mmaped(sk) &&
msg->msg_iov->iov_base == NULL) { msg->msg_iter.iov->iov_base == NULL) {
err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
siocb); siocb);
goto out; goto out;

View File

@ -2408,11 +2408,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
unsigned short gso_type = 0; unsigned short gso_type = 0;
int hlen, tlen; int hlen, tlen;
int extra_len = 0; int extra_len = 0;
struct iov_iter from;
ssize_t n; ssize_t n;
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
/* /*
* Get and verify the address. * Get and verify the address.
*/ */
@ -2451,7 +2448,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
len -= vnet_hdr_len; len -= vnet_hdr_len;
err = -EFAULT; err = -EFAULT;
n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &from); n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &msg->msg_iter);
if (n != vnet_hdr_len) if (n != vnet_hdr_len)
goto out_unlock; goto out_unlock;
@ -2522,7 +2519,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
} }
/* Returns -EFAULT on error */ /* Returns -EFAULT on error */
err = skb_copy_datagram_from_iter(skb, offset, &from, len); err = skb_copy_datagram_from_iter(skb, offset, &msg->msg_iter, len);
if (err) if (err)
goto out_free; goto out_free;

View File

@ -404,7 +404,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; int ret = 0, nonblock = msg_flags & MSG_DONTWAIT;
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
struct rds_incoming *inc = NULL; struct rds_incoming *inc = NULL;
struct iov_iter to;
/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ /* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */
timeo = sock_rcvtimeo(sk, nonblock); timeo = sock_rcvtimeo(sk, nonblock);
@ -415,6 +414,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
goto out; goto out;
while (1) { while (1) {
struct iov_iter save;
/* If there are pending notifications, do those - and nothing else */ /* If there are pending notifications, do those - and nothing else */
if (!list_empty(&rs->rs_notify_queue)) { if (!list_empty(&rs->rs_notify_queue)) {
ret = rds_notify_queue_get(rs, msg); ret = rds_notify_queue_get(rs, msg);
@ -450,8 +450,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
rdsdebug("copying inc %p from %pI4:%u to user\n", inc, rdsdebug("copying inc %p from %pI4:%u to user\n", inc,
&inc->i_conn->c_faddr, &inc->i_conn->c_faddr,
ntohs(inc->i_hdr.h_sport)); ntohs(inc->i_hdr.h_sport));
iov_iter_init(&to, READ, msg->msg_iov, msg->msg_iovlen, size); save = msg->msg_iter;
ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &to); ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter);
if (ret < 0) if (ret < 0)
break; break;
@ -464,6 +464,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
rds_inc_put(inc); rds_inc_put(inc);
inc = NULL; inc = NULL;
rds_stats_inc(s_recv_deliver_raced); rds_stats_inc(s_recv_deliver_raced);
msg->msg_iter = save;
continue; continue;
} }

View File

@ -934,9 +934,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
int queued = 0, allocated_mr = 0; int queued = 0, allocated_mr = 0;
int nonblock = msg->msg_flags & MSG_DONTWAIT; int nonblock = msg->msg_flags & MSG_DONTWAIT;
long timeo = sock_sndtimeo(sk, nonblock); long timeo = sock_sndtimeo(sk, nonblock);
struct iov_iter from;
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, payload_len);
/* Mirror Linux UDP mirror of BSD error message compatibility */ /* Mirror Linux UDP mirror of BSD error message compatibility */
/* XXX: Perhaps MSG_MORE someday */ /* XXX: Perhaps MSG_MORE someday */
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) { if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
@ -984,7 +982,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
ret = rds_message_copy_from_user(rm, &from); ret = rds_message_copy_from_user(rm, &msg->msg_iter);
if (ret) if (ret)
goto out; goto out;
} }

View File

@ -531,14 +531,12 @@ static int rxrpc_send_data(struct kiocb *iocb,
struct rxrpc_skb_priv *sp; struct rxrpc_skb_priv *sp;
unsigned char __user *from; unsigned char __user *from;
struct sk_buff *skb; struct sk_buff *skb;
struct iovec *iov; const struct iovec *iov;
struct sock *sk = &rx->sk; struct sock *sk = &rx->sk;
long timeo; long timeo;
bool more; bool more;
int ret, ioc, segment, copied; int ret, ioc, segment, copied;
_enter(",,,{%zu},%zu", msg->msg_iovlen, len);
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
/* this should be in poll */ /* this should be in poll */
@ -547,8 +545,8 @@ static int rxrpc_send_data(struct kiocb *iocb,
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
return -EPIPE; return -EPIPE;
iov = msg->msg_iov; iov = msg->msg_iter.iov;
ioc = msg->msg_iovlen - 1; ioc = msg->msg_iter.nr_segs - 1;
from = iov->iov_base; from = iov->iov_base;
segment = iov->iov_len; segment = iov->iov_len;
iov++; iov++;

View File

@ -1609,9 +1609,6 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
__u16 sinfo_flags = 0; __u16 sinfo_flags = 0;
long timeo; long timeo;
int err; int err;
struct iov_iter from;
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, msg_len);
err = 0; err = 0;
sp = sctp_sk(sk); sp = sctp_sk(sk);
@ -1950,7 +1947,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
} }
/* Break the message into multiple chunks of maximum size. */ /* Break the message into multiple chunks of maximum size. */
datamsg = sctp_datamsg_from_user(asoc, sinfo, &from); datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter);
if (IS_ERR(datamsg)) { if (IS_ERR(datamsg)) {
err = PTR_ERR(datamsg); err = PTR_ERR(datamsg);
goto out_free; goto out_free;

View File

@ -689,8 +689,7 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
* the following is safe, since for compiler definitions of kvec and * the following is safe, since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment * iovec are identical, yielding the same in-core layout and alignment
*/ */
msg->msg_iov = (struct iovec *)vec; iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size);
msg->msg_iovlen = num;
result = sock_sendmsg(sock, msg, size); result = sock_sendmsg(sock, msg, size);
set_fs(oldfs); set_fs(oldfs);
return result; return result;
@ -853,7 +852,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
* the following is safe, since for compiler definitions of kvec and * the following is safe, since for compiler definitions of kvec and
* iovec are identical, yielding the same in-core layout and alignment * iovec are identical, yielding the same in-core layout and alignment
*/ */
msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size);
result = sock_recvmsg(sock, msg, size, flags); result = sock_recvmsg(sock, msg, size, flags);
set_fs(oldfs); set_fs(oldfs);
return result; return result;
@ -913,8 +912,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
msg->msg_namelen = 0; msg->msg_namelen = 0;
msg->msg_control = NULL; msg->msg_control = NULL;
msg->msg_controllen = 0; msg->msg_controllen = 0;
msg->msg_iov = (struct iovec *)iov; iov_iter_init(&msg->msg_iter, READ, iov, nr_segs, size);
msg->msg_iovlen = nr_segs;
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags); return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
@ -953,8 +951,7 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
msg->msg_namelen = 0; msg->msg_namelen = 0;
msg->msg_control = NULL; msg->msg_control = NULL;
msg->msg_controllen = 0; msg->msg_controllen = 0;
msg->msg_iov = (struct iovec *)iov; iov_iter_init(&msg->msg_iter, WRITE, iov, nr_segs, size);
msg->msg_iovlen = nr_segs;
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
if (sock->type == SOCK_SEQPACKET) if (sock->type == SOCK_SEQPACKET)
msg->msg_flags |= MSG_EOR; msg->msg_flags |= MSG_EOR;
@ -1798,8 +1795,7 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
iov.iov_base = buff; iov.iov_base = buff;
iov.iov_len = len; iov.iov_len = len;
msg.msg_name = NULL; msg.msg_name = NULL;
msg.msg_iov = &iov; iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len);
msg.msg_iovlen = 1;
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_namelen = 0; msg.msg_namelen = 0;
@ -1856,10 +1852,9 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
msg.msg_control = NULL; msg.msg_control = NULL;
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = &iov;
iov.iov_len = size; iov.iov_len = size;
iov.iov_base = ubuf; iov.iov_base = ubuf;
iov_iter_init(&msg.msg_iter, READ, &iov, 1, size);
/* Save some cycles and don't copy the address if not needed */ /* Save some cycles and don't copy the address if not needed */
msg.msg_name = addr ? (struct sockaddr *)&address : NULL; msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
/* We assume all kernel code knows the size of sockaddr_storage */ /* We assume all kernel code knows the size of sockaddr_storage */
@ -1993,13 +1988,14 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
{ {
struct sockaddr __user *uaddr; struct sockaddr __user *uaddr;
struct iovec __user *uiov; struct iovec __user *uiov;
size_t nr_segs;
ssize_t err; ssize_t err;
if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
__get_user(uaddr, &umsg->msg_name) || __get_user(uaddr, &umsg->msg_name) ||
__get_user(kmsg->msg_namelen, &umsg->msg_namelen) || __get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
__get_user(uiov, &umsg->msg_iov) || __get_user(uiov, &umsg->msg_iov) ||
__get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || __get_user(nr_segs, &umsg->msg_iovlen) ||
__get_user(kmsg->msg_control, &umsg->msg_control) || __get_user(kmsg->msg_control, &umsg->msg_control) ||
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
__get_user(kmsg->msg_flags, &umsg->msg_flags)) __get_user(kmsg->msg_flags, &umsg->msg_flags))
@ -2029,14 +2025,15 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
kmsg->msg_namelen = 0; kmsg->msg_namelen = 0;
} }
if (kmsg->msg_iovlen > UIO_MAXIOV) if (nr_segs > UIO_MAXIOV)
return -EMSGSIZE; return -EMSGSIZE;
err = rw_copy_check_uvector(save_addr ? READ : WRITE, err = rw_copy_check_uvector(save_addr ? READ : WRITE,
uiov, kmsg->msg_iovlen, uiov, nr_segs,
UIO_FASTIOV, *iov, iov); UIO_FASTIOV, *iov, iov);
if (err >= 0) if (err >= 0)
kmsg->msg_iov = *iov; iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
*iov, nr_segs, err);
return err; return err;
} }

View File

@ -194,7 +194,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
__skb_queue_tail(list, skb); __skb_queue_tail(list, skb);
skb_copy_to_linear_data(skb, mhdr, mhsz); skb_copy_to_linear_data(skb, mhdr, mhsz);
pktpos = skb->data + mhsz; pktpos = skb->data + mhsz;
if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iov, offset, if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset,
dsz)) dsz))
return dsz; return dsz;
rc = -EFAULT; rc = -EFAULT;
@ -224,7 +224,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
if (drem < pktrem) if (drem < pktrem)
pktrem = drem; pktrem = drem;
if (memcpy_fromiovecend(pktpos, m->msg_iov, offset, pktrem)) { if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) {
rc = -EFAULT; rc = -EFAULT;
goto error; goto error;
} }

View File

@ -1459,9 +1459,6 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct scm_cookie tmp_scm; struct scm_cookie tmp_scm;
int max_level; int max_level;
int data_len = 0; int data_len = 0;
struct iov_iter from;
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
if (NULL == siocb->scm) if (NULL == siocb->scm)
siocb->scm = &tmp_scm; siocb->scm = &tmp_scm;
@ -1519,7 +1516,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
skb_put(skb, len - data_len); skb_put(skb, len - data_len);
skb->data_len = data_len; skb->data_len = data_len;
skb->len = len; skb->len = len;
err = skb_copy_datagram_from_iter(skb, 0, &from, len); err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len);
if (err) if (err)
goto out_free; goto out_free;
@ -1641,9 +1638,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
bool fds_sent = false; bool fds_sent = false;
int max_level; int max_level;
int data_len; int data_len;
struct iov_iter from;
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
if (NULL == siocb->scm) if (NULL == siocb->scm)
siocb->scm = &tmp_scm; siocb->scm = &tmp_scm;
@ -1700,7 +1694,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
skb_put(skb, size - data_len); skb_put(skb, size - data_len);
skb->data_len = data_len; skb->data_len = data_len;
skb->len = size; skb->len = size;
err = skb_copy_datagram_from_iter(skb, 0, &from, size); err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
if (err) { if (err) {
kfree_skb(skb); kfree_skb(skb);
goto out_err; goto out_err;

View File

@ -1840,9 +1840,9 @@ static ssize_t vmci_transport_stream_dequeue(
int flags) int flags)
{ {
if (flags & MSG_PEEK) if (flags & MSG_PEEK)
return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg, len, 0);
else else
return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg, len, 0);
} }
static ssize_t vmci_transport_stream_enqueue( static ssize_t vmci_transport_stream_enqueue(
@ -1850,7 +1850,8 @@ static ssize_t vmci_transport_stream_enqueue(
struct msghdr *msg, struct msghdr *msg,
size_t len) size_t len)
{ {
return vmci_qpair_enquev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); /* XXX: stripping const */
return vmci_qpair_enquev(vmci_trans(vsk)->qpair, (struct iovec *)msg->msg_iter.iov, len, 0);
} }
static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk) static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk)