From owner-svn-src-all@FreeBSD.ORG Tue Jul 8 21:55:32 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0FC058C6; Tue, 8 Jul 2014 21:55:32 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EDBC125EF; Tue, 8 Jul 2014 21:55:31 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s68LtViN019383; Tue, 8 Jul 2014 21:55:31 GMT (envelope-from delphij@svn.freebsd.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s68LtS58019358; Tue, 8 Jul 2014 21:55:28 GMT (envelope-from delphij@svn.freebsd.org) Message-Id: <201407082155.s68LtS58019358@svn.freebsd.org> From: Xin LI Date: Tue, 8 Jul 2014 21:55:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r268434 - in releng: 10.0 10.0/sys/conf 10.0/sys/kern 10.0/sys/netinet 9.1 9.1/sys/conf 9.1/sys/kern 9.1/sys/netinet 9.2 9.2/sys/conf 9.2/sys/kern 9.2/sys/netinet X-SVN-Group: releng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Jul 2014 21:55:32 -0000 Author: delphij Date: Tue Jul 8 21:55:27 2014 New Revision: 268434 URL: http://svnweb.freebsd.org/changeset/base/268434 Log: Fix kernel memory disclosure in control message and SCTP notifications. Security: FreeBSD-SA-14:17.kmem Security: CVE-2014-3952, CVE-2014-3953 Approved by: so Modified: releng/10.0/UPDATING releng/10.0/sys/conf/newvers.sh releng/10.0/sys/kern/uipc_sockbuf.c releng/10.0/sys/netinet/sctp_auth.c releng/10.0/sys/netinet/sctp_indata.c releng/10.0/sys/netinet/sctputil.c releng/9.1/UPDATING releng/9.1/sys/conf/newvers.sh releng/9.1/sys/kern/uipc_sockbuf.c releng/9.1/sys/netinet/sctp_auth.c releng/9.1/sys/netinet/sctp_indata.c releng/9.1/sys/netinet/sctputil.c releng/9.2/UPDATING releng/9.2/sys/conf/newvers.sh releng/9.2/sys/kern/uipc_sockbuf.c releng/9.2/sys/netinet/sctp_auth.c releng/9.2/sys/netinet/sctp_indata.c releng/9.2/sys/netinet/sctputil.c Modified: releng/10.0/UPDATING ============================================================================== --- releng/10.0/UPDATING Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/UPDATING Tue Jul 8 21:55:27 2014 (r268434) @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITH stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20140708: p7 FreeBSD-SA-14:17.kmem + Fix kernel memory disclosure in control messages and SCTP + notifications. [SA-14:17] + 20140624: p6 FreeBSD-SA-14:15.iconv FreeBSD-SA-14:16.file FreeBSD-EN-14:07.pmap Modified: releng/10.0/sys/conf/newvers.sh ============================================================================== --- releng/10.0/sys/conf/newvers.sh Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/sys/conf/newvers.sh Tue Jul 8 21:55:27 2014 (r268434) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.0" -BRANCH="RELEASE-p6" +BRANCH="RELEASE-p7" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi Modified: releng/10.0/sys/kern/uipc_sockbuf.c ============================================================================== --- releng/10.0/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1044,6 +1044,11 @@ sbcreatecontrol(caddr_t p, int size, int 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); Modified: releng/10.0/sys/netinet/sctp_auth.c ============================================================================== --- releng/10.0/sys/netinet/sctp_auth.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/sys/netinet/sctp_auth.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1790,6 +1790,7 @@ sctp_notify_authentication(struct sctp_t 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); Modified: releng/10.0/sys/netinet/sctp_indata.c ============================================================================== --- releng/10.0/sys/netinet/sctp_indata.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/sys/netinet/sctp_indata.c Tue Jul 8 21:55:27 2014 (r268434) @@ -250,6 +250,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb /* 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)); Modified: releng/10.0/sys/netinet/sctputil.c ============================================================================== --- releng/10.0/sys/netinet/sctputil.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/10.0/sys/netinet/sctputil.c Tue Jul 8 21:55:27 2014 (r268434) @@ -2622,6 +2622,7 @@ sctp_notify_assoc_change(uint16_t state, } 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); @@ -2835,21 +2836,21 @@ sctp_notify_send_failed(struct sctp_tcb 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; @@ -2859,12 +2860,15 @@ sctp_notify_send_failed(struct sctp_tcb 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 :) */ @@ -2948,16 +2952,16 @@ sctp_notify_send_failed2(struct sctp_tcb /* 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; @@ -2971,12 +2975,13 @@ sctp_notify_send_failed2(struct sctp_tcb 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) { @@ -3038,6 +3043,7 @@ sctp_notify_adaptation_layer(struct sctp 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); @@ -3093,6 +3099,7 @@ sctp_notify_partial_delivery_indication( 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); @@ -3202,6 +3209,7 @@ sctp_notify_shutdown_event(struct sctp_t /* 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); @@ -3252,6 +3260,7 @@ sctp_notify_sender_dry_event(struct sctp } 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); @@ -3284,7 +3293,6 @@ sctp_notify_stream_reset_add(struct sctp 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))) { @@ -3297,25 +3305,20 @@ sctp_notify_stream_reset_add(struct sctp return; } stcb->asoc.peer_req_out = 0; - m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 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 */ @@ -3346,32 +3349,26 @@ sctp_notify_stream_reset_tsn(struct sctp 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_NOWAIT, 1, MT_DATA); + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 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 */ @@ -3424,6 +3421,7 @@ sctp_notify_stream_reset(struct sctp_tcb 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; @@ -6214,9 +6212,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, Modified: releng/9.1/UPDATING ============================================================================== --- releng/9.1/UPDATING Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/UPDATING Tue Jul 8 21:55:27 2014 (r268434) @@ -9,6 +9,10 @@ handbook. Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20140708: p17 FreeBSD-SA-14:17.kmem + Fix kernel memory disclosure in control messages and SCTP + notifications. [SA-14:17] + 20140624: p16 FreeBSD-SA-14:16.file FreeBSD-EN-14:08.heimdal Modified: releng/9.1/sys/conf/newvers.sh ============================================================================== --- releng/9.1/sys/conf/newvers.sh Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/sys/conf/newvers.sh Tue Jul 8 21:55:27 2014 (r268434) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="9.1" -BRANCH="RELEASE-p16" +BRANCH="RELEASE-p17" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi Modified: releng/9.1/sys/kern/uipc_sockbuf.c ============================================================================== --- releng/9.1/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1011,6 +1011,11 @@ sbcreatecontrol(caddr_t p, int size, int 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); Modified: releng/9.1/sys/netinet/sctp_auth.c ============================================================================== --- releng/9.1/sys/netinet/sctp_auth.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/sys/netinet/sctp_auth.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1876,6 +1876,7 @@ sctp_notify_authentication(struct sctp_t 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); Modified: releng/9.1/sys/netinet/sctp_indata.c ============================================================================== --- releng/9.1/sys/netinet/sctp_indata.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/sys/netinet/sctp_indata.c Tue Jul 8 21:55:27 2014 (r268434) @@ -250,6 +250,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb /* 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)); Modified: releng/9.1/sys/netinet/sctputil.c ============================================================================== --- releng/9.1/sys/netinet/sctputil.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.1/sys/netinet/sctputil.c Tue Jul 8 21:55:27 2014 (r268434) @@ -2628,6 +2628,7 @@ sctp_notify_assoc_change(uint16_t state, } 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); @@ -2834,21 +2835,21 @@ sctp_notify_send_failed(struct sctp_tcb 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; @@ -2858,12 +2859,15 @@ sctp_notify_send_failed(struct sctp_tcb 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 :) */ @@ -2947,16 +2951,16 @@ sctp_notify_send_failed2(struct sctp_tcb /* 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; @@ -2970,12 +2974,13 @@ sctp_notify_send_failed2(struct sctp_tcb 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 = sp->strseq; if (sp->some_taken) { @@ -3037,6 +3042,7 @@ sctp_notify_adaptation_layer(struct sctp 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); @@ -3092,6 +3098,7 @@ sctp_notify_partial_delivery_indication( 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); @@ -3201,6 +3208,7 @@ sctp_notify_shutdown_event(struct sctp_t /* 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); @@ -3251,6 +3259,7 @@ sctp_notify_sender_dry_event(struct sctp } 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); @@ -3283,7 +3292,6 @@ sctp_notify_stream_reset_add(struct sctp 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))) { @@ -3296,25 +3304,20 @@ sctp_notify_stream_reset_add(struct sctp 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 */ @@ -3345,32 +3348,26 @@ sctp_notify_stream_reset_tsn(struct sctp 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 */ @@ -3423,6 +3420,7 @@ sctp_notify_stream_reset(struct sctp_tcb 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; @@ -6261,9 +6259,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, Modified: releng/9.2/UPDATING ============================================================================== --- releng/9.2/UPDATING Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/UPDATING Tue Jul 8 21:55:27 2014 (r268434) @@ -11,6 +11,10 @@ handbook: Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20140708: p10 FreeBSD-SA-14:17.kmem + Fix kernel memory disclosure in control messages and SCTP + notifications. [SA-14:17] + 20140624: p9 FreeBSD-SA-14:16.file FreeBSD-EN-14:08.heimdal Modified: releng/9.2/sys/conf/newvers.sh ============================================================================== --- releng/9.2/sys/conf/newvers.sh Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/sys/conf/newvers.sh Tue Jul 8 21:55:27 2014 (r268434) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="9.2" -BRANCH="RELEASE-p9" +BRANCH="RELEASE-p10" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi Modified: releng/9.2/sys/kern/uipc_sockbuf.c ============================================================================== --- releng/9.2/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/sys/kern/uipc_sockbuf.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1018,6 +1018,11 @@ sbcreatecontrol(caddr_t p, int size, int 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); Modified: releng/9.2/sys/netinet/sctp_auth.c ============================================================================== --- releng/9.2/sys/netinet/sctp_auth.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/sys/netinet/sctp_auth.c Tue Jul 8 21:55:27 2014 (r268434) @@ -1876,6 +1876,7 @@ sctp_notify_authentication(struct sctp_t 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); Modified: releng/9.2/sys/netinet/sctp_indata.c ============================================================================== --- releng/9.2/sys/netinet/sctp_indata.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/sys/netinet/sctp_indata.c Tue Jul 8 21:55:27 2014 (r268434) @@ -250,6 +250,11 @@ sctp_build_ctl_nchunk(struct sctp_inpcb /* 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)); Modified: releng/9.2/sys/netinet/sctputil.c ============================================================================== --- releng/9.2/sys/netinet/sctputil.c Tue Jul 8 21:55:02 2014 (r268433) +++ releng/9.2/sys/netinet/sctputil.c Tue Jul 8 21:55:27 2014 (r268434) @@ -2622,6 +2622,7 @@ sctp_notify_assoc_change(uint16_t state, } 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); @@ -2835,21 +2836,21 @@ sctp_notify_send_failed(struct sctp_tcb 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; @@ -2859,12 +2860,15 @@ sctp_notify_send_failed(struct sctp_tcb 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 :) */ @@ -2948,16 +2952,16 @@ sctp_notify_send_failed2(struct sctp_tcb /* 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; @@ -2971,12 +2975,13 @@ sctp_notify_send_failed2(struct sctp_tcb 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) { @@ -3038,6 +3043,7 @@ sctp_notify_adaptation_layer(struct sctp 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); @@ -3093,6 +3099,7 @@ sctp_notify_partial_delivery_indication( 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); @@ -3202,6 +3209,7 @@ sctp_notify_shutdown_event(struct sctp_t /* 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); @@ -3252,6 +3260,7 @@ sctp_notify_sender_dry_event(struct sctp } 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); @@ -3284,7 +3293,6 @@ sctp_notify_stream_reset_add(struct sctp 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))) { @@ -3297,25 +3305,20 @@ sctp_notify_stream_reset_add(struct sctp 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 */ @@ -3346,32 +3349,26 @@ sctp_notify_stream_reset_tsn(struct sctp 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 */ @@ -3424,6 +3421,7 @@ sctp_notify_stream_reset(struct sctp_tcb 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; @@ -6215,9 +6213,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,