Skip to content

Commit

Permalink
Merge branch 'infoleaks'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 7, 2013
2 parents 50a75a8 + d5e0d0f commit f89e8a6
Show file tree
Hide file tree
Showing 16 changed files with 32 additions and 3 deletions.
2 changes: 2 additions & 0 deletions net/atm/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ 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;

Expand Down
1 change: 1 addition & 0 deletions net/ax25/af_ax25.c
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
ax25_address src;
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,
&digi, NULL, NULL);
sax->sax25_family = AF_AX25;
Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/af_bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,15 @@ 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)
return 0;
return err;
}

msg->msg_namelen = 0;

copied = skb->len;
if (len < copied) {
msg->msg_flags |= MSG_TRUNC;
Expand Down
1 change: 1 addition & 0 deletions net/bluetooth/rfcomm/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
rfcomm_dlc_accept(d);
msg->msg_namelen = 0;
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions net/bluetooth/sco.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
hci_conn_accept(pi->conn->hcon, 0);
sk->sk_state = BT_CONFIG;
msg->msg_namelen = 0;

release_sock(sk);
return 0;
Expand Down
2 changes: 2 additions & 0 deletions net/caif/caif_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ 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;
Expand Down
2 changes: 2 additions & 0 deletions net/irda/af_irda.c
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,8 @@ 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)
Expand Down
2 changes: 2 additions & 0 deletions net/iucv/af_iucv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1328,6 +1328,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb, *rskb, *cskb;
int err = 0;

msg->msg_namelen = 0;

if ((sk->sk_state == IUCV_DISCONN) &&
skb_queue_empty(&iucv->backlog_skb_q) &&
skb_queue_empty(&sk->sk_receive_queue) &&
Expand Down
1 change: 1 addition & 0 deletions net/l2tp/l2tp_ip6.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk,
lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
lsa->l2tp_flowinfo = 0;
lsa->l2tp_scope_id = 0;
lsa->l2tp_conn_id = 0;
if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
lsa->l2tp_scope_id = IP6CB(skb)->iif;
}
Expand Down
2 changes: 2 additions & 0 deletions net/llc/af_llc.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,8 @@ 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))
Expand Down
1 change: 1 addition & 0 deletions net/netrom/af_netrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
}

if (sax != NULL) {
memset(sax, 0, sizeof(sax));
sax->sax25_family = AF_NETROM;
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
AX25_ADDR_LEN);
Expand Down
3 changes: 3 additions & 0 deletions net/nfc/llcp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,8 @@ 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 &&
Expand Down Expand Up @@ -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);

memset(sockaddr, 0, sizeof(*sockaddr));
sockaddr->sa_family = AF_NFC;
sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP;
sockaddr->dsap = ui_cb->dsap;
Expand Down
1 change: 1 addition & 0 deletions net/rose/af_rose.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,7 @@ 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);
srose->srose_family = AF_ROSE;
srose->srose_addr = rose->dest_addr;
srose->srose_call = rose->dest_call;
Expand Down
7 changes: 7 additions & 0 deletions net/tipc/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
if (addr) {
addr->family = AF_TIPC;
addr->addrtype = TIPC_ADDR_ID;
memset(&addr->addr, 0, sizeof(addr->addr));
addr->addr.id.ref = msg_origport(msg);
addr->addr.id.node = msg_orignode(msg);
addr->addr.name.domain = 0; /* could leave uninitialized */
Expand Down Expand Up @@ -904,6 +905,9 @@ 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:

Expand Down Expand Up @@ -1013,6 +1017,9 @@ 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);

Expand Down
2 changes: 2 additions & 0 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,8 @@ 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) {
Expand Down
3 changes: 2 additions & 1 deletion net/vmw_vsock/vmci_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -1736,6 +1736,8 @@ 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);
Expand Down Expand Up @@ -1768,7 +1770,6 @@ static int vmci_transport_dgram_dequeue(struct kiocb *kiocb,
if (err)
goto out;

msg->msg_namelen = 0;
if (msg->msg_name) {
struct sockaddr_vm *vm_addr;

Expand Down

0 comments on commit f89e8a6

Please sign in to comment.