Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp849985pxb; Fri, 21 Jan 2022 04:55:20 -0800 (PST) X-Google-Smtp-Source: ABdhPJySGNJkKWMHnKM9DCT9IPSgcYPVWz5gz74HDOHxHRihd2+7vCihROh0UlIgkLnyvcSvOLCn X-Received: by 2002:a63:7845:: with SMTP id t66mr2878371pgc.103.1642769720107; Fri, 21 Jan 2022 04:55:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642769720; cv=none; d=google.com; s=arc-20160816; b=M4MH8jbL9iemPszfPF+ZcRL3RII5nnTywfgNBYTBgkORbO3ZBezzIHkW9KKrfznVrz lxkxUEDNcabhkS+hujK6haktUffJhERnlFnL8juC444N4uZsg8eCds2dP60DxFDfaz+4 konHEP8BaN5ZPSe5+DQ4w5bQ8qJ16+u7TxIzV/qtnKk4TgLFKK68QXqXy5Uq/QGtu5Xl gjw4ZMa9qrPhG6gyAia4exITzyyBEfjPDLD/rBiEm3RraUgFQm9DrVN5YzSX/ubEDVKi ebPHbdg5K7uQp0rV4CyvPgQOVo5W5QkIn/AdHAizKMixhErz11w3H3OynIhJwnPnmbPZ IZeg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=WC6vCmlBaJcnOq0yqjfAIqZ48ognlL3tNUNuOCNKcLA=; b=pCz9364pemI/3IVEHksyx7ZhaA8Elh1Xp5nSDMP/UC37bofeKgYQh/xHWabTXoEYaX zuPJyVdebyyTDKY4vbH/M0LqErZetFEUO1pnEicy0O4ez5s6owJ/toRLWFMOzkJlMTOk nn4jA7lyo+rGjGarraznz+dZt5Vp+bWeIqTAmc0/waRKvSxOjptnMmrPO5FOjNkVYpkL 7vEe7lkudePzqIMcPDeUNz0EdR87BpTBHBQA8IQ5levAyquJ+H9M0VnbqiR8+D8A9A3i EGKHXKyB91E4HD5wGyTadq2BOXw0qjsibjIHGC5X5vmkvq+hCIUkAvmqZOhI3jTE3AJC yiZw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=JjdZ1Qa0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g2si5718442plt.185.2022.01.21.04.55.07; Fri, 21 Jan 2022 04:55:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=JjdZ1Qa0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350455AbiASAmf (ORCPT + 99 others); Tue, 18 Jan 2022 19:42:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235175AbiASAme (ORCPT ); Tue, 18 Jan 2022 19:42:34 -0500 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C19BC06161C for ; Tue, 18 Jan 2022 16:42:33 -0800 (PST) Received: by mail-lf1-x133.google.com with SMTP id o12so2191106lfu.12 for ; Tue, 18 Jan 2022 16:42:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=WC6vCmlBaJcnOq0yqjfAIqZ48ognlL3tNUNuOCNKcLA=; b=JjdZ1Qa07omNstuAfkDNTfKeVCeI3Y9spOp3On6OcIMntUS3IS5W/0Jqr8JBWQcuuq wvfuCIEq9LyVMNJhUREVCJJH/yzkpHWh/Jc+sx5VLJafgGpTKk90V/aeek82j8R9SpIG ssvHuxn4pBXKmBCOrMUZV8jYXXphDOr8QW6G0KsuREth4TOM/Bvt9ZM9E117kgZgQPiV IAjpkAYGdX9tH76Y4rt/BT4Rbqacl/i5q0/wIfHLLkuz1f/HVGDOzaUcZn45X1U659Ve kDcqj1epuybqsUqzS2+tPbfOWz+IqOeEAjAJ30Z4hCxtFPMwwFg+tP2ftuSGjhbA6Jj4 fhLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=WC6vCmlBaJcnOq0yqjfAIqZ48ognlL3tNUNuOCNKcLA=; b=U/6Z/7t9g1nFF0Gc4yCd7U0a4nFec86wDSJidsFlfxEZxh4admlH3F5VpTXh3a2AOg msgqGnAuI+XGiQtazG4OMwmkxuTYomNZ2C9UYJbB4c8lmrMfwPR0brADxxr2DY4rEnpg H4S8jKR+PCJ9bT+Z8w+S/WQLS479DgtD9p+B+M8QQ8fN+6p+UuehhiytBIyCTRvU8rt7 aM++T47enS5EHTRg+ayzp+RPorZz9N8IZuyQj70e/HQlxI7dQqsQghV0OraW0osIYfRb 4DZEr2b4oP3cPEHfV/D0n2XIodOPSkfIDlxChObAEQxKkkWWbnVHTxWsalHJJ8vwn7GE EkxA== X-Gm-Message-State: AOAM532NGRNqYkSLexRfGAXOt0iecEd0unNi7rQdG+wD23+RBGYrd7YM PCBDKWxSnSGBfiZ7YTSezS6/L9t1YQkIVsXniwVjRg== X-Received: by 2002:a2e:9e98:: with SMTP id f24mr22000014ljk.347.1642552951599; Tue, 18 Jan 2022 16:42:31 -0800 (PST) MIME-Version: 1.0 References: <20220118183650.3386989-1-keescook@chromium.org> <20220118193931.GH8034@ziepe.ca> <202201181255.DB5D38F6AA@keescook> In-Reply-To: <202201181255.DB5D38F6AA@keescook> From: Jann Horn Date: Wed, 19 Jan 2022 01:42:04 +0100 Message-ID: Subject: Re: [PATCH v2] tpm: vtpm_proxy: Double-check to avoid buffer overflow To: Kees Cook Cc: Jason Gunthorpe , Peter Huewe , Jarkko Sakkinen , linux-integrity@vger.kernel.org, Stefan Berger , linux-kernel@vger.kernel.org, linux-hardening@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jan 18, 2022 at 10:20 PM Kees Cook wrote: > On Tue, Jan 18, 2022 at 03:39:31PM -0400, Jason Gunthorpe wrote: > > On Tue, Jan 18, 2022 at 08:32:43PM +0100, Jann Horn wrote: > > > On Tue, Jan 18, 2022 at 7:37 PM Kees Cook wro= te: > > > > When building with -Warray-bounds, this warning was emitted: > > > > > > > > In function 'memset', > > > > inlined from 'vtpm_proxy_fops_read' at drivers/char/tpm/tpm_vtp= m_proxy.c:102:2: > > > > ./include/linux/fortify-string.h:43:33: warning: '__builtin_memset'= pointer overflow between offset 164 and size [2147483648, 4294967295] > > > > [-Warray-bounds] > > > > 43 | #define __underlying_memset __builtin_memset > > > > | ^ > > > > > > Can you explain what that compiler warning actually means, and which > > > compiler it is from? Is this from a 32-bit or a 64-bit architecture? > > This is from ARCH=3Di386 > > > > > > > It sounds like the compiler (GCC?) is hallucinating a codepath on > > Yes, GCC 11.2. > > > > which "len" is guaranteed to be >=3D2147483648, right? Why is it doin= g > > > that? Is this some kinda side effect from the fortify code? > > Right; I don't know what triggered it. I assume the "count" comparison. > The warning is generated with or without CONFIG_FORTIFY_SOURCE. It is > from adding -Warray-bounds. This is one of the last places in the kernel > where a warning is being thrown for this option, and it has found a lot > of real bugs, so Gustavo and I have been working to get the build > warning-clean so we can enable it globally. > > > I agree, this looks bogus, or at least the commit message neeeds alot > > more explaining. > > > > static int vtpm_proxy_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_= t count) > > > > if (count > sizeof(proxy_dev->buffer)) > > [...] > > proxy_dev->req_len =3D count; > > > > Not clear how req_len can be larger than sizeof(buffer)? > > Given the current code, I agree: it's not possible. > > As for the cause of the warning, my assumption is that since the compiler > only has visibility into vtpm_proxy_fops_read(), and sees size_t len set > from ((struct proxy_dev *)filp->private_data)->req_len, and it performs > range checking perhaps triggered by the "count" comparison: > > > static ssize_t vtpm_proxy_fops_read(struct file *filp, char __user *buf, > size_t count, loff_t *off) > { > struct proxy_dev *proxy_dev =3D filp->private_data; > size_t len; > ... > len =3D proxy_dev->req_len; > > if (count < len) { > ... > return -EIO; > } > > rc =3D copy_to_user(buf, proxy_dev->buffer, len); > memset(proxy_dev->buffer, 0, len); > > > I haven't been able to reproduce the specific cause of why GCC decided to > do the bounds checking, but it's not an unreasonable thing to check for, > just for robustness. Ok, I think this is what's happening: $ cat bogus_bounds_warning_small.i struct proxy_dev { unsigned char buffer[4096]; }; long state; void vtpm_proxy_fops_read(struct proxy_dev *proxy_dev, unsigned int len) { /* * sz =3D=3D SIZE_MAX =3D=3D -1 because the compiler can't prove whether= proxy_dev * points to an array or a single object and we're using the type-0 versi= on. */ int sz =3D __builtin_object_size(proxy_dev->buffer, 0); _Bool check_result; /* always false but must keep this check to trigger the warning */ if (sz >=3D 0 && sz < len) { check_result =3D 0; /* * compiler forks the rest of the function starting at this check, probab= ly * because it sees that a branch further down has a condition that depend= s on * which branch we took here */ } else if (len > 0x7fffffff/*INT_MAX*/) { check_result =3D 0; } else { check_result =3D 1; } /* * this part is basically duplicated, it is compiled once for the * len<=3D0x7fffffff case and once for the len>0x7fffffff case */ __builtin_memset(proxy_dev->buffer, 0, len); if (check_result) state |=3D 1; } $ gcc -ggdb -std=3Dgnu89 -Warray-bounds -m32 -mregparm=3D3 -fno-pic -march=3Di686 -O2 -c -o bogus_bounds_warning.o bogus_bounds_warning_small.i bogus_bounds_warning_small.i: In function =E2=80=98vtpm_proxy_fops_read=E2= =80=99: bogus_bounds_warning_small.i:32:3: warning: =E2=80=98__builtin_memset=E2=80= =99 specified bound between 2147483648 and 4294967295 exceeds maximum object size 2147483647 [-Wstringop-overflow=3D] 32 | __builtin_memset(proxy_dev->buffer, 0, len); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here's what the CFG of the generated machine code looks like - you can see how the function is split up starting at the "len > 0x7fffffff" check: https://var.thejh.net/gcc_bounds_warning_cfg.png (You can also see how the two copies of __builtin_memset() generate some pretty gross and bloated code...)