提交 c0371da6 编写于 作者: A Al Viro

put iov_iter into msghdr

Note that the code _using_ ->msg_iter at that point will be very
unhappy with anything other than unshifted iovec-backed iov_iter.
We still need to convert users to proper primitives.
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 d838df2e
...@@ -42,7 +42,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock, ...@@ -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, ...@@ -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;
......
...@@ -429,13 +429,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, ...@@ -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;
......
...@@ -1095,9 +1095,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -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, ...@@ -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;
......
...@@ -1449,13 +1449,11 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -342,7 +342,6 @@ static void handle_tx(struct vhost_net *net) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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:
......
...@@ -306,8 +306,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -2646,22 +2646,24 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, ...@@ -2646,22 +2646,24 @@ 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_iovec(const struct sk_buff *from, int offset,
struct iovec *to, int size); struct iovec *to, int size);
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
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); /* XXX: stripping const */
return skb_copy_datagram_iovec(from, offset, (struct iovec *)msg->msg_iter.iov, size);
} }
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
struct iovec *iov); struct iovec *iov);
static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen, static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
struct msghdr *msg) struct msghdr *msg)
{ {
return skb_copy_and_csum_datagram_iovec(skb, hlen, msg->msg_iov); /* XXX: stripping const */
return skb_copy_and_csum_datagram_iovec(skb, hlen, (struct iovec *)msg->msg_iter.iov);
} }
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 +2691,14 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); ...@@ -2689,12 +2691,14 @@ 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); /* XXX: stripping const */
return memcpy_toiovec((struct iovec *)msg->msg_iter.iov, data, len);
} }
struct skb_checksum_ops { struct skb_checksum_ops {
......
...@@ -47,8 +47,7 @@ struct linger { ...@@ -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 */
......
...@@ -911,7 +911,7 @@ static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan, ...@@ -911,7 +911,7 @@ static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan,
/* Following is safe since for compiler definitions of kvec and /* 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
*/ */
struct kvec *vec = (struct kvec *)msg->msg_iov; struct kvec *vec = (struct kvec *)msg->msg_iter.iov;
while (len > 0) { while (len > 0) {
if (vec->iov_len) { if (vec->iov_len) {
......
...@@ -20,7 +20,8 @@ static __inline__ int udplite_getfrag(void *from, char *to, int offset, ...@@ -20,7 +20,8 @@ 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)
{ {
struct msghdr *msg = from; struct msghdr *msg = from;
return memcpy_fromiovecend(to, msg->msg_iov, offset, len); /* 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 */
......
...@@ -577,9 +577,6 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, ...@@ -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, ...@@ -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;
......
...@@ -537,12 +537,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, ...@@ -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_init(&msg.msg_iter, WRITE, (struct iovec *) &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;
......
...@@ -60,8 +60,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) ...@@ -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_init(&msg.msg_iter, WRITE, (struct iovec *)&iv, 1, total_len);
msg.msg_iovlen = 1;
l2cap_chan_send(chan, &msg, total_len); l2cap_chan_send(chan, &msg, total_len);
......
...@@ -268,8 +268,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) ...@@ -268,8 +268,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_init(&msg.msg_iter, WRITE, (struct iovec *)iv, 2, 1 + len);
msg.msg_iovlen = 2;
l2cap_chan_send(chan, &msg, 1 + len); l2cap_chan_send(chan, &msg, 1 + len);
......
...@@ -535,7 +535,7 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -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;
......
...@@ -37,13 +37,14 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg, ...@@ -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, ...@@ -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;
} }
......
...@@ -755,11 +755,13 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk ...@@ -755,11 +755,13 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
struct msghdr *msg = from; struct msghdr *msg = from;
if (skb->ip_summed == CHECKSUM_PARTIAL) { if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (memcpy_fromiovecend(to, msg->msg_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, msg->msg_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);
} }
......
...@@ -811,7 +811,8 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m ...@@ -811,7 +811,8 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
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;
......
...@@ -625,7 +625,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -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 {
......
...@@ -1085,7 +1085,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, ...@@ -1085,7 +1085,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;
...@@ -1136,8 +1136,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -1136,8 +1136,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;
......
...@@ -3050,7 +3050,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) ...@@ -3050,7 +3050,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;
} }
......
...@@ -163,7 +163,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -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;
......
...@@ -886,7 +886,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -886,7 +886,8 @@ 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, raw6_getfrag, &rfv, err = ip6_append_data(sk, raw6_getfrag, &rfv,
......
...@@ -2305,7 +2305,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -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;
......
...@@ -2408,11 +2408,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -404,7 +404,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -934,9 +934,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, ...@@ -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, ...@@ -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;
} }
......
...@@ -531,14 +531,12 @@ static int rxrpc_send_data(struct kiocb *iocb, ...@@ -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, ...@@ -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++;
......
...@@ -1609,9 +1609,6 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -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, ...@@ -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;
......
...@@ -689,8 +689,7 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -194,7 +194,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, ...@@ -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, ...@@ -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;
} }
......
...@@ -1459,9 +1459,6 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -1850,7 +1850,8 @@ 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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册