Commit f89e8a64 authored by David S. Miller's avatar David S. Miller

Merge branch 'infoleaks'

Mathias Krause says:

====================
a few more info leak fixes in the recvmsg path. The error pattern here
is the protocol specific recvmsg function is missing the msg_namelen
assignment -- either completely or in early exit paths that do not
result in errors in __sys_recvmsg()/sys_recvfrom() and, in turn, make
them call move_addr_to_user(), leaking the then still uninitialized
sockaddr_storage stack variable to userland.

My audit was initiated by a rather coarse fix of the leak that can be
found in the grsecurity patch, putting a penalty on protocols complying
to the rules of recvmsg. So credits for finding the leak in the recvmsg
path in __sys_recvmsg() should go to Brad!

The buggy protocols/subsystems are rather obscure anyway. As a missing
assignment of msg_namelen coupled with a missing filling of msg_name
would only result in garbage -- the leak -- in case userland would care
about that information, i.e. would provide a msg_name pointer. But
obviously current userland does not.

While auditing the code for the above pattern I found a few more
'uninitialized members' kind of leaks related to the msg_name filling.
Those are fixed in this series, too.

I have to admit, I failed to test all of the patches due to missing
hardware, e.g. iucv depends on S390 -- hardware I've no access to :/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 50a75a89 d5e0d0f6
...@@ -531,6 +531,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, ...@@ -531,6 +531,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
struct sk_buff *skb; struct sk_buff *skb;
int copied, error = -EINVAL; int copied, error = -EINVAL;
msg->msg_namelen = 0;
if (sock->state != SS_CONNECTED) if (sock->state != SS_CONNECTED)
return -ENOTCONN; return -ENOTCONN;
......
...@@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
ax25_address src; ax25_address src;
const unsigned char *mac = skb_mac_header(skb); const unsigned char *mac = skb_mac_header(skb);
memset(sax, 0, sizeof(struct full_sockaddr_ax25));
ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
&digi, NULL, NULL); &digi, NULL, NULL);
sax->sax25_family = AF_AX25; sax->sax25_family = AF_AX25;
......
...@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -230,6 +230,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (flags & (MSG_OOB)) if (flags & (MSG_OOB))
return -EOPNOTSUPP; return -EOPNOTSUPP;
msg->msg_namelen = 0;
skb = skb_recv_datagram(sk, flags, noblock, &err); skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) { if (!skb) {
if (sk->sk_shutdown & RCV_SHUTDOWN) if (sk->sk_shutdown & RCV_SHUTDOWN)
...@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return err; return err;
} }
msg->msg_namelen = 0;
copied = skb->len; copied = skb->len;
if (len < copied) { if (len < copied) {
msg->msg_flags |= MSG_TRUNC; msg->msg_flags |= MSG_TRUNC;
......
...@@ -608,6 +608,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -608,6 +608,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
rfcomm_dlc_accept(d); rfcomm_dlc_accept(d);
msg->msg_namelen = 0;
return 0; return 0;
} }
......
...@@ -665,6 +665,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -665,6 +665,7 @@ static int sco_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
hci_conn_accept(pi->conn->hcon, 0); hci_conn_accept(pi->conn->hcon, 0);
sk->sk_state = BT_CONFIG; sk->sk_state = BT_CONFIG;
msg->msg_namelen = 0;
release_sock(sk); release_sock(sk);
return 0; return 0;
......
...@@ -286,6 +286,8 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -286,6 +286,8 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
if (m->msg_flags&MSG_OOB) if (m->msg_flags&MSG_OOB)
goto read_error; goto read_error;
m->msg_namelen = 0;
skb = skb_recv_datagram(sk, flags, 0 , &ret); skb = skb_recv_datagram(sk, flags, 0 , &ret);
if (!skb) if (!skb)
goto read_error; goto read_error;
......
...@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, ...@@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(4, "%s()\n", __func__); IRDA_DEBUG(4, "%s()\n", __func__);
msg->msg_namelen = 0;
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err); flags & MSG_DONTWAIT, &err);
if (!skb) if (!skb)
......
...@@ -1328,6 +1328,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1328,6 +1328,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb, *rskb, *cskb; struct sk_buff *skb, *rskb, *cskb;
int err = 0; int err = 0;
msg->msg_namelen = 0;
if ((sk->sk_state == IUCV_DISCONN) && if ((sk->sk_state == IUCV_DISCONN) &&
skb_queue_empty(&iucv->backlog_skb_q) && skb_queue_empty(&iucv->backlog_skb_q) &&
skb_queue_empty(&sk->sk_receive_queue) && skb_queue_empty(&sk->sk_receive_queue) &&
......
...@@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
lsa->l2tp_addr = ipv6_hdr(skb)->saddr; lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
lsa->l2tp_flowinfo = 0; lsa->l2tp_flowinfo = 0;
lsa->l2tp_scope_id = 0; lsa->l2tp_scope_id = 0;
lsa->l2tp_conn_id = 0;
if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
lsa->l2tp_scope_id = IP6CB(skb)->iif; lsa->l2tp_scope_id = IP6CB(skb)->iif;
} }
......
...@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -720,6 +720,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
int target; /* Read at least this many bytes */ int target; /* Read at least this many bytes */
long timeo; long timeo;
msg->msg_namelen = 0;
lock_sock(sk); lock_sock(sk);
copied = -ENOTCONN; copied = -ENOTCONN;
if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
......
...@@ -1173,6 +1173,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1173,6 +1173,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
} }
if (sax != NULL) { if (sax != NULL) {
memset(sax, 0, sizeof(sax));
sax->sax25_family = AF_NETROM; sax->sax25_family = AF_NETROM;
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
AX25_ADDR_LEN); AX25_ADDR_LEN);
......
...@@ -646,6 +646,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -646,6 +646,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
pr_debug("%p %zu\n", sk, len); pr_debug("%p %zu\n", sk, len);
msg->msg_namelen = 0;
lock_sock(sk); lock_sock(sk);
if (sk->sk_state == LLCP_CLOSED && if (sk->sk_state == LLCP_CLOSED &&
...@@ -691,6 +693,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -691,6 +693,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
memset(sockaddr, 0, sizeof(*sockaddr));
sockaddr->sa_family = AF_NFC; sockaddr->sa_family = AF_NFC;
sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP; sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP;
sockaddr->dsap = ui_cb->dsap; sockaddr->dsap = ui_cb->dsap;
......
...@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1253,6 +1253,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (srose != NULL) { if (srose != NULL) {
memset(srose, 0, msg->msg_namelen);
srose->srose_family = AF_ROSE; srose->srose_family = AF_ROSE;
srose->srose_addr = rose->dest_addr; srose->srose_addr = rose->dest_addr;
srose->srose_call = rose->dest_call; srose->srose_call = rose->dest_call;
......
...@@ -790,6 +790,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) ...@@ -790,6 +790,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
if (addr) { if (addr) {
addr->family = AF_TIPC; addr->family = AF_TIPC;
addr->addrtype = TIPC_ADDR_ID; addr->addrtype = TIPC_ADDR_ID;
memset(&addr->addr, 0, sizeof(addr->addr));
addr->addr.id.ref = msg_origport(msg); addr->addr.id.ref = msg_origport(msg);
addr->addr.id.node = msg_orignode(msg); addr->addr.id.node = msg_orignode(msg);
addr->addr.name.domain = 0; /* could leave uninitialized */ addr->addr.name.domain = 0; /* could leave uninitialized */
...@@ -904,6 +905,9 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, ...@@ -904,6 +905,9 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
goto exit; goto exit;
} }
/* will be updated in set_orig_addr() if needed */
m->msg_namelen = 0;
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart: restart:
...@@ -1013,6 +1017,9 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1013,6 +1017,9 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
goto exit; goto exit;
} }
/* will be updated in set_orig_addr() if needed */
m->msg_namelen = 0;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
......
...@@ -1670,6 +1670,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb, ...@@ -1670,6 +1670,8 @@ vsock_stream_recvmsg(struct kiocb *kiocb,
vsk = vsock_sk(sk); vsk = vsock_sk(sk);
err = 0; err = 0;
msg->msg_namelen = 0;
lock_sock(sk); lock_sock(sk);
if (sk->sk_state != SS_CONNECTED) { if (sk->sk_state != SS_CONNECTED) {
......
...@@ -1736,6 +1736,8 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb, ...@@ -1736,6 +1736,8 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
if (flags & MSG_OOB || flags & MSG_ERRQUEUE) if (flags & MSG_OOB || flags & MSG_ERRQUEUE)
return -EOPNOTSUPP; return -EOPNOTSUPP;
msg->msg_namelen = 0;
/* Retrieve the head sk_buff from the socket's receive queue. */ /* Retrieve the head sk_buff from the socket's receive queue. */
err = 0; err = 0;
skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err); skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err);
...@@ -1768,7 +1770,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb, ...@@ -1768,7 +1770,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
if (err) if (err)
goto out; goto out;
msg->msg_namelen = 0;
if (msg->msg_name) { if (msg->msg_name) {
struct sockaddr_vm *vm_addr; struct sockaddr_vm *vm_addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment