From patchwork Thu Feb 1 20:00:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 10195957 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D732B60247 for ; Thu, 1 Feb 2018 20:36:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C46D828952 for ; Thu, 1 Feb 2018 20:36:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C2D68288CD; Thu, 1 Feb 2018 20:36:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D2F428D08 for ; Thu, 1 Feb 2018 20:12:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754675AbeBAUAI (ORCPT ); Thu, 1 Feb 2018 15:00:08 -0500 Received: from bedivere.hansenpartnership.com ([66.63.167.143]:43792 "EHLO bedivere.hansenpartnership.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754594AbeBAUAI (ORCPT ); Thu, 1 Feb 2018 15:00:08 -0500 Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 0647B8EE16F; Thu, 1 Feb 2018 12:00:08 -0800 (PST) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id iHUb9Df5rUA5; Thu, 1 Feb 2018 12:00:07 -0800 (PST) Received: from [192.168.41.250] (unknown [94.107.236.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by bedivere.hansenpartnership.com (Postfix) with ESMTPSA id 0BCB38EE0C7; Thu, 1 Feb 2018 12:00:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=hansenpartnership.com; s=20151216; t=1517515207; bh=wtSueEaQ2B7Lh7JBNL1C7q9U59SjHweVIyIQ41PfZT0=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=uCCcDcxTIj/KKuFtWM+rXG113agITqskcmdCP5LiMq163/HdIdgImGFXhLEDDjCJx 0+3DLKLKHvz/TUln/RNSfMY+WnKM7r3w/YV3ue9FmF3lgIXS54ClJs+gQEuY0eG/l4 V6Z5C1/o4CVMIhUvqD0o48hgZ3dTFhqs3DpWX+TU= Message-ID: <1517515204.3145.51.camel@HansenPartnership.com> Subject: Re: TPM selftest failure in 4.15 From: James Bottomley To: Jason Gunthorpe Cc: Paul Menzel , linux-integrity Date: Thu, 01 Feb 2018 21:00:04 +0100 In-Reply-To: <20180201185909.GW17053@ziepe.ca> References: <1517487371.3251.9.camel@HansenPartnership.com> <1517488970.3251.26.camel@HansenPartnership.com> <1517498648.3145.4.camel@HansenPartnership.com> <20180201174053.GQ17053@ziepe.ca> <1517510764.3145.38.camel@HansenPartnership.com> <20180201185909.GW17053@ziepe.ca> X-Mailer: Evolution 3.20.5 Mime-Version: 1.0 Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Thu, 2018-02-01 at 11:59 -0700, Jason Gunthorpe wrote: > On Thu, Feb 01, 2018 at 07:46:04PM +0100, James Bottomley wrote: > > > > > I honestly don't think we should be waiting for the self test at > > all. > > We should kick it off and treat any TPM_RC_TESTING error as > > -EAGAIN. > > We're already under fire for slow boot sequences and adding 2s just > > to > > wait for the TPM to self test adds to that for no real value. > > Arguably the BIOS should have completed the selftest - this stuff > generally only exists to support embedded. > > I don't like the idea of EAGAIN, that just expose all our users to > this mess. > > I would support making transmit_cmd genericly wait and retry if the > TPM insists we need to wait for selftest to complete the specific > command though. OK, how about this then? James diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1d6729be4cd6..84ed271c060b 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -521,12 +521,32 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space, const struct tpm_output_header *header = buf; int err; ssize_t len; + unsigned int delay_msec = 20; - len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); - if (len < 0) - return len; + /* + * on first probe we kick off a TPM self test in the + * background This means the TPM may return RC_TESTING to any + * command that tries to use a subsystem under test, so do an + * exponential backoff wait if that happens + */ + for (;;) { + len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags); + if (len < 0) + return len; + + err = be32_to_cpu(header->return_code); + if (err != TPM2_RC_TESTING || + (flags & TPM_TRANSMIT_NOWAIT)) + break; + + delay_msec *= 2; + if (delay_msec > TPM2_DURATION_LONG) { + dev_err(&chip->dev,"TPM: still running self tests, giving up waiting\n"); + break; + } + tpm_msleep(delay_msec); + } - err = be32_to_cpu(header->return_code); if (err != 0 && desc) dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err, desc); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 528cffbd49d3..47c5a5206325 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -495,6 +495,7 @@ extern struct idr dev_nums_idr; enum tpm_transmit_flags { TPM_TRANSMIT_UNLOCKED = BIT(0), TPM_TRANSMIT_RAW = BIT(1), + TPM_TRANSMIT_NOWAIT = BIT(2), }; ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index f40d20671a78..106c126b4fe0 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -849,28 +849,24 @@ static const struct tpm_input_header tpm2_selftest_header = { static int tpm2_do_selftest(struct tpm_chip *chip) { int rc; - unsigned int delay_msec = 20; - long duration; struct tpm2_cmd cmd; - duration = jiffies_to_msecs( - tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); - - while (duration > 0) { - cmd.header.in = tpm2_selftest_header; - cmd.params.selftest_in.full_test = 0; - - rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, - 0, 0, "continue selftest"); - - if (rc != TPM2_RC_TESTING) - break; - - tpm_msleep(delay_msec); - duration -= delay_msec; - - /* wait longer the next round */ - delay_msec *= 2; + cmd.header.in = tpm2_selftest_header; + cmd.params.selftest_in.full_test = 0; + + rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, + 0, TPM_TRANSMIT_NOWAIT, "continue selftest"); + + if (rc == TPM2_RC_TESTING) { + /* + * A return of RC_TESTING means the TPM is still + * running self tests. If one fails it will go into + * failure mode and return RC_FAILED to every command, + * so treat a still in testing return as a success + * rather than causing a driver detach. + */ + dev_info(&chip->dev,"TPM: Running self test in background\n"); + rc = TPM2_RC_SUCCESS; } return rc;