summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2014-07-08 21:55:39 +0000
committerXin LI <delphij@FreeBSD.org>2014-07-08 21:55:39 +0000
commit2ae887b5c1fa2fa8d99827ee1727785055fc6815 (patch)
tree4b63ea8149e2065fda167faeed4ded39374f1b95
parent5a9e14150cbd3538e0a5eb4934cc5e8c6e56de13 (diff)
downloadsrc-test2-2ae887b5c1fa2fa8d99827ee1727785055fc6815.tar.gz
src-test2-2ae887b5c1fa2fa8d99827ee1727785055fc6815.zip
Fix kernel memory disclosure in control message and SCTP notifications.
[SA-14:17] Fix jail fails to start if WITHOUT_INET/WITHOUT_INET6 is use. [EN-14:09] Security: FreeBSD-SA-14:17.kmem Security: CVE-2014-3952, CVE-2014-3953 Approved by: so
Notes
Notes: svn path=/releng/8.4/; revision=268435
-rw-r--r--UPDATING8
-rwxr-xr-xetc/rc.d/jail4
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/kern/uipc_sockbuf.c5
-rw-r--r--sys/netinet/sctp_auth.c1
-rw-r--r--sys/netinet/sctp_indata.c5
-rw-r--r--sys/netinet/sctputil.c55
7 files changed, 51 insertions, 29 deletions
diff --git a/UPDATING b/UPDATING
index f3357dc1d37a..55e2eb043041 100644
--- a/UPDATING
+++ b/UPDATING
@@ -15,6 +15,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW ON IA64 OR SUN4V:
debugging tools present in HEAD were left in place because
sun4v support still needs work to become production ready.
+20140708: p14 FreeBSD-SA-14:17.kmem
+ FreeBSD-EN-14:09.jail
+ Fix kernel memory disclosure in control messages and SCTP
+ notifications. [SA-14:17]
+
+ Fix jail fails to start if WITHOUT_INET/WITHOUT_INET6 is use.
+ [EN-14:09]
+
20140624: p13 FreeBSD-SA-14:16.file
FreeBSD-EN-14:08.heimdal
diff --git a/etc/rc.d/jail b/etc/rc.d/jail
index 0fc773436a57..abd6d0a0cbc1 100755
--- a/etc/rc.d/jail
+++ b/etc/rc.d/jail
@@ -647,7 +647,9 @@ jail_start()
done
eval ${_setfib} jail -n ${_jail} ${_flags} -i -c path=${_rootdir} host.hostname=${_hostname} \
- ip4.addr=\"${_addrl}\" ip6.addr=\"${_addr6l}\" ${_parameters} command=${_exec_start} > ${_tmp_jail} 2>&1
+ ${_addrl:+ip4.addr=\"${_addrl}\"} ${_addr6l:+ip6.addr=\"${_addr6l}\"} \
+ ${_parameters} command=${_exec_start} > ${_tmp_jail} 2>&1 \
+ </dev/null
if [ "$?" -eq 0 ] ; then
_jail_id=$(head -1 ${_tmp_jail})
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 8250b501650e..20e9e784b836 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="8.4"
-BRANCH="RELEASE-p13"
+BRANCH="RELEASE-p14"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 2d86d740996c..b71f4391eaad 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -1011,6 +1011,11 @@ sbcreatecontrol(caddr_t p, int size, int type, int level)
m->m_len = 0;
KASSERT(CMSG_SPACE((u_int)size) <= M_TRAILINGSPACE(m),
("sbcreatecontrol: short mbuf"));
+ /*
+ * Don't leave the padding between the msg header and the
+ * cmsg data and the padding after the cmsg data un-initialized.
+ */
+ bzero(cp, CMSG_SPACE((u_int)size));
if (p != NULL)
(void)memcpy(CMSG_DATA(cp), p, size);
m->m_len = CMSG_SPACE(size);
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index a5d5f71f3858..5bc659c8aaf9 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -1876,6 +1876,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
SCTP_BUF_LEN(m_notify) = 0;
auth = mtod(m_notify, struct sctp_authkey_event *);
+ memset(auth, 0, sizeof(struct sctp_authkey_event));
auth->auth_type = SCTP_AUTHENTICATION_EVENT;
auth->auth_flags = 0;
auth->auth_length = sizeof(*auth);
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index bd2d3be9ccff..38cd1daa6a39 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -250,6 +250,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
/* We need a CMSG header followed by the struct */
cmh = mtod(ret, struct cmsghdr *);
+ /*
+ * Make sure that there is no un-initialized padding between the
+ * cmsg header and cmsg data and after the cmsg data.
+ */
+ memset(cmh, 0, len);
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
cmh->cmsg_level = IPPROTO_SCTP;
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo));
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index e79cc1afd53d..a478961b8163 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -2622,6 +2622,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
}
SCTP_BUF_NEXT(m_notify) = NULL;
sac = mtod(m_notify, struct sctp_assoc_change *);
+ memset(sac, 0, notif_len);
sac->sac_type = SCTP_ASSOC_CHANGE;
sac->sac_flags = 0;
sac->sac_length = sizeof(struct sctp_assoc_change);
@@ -2829,21 +2830,21 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
if (m_notify == NULL)
/* no space left */
return;
- length += chk->send_size;
- length -= sizeof(struct sctp_data_chunk);
SCTP_BUF_LEN(m_notify) = 0;
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+ memset(ssfe, 0, length);
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
if (sent) {
ssfe->ssfe_flags = SCTP_DATA_SENT;
} else {
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
}
+ length += chk->send_size;
+ length -= sizeof(struct sctp_data_chunk);
ssfe->ssfe_length = length;
ssfe->ssfe_error = error;
/* not exactly what the user sent in, but should be close :) */
- bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
@@ -2853,12 +2854,15 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
} else {
ssf = mtod(m_notify, struct sctp_send_failed *);
+ memset(ssf, 0, length);
ssf->ssf_type = SCTP_SEND_FAILED;
if (sent) {
ssf->ssf_flags = SCTP_DATA_SENT;
} else {
ssf->ssf_flags = SCTP_DATA_UNSENT;
}
+ length += chk->send_size;
+ length -= sizeof(struct sctp_data_chunk);
ssf->ssf_length = length;
ssf->ssf_error = error;
/* not exactly what the user sent in, but should be close :) */
@@ -2942,16 +2946,16 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
/* no space left */
return;
}
- length += sp->length;
SCTP_BUF_LEN(m_notify) = 0;
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
ssfe = mtod(m_notify, struct sctp_send_failed_event *);
+ memset(ssfe, 0, length);
ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
ssfe->ssfe_flags = SCTP_DATA_UNSENT;
+ length += sp->length;
ssfe->ssfe_length = length;
ssfe->ssfe_error = error;
/* not exactly what the user sent in, but should be close :) */
- bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info));
ssfe->ssfe_info.snd_sid = sp->stream;
if (sp->some_taken) {
ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
@@ -2965,12 +2969,13 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
} else {
ssf = mtod(m_notify, struct sctp_send_failed *);
+ memset(ssf, 0, length);
ssf->ssf_type = SCTP_SEND_FAILED;
ssf->ssf_flags = SCTP_DATA_UNSENT;
+ length += sp->length;
ssf->ssf_length = length;
ssf->ssf_error = error;
/* not exactly what the user sent in, but should be close :) */
- bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
ssf->ssf_info.sinfo_stream = sp->stream;
ssf->ssf_info.sinfo_ssn = 0;
if (sp->some_taken) {
@@ -3032,6 +3037,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb)
return;
SCTP_BUF_LEN(m_notify) = 0;
sai = mtod(m_notify, struct sctp_adaptation_event *);
+ memset(sai, 0, sizeof(struct sctp_adaptation_event));
sai->sai_type = SCTP_ADAPTATION_INDICATION;
sai->sai_flags = 0;
sai->sai_length = sizeof(struct sctp_adaptation_event);
@@ -3087,6 +3093,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
return;
SCTP_BUF_LEN(m_notify) = 0;
pdapi = mtod(m_notify, struct sctp_pdapi_event *);
+ memset(pdapi, 0, sizeof(struct sctp_pdapi_event));
pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
pdapi->pdapi_flags = 0;
pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
@@ -3196,6 +3203,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
/* no space left */
return;
sse = mtod(m_notify, struct sctp_shutdown_event *);
+ memset(sse, 0, sizeof(struct sctp_shutdown_event));
sse->sse_type = SCTP_SHUTDOWN_EVENT;
sse->sse_flags = 0;
sse->sse_length = sizeof(struct sctp_shutdown_event);
@@ -3246,6 +3254,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
}
SCTP_BUF_LEN(m_notify) = 0;
event = mtod(m_notify, struct sctp_sender_dry_event *);
+ memset(event, 0, sizeof(struct sctp_sender_dry_event));
event->sender_dry_type = SCTP_SENDER_DRY_EVENT;
event->sender_dry_flags = 0;
event->sender_dry_length = sizeof(struct sctp_sender_dry_event);
@@ -3278,7 +3287,6 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
struct mbuf *m_notify;
struct sctp_queued_to_read *control;
struct sctp_stream_change_event *stradd;
- int len;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
@@ -3291,25 +3299,20 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t
return;
}
stcb->asoc.peer_req_out = 0;
- m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
+ m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_DONTWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
SCTP_BUF_LEN(m_notify) = 0;
- len = sizeof(struct sctp_stream_change_event);
- if (len > M_TRAILINGSPACE(m_notify)) {
- /* never enough room */
- sctp_m_freem(m_notify);
- return;
- }
stradd = mtod(m_notify, struct sctp_stream_change_event *);
+ memset(stradd, 0, sizeof(struct sctp_stream_change_event));
stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
stradd->strchange_flags = flag;
- stradd->strchange_length = len;
+ stradd->strchange_length = sizeof(struct sctp_stream_change_event);
stradd->strchange_assoc_id = sctp_get_associd(stcb);
stradd->strchange_instrms = numberin;
stradd->strchange_outstrms = numberout;
- SCTP_BUF_LEN(m_notify) = len;
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event);
SCTP_BUF_NEXT(m_notify) = NULL;
if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
/* no space */
@@ -3340,32 +3343,26 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32
struct mbuf *m_notify;
struct sctp_queued_to_read *control;
struct sctp_assoc_reset_event *strasoc;
- int len;
if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
/* event not enabled */
return;
}
- m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
+ m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_DONTWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
return;
SCTP_BUF_LEN(m_notify) = 0;
- len = sizeof(struct sctp_assoc_reset_event);
- if (len > M_TRAILINGSPACE(m_notify)) {
- /* never enough room */
- sctp_m_freem(m_notify);
- return;
- }
strasoc = mtod(m_notify, struct sctp_assoc_reset_event *);
+ memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event));
strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
strasoc->assocreset_flags = flag;
- strasoc->assocreset_length = len;
+ strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event);
strasoc->assocreset_assoc_id = sctp_get_associd(stcb);
strasoc->assocreset_local_tsn = sending_tsn;
strasoc->assocreset_remote_tsn = recv_tsn;
- SCTP_BUF_LEN(m_notify) = len;
+ SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event);
SCTP_BUF_NEXT(m_notify) = NULL;
if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
/* no space */
@@ -3418,6 +3415,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
return;
}
strreset = mtod(m_notify, struct sctp_stream_reset_event *);
+ memset(strreset, 0, len);
strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
strreset->strreset_flags = flag;
strreset->strreset_length = len;
@@ -6209,9 +6207,12 @@ sctp_soreceive(struct socket *so,
fromlen = 0;
}
+ if (filling_sinfo) {
+ memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo));
+ }
error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp,
(struct sctp_sndrcvinfo *)&sinfo, filling_sinfo);
- if ((controlp) && (filling_sinfo)) {
+ if (controlp != NULL) {
/* copy back the sinfo in a CMSG format */
if (filling_sinfo)
*controlp = sctp_build_ctl_nchunk(inp,