From patchwork Mon Dec 17 20:08:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014750 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.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="h2UQf0mz"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JXV26N63z9s3q for ; Tue, 18 Dec 2018 07:16:10 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 93E32C221C0; Mon, 17 Dec 2018 20:15:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id CD7EDC221B1; Mon, 17 Dec 2018 20:09:09 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5D042C221A9; Mon, 17 Dec 2018 20:08:59 +0000 (UTC) Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by lists.denx.de (Postfix) with ESMTPS id 7C38DC221E2 for ; Mon, 17 Dec 2018 20:08:53 +0000 (UTC) Received: by mail-wr1-f66.google.com with SMTP id j2so13633345wrw.1 for ; Mon, 17 Dec 2018 12:08:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wdp/dAgyUB8W/vOsnLVGsMaG9tz+uxfpXX5lxZPnpXE=; b=h2UQf0mzHRB6btDsH5Lew+o5deJbP0QkGUaV1LdfETpKtBBkPVbkmQ5l3uKMfmQ8Kx bdUYu9NrphCQUYG7hDJCVJKftdhxb1nLjpJPiMYNGt29lvTHHYLPSUxas599OCK6eEfc 9Um65hVoQctvYNyqXxy/eojc3YguFGVIPtF9u+7l3cfgu6mPCXa95efKmUpP3FuXS3dW tFI58M4qvg/957S+HrvGOQIBFqnAvc3uKZIRxUXaFuPFPFyP6KypHsppuH0buNexI5J0 wq9qZqqocbr1KDzT6N/JcuPMC30YMCGrPyUwbDbSDEt6TmAfZjaBb75ix0VgN7HvaS5Y TjCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wdp/dAgyUB8W/vOsnLVGsMaG9tz+uxfpXX5lxZPnpXE=; b=Rn/jVOAYMN2lUL5FUvrs1aPPuUnot3ALQ83fDtN9kikbPTdHO4XZWuTfDmFs3bNzKH NLIU5SV3+odgXZCCjQJKEhdYhqP6G+ds+x5LfoTBNVd6ezW+BUyI3w8/A4HYunMvDzo+ S5tpjOAT96YzqY7GfF73GzmgjgrN4wc7A2eaTEGreHc7D7VsnA2ozx4soSyaWBv1EHHu VmU0CqoP3mjOVVL4MR5QL/G6aRMjcnyWo9/wnz3MN/0hQdDjwcP6gDgL6mHjwN1l8Hye k/KaOEhJrYrCcDLD93TFU8gmrQCAwNsFNmRP93oXkGAPW+ueOYAXdv9Sx+exVNuJQrpK kxnw== X-Gm-Message-State: AA+aEWZdaXnV+NMQX3lXKincIKYJ9Xbx40xuZG3rAN43ehvAhEWz6l5y Q9WNwGFwa2XBazG6byoHVN8= X-Google-Smtp-Source: AFSGD/V0s0vdJWBmDSw5KEXePaOuLBdxMTW0On+2I4pozdHSxcyPpOHeZP1Oh9TKrqSkD1zaB4V9Iw== X-Received: by 2002:a5d:550f:: with SMTP id b15mr12585481wrv.330.1545077333173; Mon, 17 Dec 2018 12:08:53 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id q9sm1066472wrv.26.2018.12.17.12.08.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 12:08:52 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 21:08:29 +0100 Message-Id: <20181217200830.32585-10-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217200830.32585-1-simon.k.r.goldschmidt@gmail.com> References: <20181217200830.32585-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v8 09/10] tftp: prevent overwriting reserved memory X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This fixes CVE-2018-18439 ("insufficient boundary checks in network image boot") by using lmb to check for a valid range to store received blocks. Signed-off-by: Simon Goldschmidt --- Changes in v8: None Changes in v7: - fix compiling without CONFIG_LMB Changes in v6: None Changes in v5: None Changes in v4: - this was patch 8, is now patch 7 - lines changed because v3 patch 7 got removed and MCAST_TFTP still exists Changes in v2: - this patch is new in v2 net/tftp.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 68ffd81414..a9335b1b7e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -17,6 +17,8 @@ #include #endif +DECLARE_GLOBAL_DATA_PTR; + /* Well known TFTP port # */ #define WELL_KNOWN_PORT 69 /* Millisecs to timeout for lost pkt */ @@ -81,6 +83,10 @@ static ulong tftp_block_wrap; /* memory offset due to wrapping */ static ulong tftp_block_wrap_offset; static int tftp_state; +static ulong tftp_load_addr; +#ifdef CONFIG_LMB +static ulong tftp_load_size; +#endif #ifdef CONFIG_TFTP_TSIZE /* The file size reported by the server */ static int tftp_tsize; @@ -164,10 +170,11 @@ static void mcast_cleanup(void) #endif /* CONFIG_MCAST_TFTP */ -static inline void store_block(int block, uchar *src, unsigned len) +static inline int store_block(int block, uchar *src, unsigned int len) { ulong offset = block * tftp_block_size + tftp_block_wrap_offset; ulong newsize = offset + len; + ulong store_addr = tftp_load_addr + offset; #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP int i, rc = 0; @@ -175,24 +182,32 @@ static inline void store_block(int block, uchar *src, unsigned len) /* start address in flash? */ if (flash_info[i].flash_id == FLASH_UNKNOWN) continue; - if (load_addr + offset >= flash_info[i].start[0]) { + if (store_addr >= flash_info[i].start[0]) { rc = 1; break; } } if (rc) { /* Flash is destination for this packet */ - rc = flash_write((char *)src, (ulong)(load_addr+offset), len); + rc = flash_write((char *)src, store_addr, len); if (rc) { flash_perror(rc); - net_set_state(NETLOOP_FAIL); - return; + return rc; } } else #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */ { - void *ptr = map_sysmem(load_addr + offset, len); - + void *ptr; + +#ifdef CONFIG_LMB + if (store_addr < tftp_load_addr || + store_addr + len > tftp_load_addr + tftp_load_size) { + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return -1; + } +#endif + ptr = map_sysmem(store_addr, len); memcpy(ptr, src, len); unmap_sysmem(ptr); } @@ -203,6 +218,8 @@ static inline void store_block(int block, uchar *src, unsigned len) if (net_boot_file_size < newsize) net_boot_file_size = newsize; + + return 0; } /* Clear our state ready for a new transfer */ @@ -606,7 +623,11 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, timeout_count_max = tftp_timeout_count_max; net_set_timeout_handler(timeout_ms, tftp_timeout_handler); - store_block(tftp_cur_block - 1, pkt + 2, len); + if (store_block(tftp_cur_block - 1, pkt + 2, len)) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + break; + } /* * Acknowledge the block just received, which will prompt @@ -695,6 +716,25 @@ static void tftp_timeout_handler(void) } } +/* Initialize tftp_load_addr and tftp_load_size from load_addr and lmb */ +static int tftp_init_load_addr(void) +{ +#ifdef CONFIG_LMB + struct lmb lmb; + phys_size_t max_size; + + lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start, + gd->bd->bi_dram[0].size, (void *)gd->fdt_blob); + + max_size = lmb_get_unreserved_size(&lmb, load_addr); + if (!max_size) + return -1; + + tftp_load_size = max_size; +#endif + tftp_load_addr = load_addr; + return 0; +} void tftp_start(enum proto_t protocol) { @@ -791,7 +831,14 @@ void tftp_start(enum proto_t protocol) } else #endif { - printf("Load address: 0x%lx\n", load_addr); + if (tftp_init_load_addr()) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return; + } + printf("Load address: 0x%lx\n", tftp_load_addr); puts("Loading: *\b"); tftp_state = STATE_SEND_RRQ; #ifdef CONFIG_CMD_BOOTEFI @@ -842,9 +889,15 @@ void tftp_start_server(void) { tftp_filename[0] = 0; + if (tftp_init_load_addr()) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + puts("\nTFTP error: trying to overwrite reserved memory...\n"); + return; + } printf("Using %s device\n", eth_get_name()); printf("Listening for TFTP transfer on %pI4\n", &net_ip); - printf("Load address: 0x%lx\n", load_addr); + printf("Load address: 0x%lx\n", tftp_load_addr); puts("Loading: *\b");