diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-20 07:01:29 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-11-24 05:16:42 -0500 |
commit | 7424ce65065852bdf7a040bf2490da4a8fc4b464 (patch) | |
tree | b5a44fdeca7a925a2c763bb60a290c0b9bc6a11d /net/atm | |
parent | 0f7db23a07af5de22940f08c3f88a0741d4df0bc (diff) | |
download | linux-stable-7424ce65065852bdf7a040bf2490da4a8fc4b464.tar.gz linux-stable-7424ce65065852bdf7a040bf2490da4a8fc4b464.tar.bz2 linux-stable-7424ce65065852bdf7a040bf2490da4a8fc4b464.zip |
[atm] switch vcc_sendmsg() to copy_from_iter()
... and make it handle multi-segment iovecs - deals with that
"fix this later" issue for free. A bit of shame, really - it
had been there since 2.3.15pre3 when the whole thing went into the
tree, practically a historical artefact by now...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/atm')
-rw-r--r-- | net/atm/common.c | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/net/atm/common.c b/net/atm/common.c index 9cd1ccae9a11..f59112944c91 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -570,15 +570,16 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, } int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - size_t total_len) + size_t size) { struct sock *sk = sock->sk; DEFINE_WAIT(wait); struct atm_vcc *vcc; struct sk_buff *skb; int eff, error; - const void __user *buff; - int size; + struct iov_iter from; + + iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, size); lock_sock(sk); if (sock->state != SS_CONNECTED) { @@ -589,12 +590,6 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, error = -EISCONN; goto out; } - if (m->msg_iovlen != 1) { - error = -ENOSYS; /* fix this later @@@ */ - goto out; - } - buff = m->msg_iov->iov_base; - size = m->msg_iov->iov_len; vcc = ATM_SD(sock); if (test_bit(ATM_VF_RELEASED, &vcc->flags) || test_bit(ATM_VF_CLOSE, &vcc->flags) || @@ -607,7 +602,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, error = 0; goto out; } - if (size < 0 || size > vcc->qos.txtp.max_sdu) { + if (size > vcc->qos.txtp.max_sdu) { error = -EMSGSIZE; goto out; } @@ -639,7 +634,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, goto out; skb->dev = NULL; /* for paths shared with net_device interfaces */ ATM_SKB(skb)->atm_options = vcc->atm_options; - if (copy_from_user(skb_put(skb, size), buff, size)) { + if (copy_from_iter(skb_put(skb, size), size, &from) != size) { kfree_skb(skb); error = -EFAULT; goto out; |