From patchwork Thu Sep 7 13:02:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kleber Sacilotto de Souza X-Patchwork-Id: 811003 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3xp0x23QWfz9sRY; Thu, 7 Sep 2017 23:02:46 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1dpwS7-00077p-QF; Thu, 07 Sep 2017 13:02:39 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1dpwS6-00077j-WA for kernel-team@lists.ubuntu.com; Thu, 07 Sep 2017 13:02:38 +0000 Received: from mail-wm0-f71.google.com ([74.125.82.71]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1dpwS6-0003es-Oo for kernel-team@lists.ubuntu.com; Thu, 07 Sep 2017 13:02:38 +0000 Received: by mail-wm0-f71.google.com with SMTP id e64so1473476wmi.0 for ; Thu, 07 Sep 2017 06:02:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=9PmIl1ozgNJ4qvNywrwX58IoUXnfGy6Yc36/gu9id4M=; b=rT1j1YpGvrzmlXYrHfaphSzH/ss5Exjrr7pxWF4DbA+liuJgEOhpwuEDYLIJrGdNGb IEVAVsHMk2/PYitgcXEMScOeyQ89z4ZySYL/zk9Vp+3GOiX1Mtaz9jG8H9yOjLYLHK6b OJNUYVNO+DOXIPKEAJKtesqG0KY0hhd01+dWbRgrtyJgphR3a0cWTtbdHRoKY0oNBt8O OllwTCANAGeObBG0VmLDSl4gn641qJhUG9Fr0wQcnuyM0QtRRTNhxwsymEtBNi9iL87Q mCSqKfR/GOLedkXxWMdzRWftf26UwgwjcritpFem5ewzUimgjywhgNzFaZsvdX3hinvE Y2bw== X-Gm-Message-State: AHPjjUgIHr+gQrPjn8gg23p4ps4xG0YYlwfh15e1XaEV0+hnrbmLy29u Ezl+DHNxy0Yp22sjgMoTg8oORv9I52RBPMOZxHxxZ9Ucv/4uZ0OwmQ2+CefTL6+iTeJDV9BETbO mOERtJaU9+yihiCDgNSvihdYPs/rU3HOz X-Received: by 10.80.147.228 with SMTP id o91mr2372133eda.163.1504789357709; Thu, 07 Sep 2017 06:02:37 -0700 (PDT) X-Google-Smtp-Source: ADKCNb7yyRmzcnupZVDvUmlNIEG0If5AVX1V616ZahXCwrlyuo9vxSnWaBw+bZ6kDMv0M52tCMZKQQ== X-Received: by 10.80.147.228 with SMTP id o91mr2372079eda.163.1504789356597; Thu, 07 Sep 2017 06:02:36 -0700 (PDT) Received: from localhost (ip5f5bd015.dynamic.kabel-deutschland.de. [95.91.208.21]) by smtp.gmail.com with ESMTPSA id q5sm2085339edh.24.2017.09.07.06.02.35 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 07 Sep 2017 06:02:35 -0700 (PDT) From: Kleber Sacilotto de Souza To: kernel-team@lists.ubuntu.com Subject: [Trusty SRU][CVE-2016-8633][PATCH] firewire: net: guard against rx buffer overflows Date: Thu, 7 Sep 2017 15:02:33 +0200 Message-Id: <20170907130233.30902-1-kleber.souza@canonical.com> X-Mailer: git-send-email 2.14.1 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Stefan Richter CVE-2016-8633 The IP-over-1394 driver firewire-net lacked input validation when handling incoming fragmented datagrams. A maliciously formed fragment with a respectively large datagram_offset would cause a memcpy past the datagram buffer. So, drop any packets carrying a fragment with offset + length larger than datagram_size. In addition, ensure that - GASP header, unfragmented encapsulation header, or fragment encapsulation header actually exists before we access it, - the encapsulated datagram or fragment is of nonzero size. Reported-by: Eyal Itkin Reviewed-by: Eyal Itkin Fixes: CVE 2016-8633 Cc: stable@vger.kernel.org Signed-off-by: Stefan Richter (cherry picked from commit 667121ace9dbafb368618dbabcf07901c962ddac) Signed-off-by: Kleber Sacilotto de Souza Acked-by: Stefan Bader Acked-by: Colin Ian King --- Notes: Only Trusty still needs the fix for this CVE. Cherry pick applies cleanly, compile tested. Kleber drivers/firewire/net.c | 51 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 4af0a7bad7f2..641eeab43c57 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -591,6 +591,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, int retval; u16 ether_type; + if (len <= RFC2374_UNFRAG_HDR_SIZE) + return 0; + hdr.w0 = be32_to_cpu(buf[0]); lf = fwnet_get_hdr_lf(&hdr); if (lf == RFC2374_HDR_UNFRAG) { @@ -615,7 +618,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, return fwnet_finish_incoming_packet(net, skb, source_node_id, is_broadcast, ether_type); } + /* A datagram fragment has been received, now the fun begins. */ + + if (len <= RFC2374_FRAG_HDR_SIZE) + return 0; + hdr.w1 = ntohl(buf[1]); buf += 2; len -= RFC2374_FRAG_HDR_SIZE; @@ -629,6 +637,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, datagram_label = fwnet_get_hdr_dgl(&hdr); dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ + if (fg_off + len > dg_size) + return 0; + spin_lock_irqsave(&dev->lock, flags); peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); @@ -735,6 +746,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, fw_send_response(card, r, rcode); } +static int gasp_source_id(__be32 *p) +{ + return be32_to_cpu(p[0]) >> 16; +} + +static u32 gasp_specifier_id(__be32 *p) +{ + return (be32_to_cpu(p[0]) & 0xffff) << 8 | + (be32_to_cpu(p[1]) & 0xff000000) >> 24; +} + +static u32 gasp_version(__be32 *p) +{ + return be32_to_cpu(p[1]) & 0xffffff; +} + static void fwnet_receive_broadcast(struct fw_iso_context *context, u32 cycle, size_t header_length, void *header, void *data) { @@ -744,9 +771,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, __be32 *buf_ptr; int retval; u32 length; - u16 source_node_id; - u32 specifier_id; - u32 ver; unsigned long offset; unsigned long flags; @@ -763,22 +787,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, spin_unlock_irqrestore(&dev->lock, flags); - specifier_id = (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8 - | (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24; - ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; - source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; - - if (specifier_id == IANA_SPECIFIER_ID && - (ver == RFC2734_SW_VERSION + if (length > IEEE1394_GASP_HDR_SIZE && + gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID && + (gasp_version(buf_ptr) == RFC2734_SW_VERSION #if IS_ENABLED(CONFIG_IPV6) - || ver == RFC3146_SW_VERSION + || gasp_version(buf_ptr) == RFC3146_SW_VERSION #endif - )) { - buf_ptr += 2; - length -= IEEE1394_GASP_HDR_SIZE; - fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, + )) + fwnet_incoming_packet(dev, buf_ptr + 2, + length - IEEE1394_GASP_HDR_SIZE, + gasp_source_id(buf_ptr), context->card->generation, true); - } packet.payload_length = dev->rcv_buffer_size; packet.interrupt = 1;