775 lines
25 KiB
Diff
775 lines
25 KiB
Diff
Bugzilla: 1039874
|
|
Upstream-status: 3.13 and 3.12.4
|
|
|
|
From 9cb9fb275f8794546dc31a79f2f02127fed5baf2 Mon Sep 17 00:00:00 2001
|
|
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
|
Date: Thu, 21 Nov 2013 03:14:22 +0100
|
|
Subject: [PATCH] net: rework recvmsg handler msg_name and msg_namelen logic
|
|
|
|
[ Upstream commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c ]
|
|
|
|
This patch now always passes msg->msg_namelen as 0. recvmsg handlers must
|
|
set msg_namelen to the proper size <= sizeof(struct sockaddr_storage)
|
|
to return msg_name to the user.
|
|
|
|
This prevents numerous uninitialized memory leaks we had in the
|
|
recvmsg handlers and makes it harder for new code to accidentally leak
|
|
uninitialized memory.
|
|
|
|
Optimize for the case recvfrom is called with NULL as address. We don't
|
|
need to copy the address at all, so set it to NULL before invoking the
|
|
recvmsg handler. We can do so, because all the recvmsg handlers must
|
|
cope with the case a plain read() is called on them. read() also sets
|
|
msg_name to NULL.
|
|
|
|
Also document these changes in include/linux/net.h as suggested by David
|
|
Miller.
|
|
|
|
Changes since RFC:
|
|
|
|
Set msg->msg_name = NULL if user specified a NULL in msg_name but had a
|
|
non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't
|
|
affect sendto as it would bail out earlier while trying to copy-in the
|
|
address. It also more naturally reflects the logic by the callers of
|
|
verify_iovec.
|
|
|
|
With this change in place I could remove "
|
|
if (!uaddr || msg_sys->msg_namelen == 0)
|
|
msg->msg_name = NULL
|
|
".
|
|
|
|
This change does not alter the user visible error logic as we ignore
|
|
msg_namelen as long as msg_name is NULL.
|
|
|
|
Also remove two unnecessary curly brackets in ___sys_recvmsg and change
|
|
comments to netdev style.
|
|
|
|
Cc: David Miller <davem@davemloft.net>
|
|
Suggested-by: Eric Dumazet <eric.dumazet@gmail.com>
|
|
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
---
|
|
crypto/algif_hash.c | 2 --
|
|
crypto/algif_skcipher.c | 1 -
|
|
drivers/isdn/mISDN/socket.c | 13 ++++---------
|
|
drivers/net/ppp/pppoe.c | 2 --
|
|
include/linux/net.h | 8 ++++++++
|
|
net/appletalk/ddp.c | 16 +++++++---------
|
|
net/atm/common.c | 2 --
|
|
net/ax25/af_ax25.c | 4 ++--
|
|
net/bluetooth/af_bluetooth.c | 4 ----
|
|
net/bluetooth/hci_sock.c | 2 --
|
|
net/bluetooth/rfcomm/sock.c | 1 -
|
|
net/bluetooth/sco.c | 1 -
|
|
net/caif/caif_socket.c | 4 ----
|
|
net/compat.c | 3 ++-
|
|
net/core/iovec.c | 3 ++-
|
|
net/ipx/af_ipx.c | 3 +--
|
|
net/irda/af_irda.c | 4 ----
|
|
net/iucv/af_iucv.c | 2 --
|
|
net/key/af_key.c | 1 -
|
|
net/l2tp/l2tp_ppp.c | 2 --
|
|
net/llc/af_llc.c | 2 --
|
|
net/netlink/af_netlink.c | 2 --
|
|
net/netrom/af_netrom.c | 3 +--
|
|
net/nfc/llcp_sock.c | 2 --
|
|
net/nfc/rawsock.c | 2 --
|
|
net/packet/af_packet.c | 32 +++++++++++++++-----------------
|
|
net/rds/recv.c | 2 --
|
|
net/rose/af_rose.c | 8 +++++---
|
|
net/rxrpc/ar-recvmsg.c | 9 ++++++---
|
|
net/socket.c | 19 +++++++++++--------
|
|
net/tipc/socket.c | 6 ------
|
|
net/unix/af_unix.c | 5 -----
|
|
net/vmw_vsock/af_vsock.c | 2 --
|
|
net/vmw_vsock/vmci_transport.c | 2 --
|
|
net/x25/af_x25.c | 3 +--
|
|
35 files changed, 65 insertions(+), 112 deletions(-)
|
|
|
|
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
|
|
index 0262210..ef5356c 100644
|
|
--- a/crypto/algif_hash.c
|
|
+++ b/crypto/algif_hash.c
|
|
@@ -161,8 +161,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
|
|
else if (len < ds)
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
if (ctx->more) {
|
|
ctx->more = 0;
|
|
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
|
|
index a1c4f0a..6a6dfc0 100644
|
|
--- a/crypto/algif_skcipher.c
|
|
+++ b/crypto/algif_skcipher.c
|
|
@@ -432,7 +432,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
|
|
long copied = 0;
|
|
|
|
lock_sock(sk);
|
|
- msg->msg_namelen = 0;
|
|
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
|
|
iovlen--, iov++) {
|
|
unsigned long seglen = iov->iov_len;
|
|
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
|
|
index e47dcb9..5cefb47 100644
|
|
--- a/drivers/isdn/mISDN/socket.c
|
|
+++ b/drivers/isdn/mISDN/socket.c
|
|
@@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
{
|
|
struct sk_buff *skb;
|
|
struct sock *sk = sock->sk;
|
|
- struct sockaddr_mISDN *maddr;
|
|
|
|
int copied, err;
|
|
|
|
@@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return err;
|
|
|
|
- if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) {
|
|
- msg->msg_namelen = sizeof(struct sockaddr_mISDN);
|
|
- maddr = (struct sockaddr_mISDN *)msg->msg_name;
|
|
+ if (msg->msg_name) {
|
|
+ struct sockaddr_mISDN *maddr = msg->msg_name;
|
|
+
|
|
maddr->family = AF_ISDN;
|
|
maddr->dev = _pms(sk)->dev->id;
|
|
if ((sk->sk_protocol == ISDN_P_LAPD_TE) ||
|
|
@@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
maddr->sapi = _pms(sk)->ch.addr & 0xFF;
|
|
maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF;
|
|
}
|
|
- } else {
|
|
- if (msg->msg_namelen)
|
|
- printk(KERN_WARNING "%s: too small namelen %d\n",
|
|
- __func__, msg->msg_namelen);
|
|
- msg->msg_namelen = 0;
|
|
+ msg->msg_namelen = sizeof(*maddr);
|
|
}
|
|
|
|
copied = skb->len + MISDN_HEADER_LEN;
|
|
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
|
|
index 5f66e30..82ee6ed 100644
|
|
--- a/drivers/net/ppp/pppoe.c
|
|
+++ b/drivers/net/ppp/pppoe.c
|
|
@@ -979,8 +979,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (error < 0)
|
|
goto end;
|
|
|
|
- m->msg_namelen = 0;
|
|
-
|
|
if (skb) {
|
|
total_len = min_t(size_t, total_len, skb->len);
|
|
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
|
|
diff --git a/include/linux/net.h b/include/linux/net.h
|
|
index 4f27575..8bd9d92 100644
|
|
--- a/include/linux/net.h
|
|
+++ b/include/linux/net.h
|
|
@@ -163,6 +163,14 @@ struct proto_ops {
|
|
#endif
|
|
int (*sendmsg) (struct kiocb *iocb, struct socket *sock,
|
|
struct msghdr *m, size_t total_len);
|
|
+ /* Notes for implementing recvmsg:
|
|
+ * ===============================
|
|
+ * msg->msg_namelen should get updated by the recvmsg handlers
|
|
+ * iff msg_name != NULL. It is by default 0 to prevent
|
|
+ * returning uninitialized memory to user space. The recvfrom
|
|
+ * handlers can assume that msg.msg_name is either NULL or has
|
|
+ * a minimum size of sizeof(struct sockaddr_storage).
|
|
+ */
|
|
int (*recvmsg) (struct kiocb *iocb, struct socket *sock,
|
|
struct msghdr *m, size_t total_len,
|
|
int flags);
|
|
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
|
|
index 7fee50d..7d424ac 100644
|
|
--- a/net/appletalk/ddp.c
|
|
+++ b/net/appletalk/ddp.c
|
|
@@ -1735,7 +1735,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
|
|
size_t size, int flags)
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
- struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
|
|
struct ddpehdr *ddp;
|
|
int copied = 0;
|
|
int offset = 0;
|
|
@@ -1764,14 +1763,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
|
|
}
|
|
err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
|
|
|
|
- if (!err) {
|
|
- if (sat) {
|
|
- sat->sat_family = AF_APPLETALK;
|
|
- sat->sat_port = ddp->deh_sport;
|
|
- sat->sat_addr.s_node = ddp->deh_snode;
|
|
- sat->sat_addr.s_net = ddp->deh_snet;
|
|
- }
|
|
- msg->msg_namelen = sizeof(*sat);
|
|
+ if (!err && msg->msg_name) {
|
|
+ struct sockaddr_at *sat = msg->msg_name;
|
|
+ sat->sat_family = AF_APPLETALK;
|
|
+ sat->sat_port = ddp->deh_sport;
|
|
+ sat->sat_addr.s_node = ddp->deh_snode;
|
|
+ sat->sat_addr.s_net = ddp->deh_snet;
|
|
+ msg->msg_namelen = sizeof(*sat);
|
|
}
|
|
|
|
skb_free_datagram(sk, skb); /* Free the datagram. */
|
|
diff --git a/net/atm/common.c b/net/atm/common.c
|
|
index 737bef5..7b49100 100644
|
|
--- a/net/atm/common.c
|
|
+++ b/net/atm/common.c
|
|
@@ -531,8 +531,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
|
struct sk_buff *skb;
|
|
int copied, error = -EINVAL;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if (sock->state != SS_CONNECTED)
|
|
return -ENOTCONN;
|
|
|
|
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
|
|
index 4b4d2b7..78c474f 100644
|
|
--- a/net/ax25/af_ax25.c
|
|
+++ b/net/ax25/af_ax25.c
|
|
@@ -1636,11 +1636,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
|
|
|
|
- if (msg->msg_namelen != 0) {
|
|
- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
|
|
+ if (msg->msg_name) {
|
|
ax25_digi digi;
|
|
ax25_address src;
|
|
const unsigned char *mac = skb_mac_header(skb);
|
|
+ struct sockaddr_ax25 *sax = msg->msg_name;
|
|
|
|
memset(sax, 0, sizeof(struct full_sockaddr_ax25));
|
|
ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
|
|
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
|
|
index 9096137..6629cdc 100644
|
|
--- a/net/bluetooth/af_bluetooth.c
|
|
+++ b/net/bluetooth/af_bluetooth.c
|
|
@@ -221,8 +221,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags & (MSG_OOB))
|
|
return -EOPNOTSUPP;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, noblock, &err);
|
|
if (!skb) {
|
|
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
@@ -287,8 +285,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags & MSG_OOB)
|
|
return -EOPNOTSUPP;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
BT_DBG("sk %p size %zu", sk, size);
|
|
|
|
lock_sock(sk);
|
|
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
|
|
index 9bd7d95..fa4bf66 100644
|
|
--- a/net/bluetooth/hci_sock.c
|
|
+++ b/net/bluetooth/hci_sock.c
|
|
@@ -752,8 +752,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return err;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
|
|
index 30b3721..c1c6028 100644
|
|
--- a/net/bluetooth/rfcomm/sock.c
|
|
+++ b/net/bluetooth/rfcomm/sock.c
|
|
@@ -608,7 +608,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
|
|
rfcomm_dlc_accept(d);
|
|
- msg->msg_namelen = 0;
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
|
|
index e7bd4ee..2bb1d3a 100644
|
|
--- a/net/bluetooth/sco.c
|
|
+++ b/net/bluetooth/sco.c
|
|
@@ -700,7 +700,6 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
|
|
sco_conn_defer_accept(pi->conn->hcon, 0);
|
|
sk->sk_state = BT_CONFIG;
|
|
- msg->msg_namelen = 0;
|
|
|
|
release_sock(sk);
|
|
return 0;
|
|
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
|
|
index 05a41c7..d6be3ed 100644
|
|
--- a/net/caif/caif_socket.c
|
|
+++ b/net/caif/caif_socket.c
|
|
@@ -286,8 +286,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (m->msg_flags&MSG_OOB)
|
|
goto read_error;
|
|
|
|
- m->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags, 0 , &ret);
|
|
if (!skb)
|
|
goto read_error;
|
|
@@ -361,8 +359,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags&MSG_OOB)
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
/*
|
|
* Lock the socket to prevent queue disordering
|
|
* while sleeps in memcpy_tomsg
|
|
diff --git a/net/compat.c b/net/compat.c
|
|
index 8903258..618c6a8 100644
|
|
--- a/net/compat.c
|
|
+++ b/net/compat.c
|
|
@@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
- kern_msg->msg_name = kern_address;
|
|
+ if (kern_msg->msg_name)
|
|
+ kern_msg->msg_name = kern_address;
|
|
} else
|
|
kern_msg->msg_name = NULL;
|
|
|
|
diff --git a/net/core/iovec.c b/net/core/iovec.c
|
|
index de178e4..9a31515 100644
|
|
--- a/net/core/iovec.c
|
|
+++ b/net/core/iovec.c
|
|
@@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
- m->msg_name = address;
|
|
+ if (m->msg_name)
|
|
+ m->msg_name = address;
|
|
} else {
|
|
m->msg_name = NULL;
|
|
}
|
|
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
|
|
index 7a1e0fc..e096025 100644
|
|
--- a/net/ipx/af_ipx.c
|
|
+++ b/net/ipx/af_ipx.c
|
|
@@ -1823,8 +1823,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (skb->tstamp.tv64)
|
|
sk->sk_stamp = skb->tstamp;
|
|
|
|
- msg->msg_namelen = sizeof(*sipx);
|
|
-
|
|
if (sipx) {
|
|
sipx->sipx_family = AF_IPX;
|
|
sipx->sipx_port = ipx->ipx_source.sock;
|
|
@@ -1832,6 +1830,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net;
|
|
sipx->sipx_type = ipx->ipx_type;
|
|
sipx->sipx_zero = 0;
|
|
+ msg->msg_namelen = sizeof(*sipx);
|
|
}
|
|
rc = copied;
|
|
|
|
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
|
|
index 0578d4f..a5e62ef5 100644
|
|
--- a/net/irda/af_irda.c
|
|
+++ b/net/irda/af_irda.c
|
|
@@ -1385,8 +1385,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
|
|
|
|
IRDA_DEBUG(4, "%s()\n", __func__);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
|
flags & MSG_DONTWAIT, &err);
|
|
if (!skb)
|
|
@@ -1451,8 +1449,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
|
|
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
|
|
timeo = sock_rcvtimeo(sk, noblock);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
do {
|
|
int chunk;
|
|
struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
|
|
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
|
|
index 168aff5..c4b7218 100644
|
|
--- a/net/iucv/af_iucv.c
|
|
+++ b/net/iucv/af_iucv.c
|
|
@@ -1324,8 +1324,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
int err = 0;
|
|
u32 offset;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if ((sk->sk_state == IUCV_DISCONN) &&
|
|
skb_queue_empty(&iucv->backlog_skb_q) &&
|
|
skb_queue_empty(&sk->sk_receive_queue) &&
|
|
diff --git a/net/key/af_key.c b/net/key/af_key.c
|
|
index ab8bd2c..66f51c5 100644
|
|
--- a/net/key/af_key.c
|
|
+++ b/net/key/af_key.c
|
|
@@ -3623,7 +3623,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
|
|
if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err);
|
|
if (skb == NULL)
|
|
goto out;
|
|
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
|
|
index 8c46b27..44441c0 100644
|
|
--- a/net/l2tp/l2tp_ppp.c
|
|
+++ b/net/l2tp/l2tp_ppp.c
|
|
@@ -197,8 +197,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (sk->sk_state & PPPOX_BOUND)
|
|
goto end;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
err = 0;
|
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
|
flags & MSG_DONTWAIT, &err);
|
|
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
|
|
index 48aaa89..8870988 100644
|
|
--- a/net/llc/af_llc.c
|
|
+++ b/net/llc/af_llc.c
|
|
@@ -720,8 +720,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
int target; /* Read at least this many bytes */
|
|
long timeo;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
copied = -ENOTCONN;
|
|
if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
|
|
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
|
|
index 0c61b59..90b654b 100644
|
|
--- a/net/netlink/af_netlink.c
|
|
+++ b/net/netlink/af_netlink.c
|
|
@@ -2317,8 +2317,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
|
|
}
|
|
#endif
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = data_skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
|
|
index 698814b..53c19a3 100644
|
|
--- a/net/netrom/af_netrom.c
|
|
+++ b/net/netrom/af_netrom.c
|
|
@@ -1179,10 +1179,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
sax->sax25_family = AF_NETROM;
|
|
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
|
|
AX25_ADDR_LEN);
|
|
+ msg->msg_namelen = sizeof(*sax);
|
|
}
|
|
|
|
- msg->msg_namelen = sizeof(*sax);
|
|
-
|
|
skb_free_datagram(sk, skb);
|
|
|
|
release_sock(sk);
|
|
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
|
|
index d308402..824c605 100644
|
|
--- a/net/nfc/llcp_sock.c
|
|
+++ b/net/nfc/llcp_sock.c
|
|
@@ -807,8 +807,6 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
pr_debug("%p %zu\n", sk, len);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state == LLCP_CLOSED &&
|
|
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
|
|
index 313bf1b..5d11f4a 100644
|
|
--- a/net/nfc/rawsock.c
|
|
+++ b/net/nfc/rawsock.c
|
|
@@ -241,8 +241,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (!skb)
|
|
return rc;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
copied = skb->len;
|
|
if (len < copied) {
|
|
msg->msg_flags |= MSG_TRUNC;
|
|
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
|
|
index 75c8bbf..739c50d 100644
|
|
--- a/net/packet/af_packet.c
|
|
+++ b/net/packet/af_packet.c
|
|
@@ -2694,7 +2694,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
struct sock *sk = sock->sk;
|
|
struct sk_buff *skb;
|
|
int copied, err;
|
|
- struct sockaddr_ll *sll;
|
|
int vnet_hdr_len = 0;
|
|
|
|
err = -EINVAL;
|
|
@@ -2777,22 +2776,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
goto out_free;
|
|
}
|
|
|
|
- /*
|
|
- * If the address length field is there to be filled in, we fill
|
|
- * it in now.
|
|
- */
|
|
-
|
|
- sll = &PACKET_SKB_CB(skb)->sa.ll;
|
|
- if (sock->type == SOCK_PACKET)
|
|
- msg->msg_namelen = sizeof(struct sockaddr_pkt);
|
|
- else
|
|
- msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
|
|
-
|
|
- /*
|
|
- * You lose any data beyond the buffer you gave. If it worries a
|
|
- * user program they can ask the device for its MTU anyway.
|
|
+ /* You lose any data beyond the buffer you gave. If it worries
|
|
+ * a user program they can ask the device for its MTU
|
|
+ * anyway.
|
|
*/
|
|
-
|
|
copied = skb->len;
|
|
if (copied > len) {
|
|
copied = len;
|
|
@@ -2805,9 +2792,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
sock_recv_ts_and_drops(msg, sk, skb);
|
|
|
|
- if (msg->msg_name)
|
|
+ if (msg->msg_name) {
|
|
+ /* If the address length field is there to be filled
|
|
+ * in, we fill it in now.
|
|
+ */
|
|
+ if (sock->type == SOCK_PACKET) {
|
|
+ msg->msg_namelen = sizeof(struct sockaddr_pkt);
|
|
+ } else {
|
|
+ struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
|
|
+ msg->msg_namelen = sll->sll_halen +
|
|
+ offsetof(struct sockaddr_ll, sll_addr);
|
|
+ }
|
|
memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
|
|
msg->msg_namelen);
|
|
+ }
|
|
|
|
if (pkt_sk(sk)->auxdata) {
|
|
struct tpacket_auxdata aux;
|
|
diff --git a/net/rds/recv.c b/net/rds/recv.c
|
|
index 9f0f17c..de339b2 100644
|
|
--- a/net/rds/recv.c
|
|
+++ b/net/rds/recv.c
|
|
@@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
|
|
|
rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
if (msg_flags & MSG_OOB)
|
|
goto out;
|
|
|
|
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
|
|
index e98fcfb..33af772 100644
|
|
--- a/net/rose/af_rose.c
|
|
+++ b/net/rose/af_rose.c
|
|
@@ -1216,7 +1216,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
struct rose_sock *rose = rose_sk(sk);
|
|
- struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name;
|
|
size_t copied;
|
|
unsigned char *asmptr;
|
|
struct sk_buff *skb;
|
|
@@ -1252,8 +1251,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
|
|
|
|
- if (srose != NULL) {
|
|
- memset(srose, 0, msg->msg_namelen);
|
|
+ if (msg->msg_name) {
|
|
+ struct sockaddr_rose *srose;
|
|
+
|
|
+ memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose));
|
|
+ srose = msg->msg_name;
|
|
srose->srose_family = AF_ROSE;
|
|
srose->srose_addr = rose->dest_addr;
|
|
srose->srose_call = rose->dest_call;
|
|
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
|
|
index 4b48687..898492a 100644
|
|
--- a/net/rxrpc/ar-recvmsg.c
|
|
+++ b/net/rxrpc/ar-recvmsg.c
|
|
@@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
|
|
/* copy the peer address and timestamp */
|
|
if (!continue_call) {
|
|
- if (msg->msg_name && msg->msg_namelen > 0)
|
|
+ if (msg->msg_name) {
|
|
+ size_t len =
|
|
+ sizeof(call->conn->trans->peer->srx);
|
|
memcpy(msg->msg_name,
|
|
- &call->conn->trans->peer->srx,
|
|
- sizeof(call->conn->trans->peer->srx));
|
|
+ &call->conn->trans->peer->srx, len);
|
|
+ msg->msg_namelen = len;
|
|
+ }
|
|
sock_recv_ts_and_drops(msg, &rx->sk, skb);
|
|
}
|
|
|
|
diff --git a/net/socket.c b/net/socket.c
|
|
index 4b94643..5158ff7 100644
|
|
--- a/net/socket.c
|
|
+++ b/net/socket.c
|
|
@@ -1849,8 +1849,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
|
|
msg.msg_iov = &iov;
|
|
iov.iov_len = size;
|
|
iov.iov_base = ubuf;
|
|
- msg.msg_name = (struct sockaddr *)&address;
|
|
- msg.msg_namelen = sizeof(address);
|
|
+ /* Save some cycles and don't copy the address if not needed */
|
|
+ msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
|
|
+ /* We assume all kernel code knows the size of sockaddr_storage */
|
|
+ msg.msg_namelen = 0;
|
|
if (sock->file->f_flags & O_NONBLOCK)
|
|
flags |= MSG_DONTWAIT;
|
|
err = sock_recvmsg(sock, &msg, size, flags);
|
|
@@ -2230,16 +2232,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
|
|
goto out;
|
|
}
|
|
|
|
- /*
|
|
- * Save the user-mode address (verify_iovec will change the
|
|
- * kernel msghdr to use the kernel address space)
|
|
+ /* Save the user-mode address (verify_iovec will change the
|
|
+ * kernel msghdr to use the kernel address space)
|
|
*/
|
|
-
|
|
uaddr = (__force void __user *)msg_sys->msg_name;
|
|
uaddr_len = COMPAT_NAMELEN(msg);
|
|
- if (MSG_CMSG_COMPAT & flags) {
|
|
+ if (MSG_CMSG_COMPAT & flags)
|
|
err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
|
|
- } else
|
|
+ else
|
|
err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE);
|
|
if (err < 0)
|
|
goto out_freeiov;
|
|
@@ -2248,6 +2248,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
|
|
cmsg_ptr = (unsigned long)msg_sys->msg_control;
|
|
msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
|
|
|
|
+ /* We assume all kernel code knows the size of sockaddr_storage */
|
|
+ msg_sys->msg_namelen = 0;
|
|
+
|
|
if (sock->file->f_flags & O_NONBLOCK)
|
|
flags |= MSG_DONTWAIT;
|
|
err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys,
|
|
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
|
|
index 6cc7ddd..dffdbea 100644
|
|
--- a/net/tipc/socket.c
|
|
+++ b/net/tipc/socket.c
|
|
@@ -984,9 +984,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
|
|
goto exit;
|
|
}
|
|
|
|
- /* will be updated in set_orig_addr() if needed */
|
|
- m->msg_namelen = 0;
|
|
-
|
|
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
restart:
|
|
|
|
@@ -1095,9 +1092,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
|
|
goto exit;
|
|
}
|
|
|
|
- /* will be updated in set_orig_addr() if needed */
|
|
- m->msg_namelen = 0;
|
|
-
|
|
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
|
|
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
|
|
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index e64bbcf..6c66e8d 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -1762,7 +1762,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
|
|
{
|
|
struct unix_sock *u = unix_sk(sk);
|
|
|
|
- msg->msg_namelen = 0;
|
|
if (u->addr) {
|
|
msg->msg_namelen = u->addr->len;
|
|
memcpy(msg->msg_name, u->addr->name, u->addr->len);
|
|
@@ -1786,8 +1785,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (flags&MSG_OOB)
|
|
goto out;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
err = mutex_lock_interruptible(&u->readlock);
|
|
if (err) {
|
|
err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
|
|
@@ -1927,8 +1924,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
|
|
timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
/* Lock the socket to prevent queue disordering
|
|
* while sleeps in memcpy_tomsg
|
|
*/
|
|
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
|
|
index 4d93346..16f721c 100644
|
|
--- a/net/vmw_vsock/af_vsock.c
|
|
+++ b/net/vmw_vsock/af_vsock.c
|
|
@@ -1663,8 +1663,6 @@ vsock_stream_recvmsg(struct kiocb *kiocb,
|
|
vsk = vsock_sk(sk);
|
|
err = 0;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
lock_sock(sk);
|
|
|
|
if (sk->sk_state != SS_CONNECTED) {
|
|
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
|
|
index ffc11df..73ca104 100644
|
|
--- a/net/vmw_vsock/vmci_transport.c
|
|
+++ b/net/vmw_vsock/vmci_transport.c
|
|
@@ -1746,8 +1746,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
|
|
if (flags & MSG_OOB || flags & MSG_ERRQUEUE)
|
|
return -EOPNOTSUPP;
|
|
|
|
- msg->msg_namelen = 0;
|
|
-
|
|
/* Retrieve the head sk_buff from the socket's receive queue. */
|
|
err = 0;
|
|
skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err);
|
|
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
|
|
index 45a3ab5..7622789 100644
|
|
--- a/net/x25/af_x25.c
|
|
+++ b/net/x25/af_x25.c
|
|
@@ -1340,10 +1340,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|
if (sx25) {
|
|
sx25->sx25_family = AF_X25;
|
|
sx25->sx25_addr = x25->dest_addr;
|
|
+ msg->msg_namelen = sizeof(*sx25);
|
|
}
|
|
|
|
- msg->msg_namelen = sizeof(struct sockaddr_x25);
|
|
-
|
|
x25_check_rbuf(sk);
|
|
rc = copied;
|
|
out_free_dgram:
|
|
--
|
|
1.8.3.1
|
|
|