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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f89e8a6432
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -230,6 +230,8 @@ 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)
|
||||
|
@ -237,8 +239,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||
return err;
|
||||
}
|
||||
|
||||
msg->msg_namelen = 0;
|
||||
|
||||
copied = skb->len;
|
||||
if (len < copied) {
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 &&
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue