From patchwork Thu Nov 16 21:40:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 10062131 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 4E26E60230 for ; Thu, 16 Nov 2017 21:41:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 40DA02ABFB for ; Thu, 16 Nov 2017 21:41:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 35B692AC0A; Thu, 16 Nov 2017 21:41:01 +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 542232AC0C for ; Thu, 16 Nov 2017 21:41:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934671AbdKPVk7 (ORCPT ); Thu, 16 Nov 2017 16:40:59 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:35263 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932671AbdKPVk5 (ORCPT ); Thu, 16 Nov 2017 16:40:57 -0500 Received: by mail-pf0-f194.google.com with SMTP id d28so328650pfe.2; Thu, 16 Nov 2017 13:40:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id; bh=dD0i4dxyrmf/IkvkL87/0/9mQTfUQ35H3XmxCjhIQxs=; b=mWA04LZpqwy3pqreXYjUQ+s7BvzppGsNnVaKvRh0/q/43BXxDkTnA0s0heSP8twN/9 3KS6noKbHdtT9R1fChZWNU0/t5w/3oGpXcJ3e0xYPbqVABb/ESbAu09/8qKZxF6oCdEx WaYkYJtPS4sFjUodBzZfoO53i17vGAnk8vSIXlnnZiPOoYVlfPNzBE09LkCElJjiAcbM hpgzj91pPUsDTAWMIha+d2Ut+iyiFf/LYsYrolFC4VcqXrMD2rcGeEcBxbLpx9lhW1PN ZG5jsLMK/D50BVAtiAfaq5jI8rQdL4f+ulFxdxSE4WaVca1ANJ7gCK4zvyDxqtGHAmD3 4k1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id; bh=dD0i4dxyrmf/IkvkL87/0/9mQTfUQ35H3XmxCjhIQxs=; b=BAi/TtxLnjoTLJogXUcsVQe2lFJvhJM32C+mPgR4cGNnQ1syfGeutmQYHo8yJJsBwT jA/WGTYJ7hvm8eDUlbJNKLjjSlt1GWeASjlmhWojB3tR2//sCECsljEcAcSm27hxrPx8 jF7fCiU6caUumSjGNDupaUVmS2Rjbqfz6OJJbs1y9onPpGbSxG6kOcQReiPgq6dfYFuY HQWWxmfUuAfMYHTyhR17SrxJHfYEw/0svDWL3Mu1Sgp5738eN7SmNWZeW2d5IbJ2S1Ss 6ANKrukUYVq2DOP46VYwOJskbCvMeeiAEsekkJK6vijocvpPajhi+UeyWg4OqLAelSuL nPeQ== X-Gm-Message-State: AJaThX6XyL5csMB9axv2jCQSP1gb7XFZqGrYCubzu4KONazwAljGpBmN vACiMtQpyvsbrvq8OSQBZnE= X-Google-Smtp-Source: AGs4zMZrPpyuWXt6MV64L03iaDIskwfjg3gTmagG9Il+ISpjJm4Csc1TWlBywy9PP0pU3JF+uEWfaw== X-Received: by 10.98.93.136 with SMTP id n8mr3314199pfj.215.1510868456883; Thu, 16 Nov 2017 13:40:56 -0800 (PST) Received: from localhost (108-223-40-66.lightspeed.sntcca.sbcglobal.net. [108.223.40.66]) by smtp.gmail.com with ESMTPSA id r13sm4173295pfl.157.2017.11.16.13.40.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Nov 2017 13:40:56 -0800 (PST) From: Guenter Roeck To: Peter Huewe Cc: Andrey Pronin , Jarkko Sakkinen , Jason Gunthorpe , linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck Subject: [PATCH v2] tpm: Add explicit chip->ops locking for sysfs attributes. Date: Thu, 16 Nov 2017 13:40:54 -0800 Message-Id: <1510868454-31912-1-git-send-email-linux@roeck-us.net> X-Mailer: git-send-email 2.7.4 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 Add explicit chip->ops locking for all sysfs attributes. This lets us support those attributes on tpm2 devices. Signed-off-by: Guenter Roeck --- v2: It makes sense to actually compile the code. drivers/char/tpm/tpm-chip.c | 4 -- drivers/char/tpm/tpm-sysfs.c | 127 ++++++++++++++++++++++++++++++++----------- 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 0eca20c5a80c..f0593ec1c11b 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -149,10 +149,6 @@ static void tpm_devs_release(struct device *dev) * Issues a TPM2_Shutdown command prior to loss of power, as required by the * TPM 2.0 spec. * Then, calls bus- and device- specific shutdown code. - * - * XXX: This codepath relies on the fact that sysfs is not enabled for - * TPM2: sysfs uses an implicit lock on chip->ops, so this could race if TPM2 - * has sysfs support enabled before TPM sysfs's implicit locking is fixed. */ static int tpm_class_shutdown(struct device *dev) { diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 83a77a445538..13405bdde725 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -47,18 +47,22 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, memset(&anti_replay, 0, sizeof(anti_replay)); - rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); + rc = tpm_try_get_ops(chip); if (rc) return rc; + rc = tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); + if (rc) + goto put_ops; + tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); rc = tpm_transmit_cmd(chip, NULL, tpm_buf.data, PAGE_SIZE, READ_PUBEK_RESULT_MIN_BODY_SIZE, 0, "attempting to read the PUBEK"); if (rc) { - tpm_buf_destroy(&tpm_buf); - return 0; + rc = 0; + goto buf_destroy; } out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; @@ -91,7 +95,10 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, } rc = str - buf; +buf_destroy: tpm_buf_destroy(&tpm_buf); +put_ops: + tpm_put_ops(chip); return rc; } static DEVICE_ATTR_RO(pubek); @@ -106,11 +113,17 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, char *str = buf; struct tpm_chip *chip = to_tpm_chip(dev); + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS", sizeof(cap.num_pcrs)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { @@ -122,23 +135,35 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, str += sprintf(str, "%02X ", digest[j]); str += sprintf(str, "\n"); } - return str - buf; + rc = str - buf; +put_ops: + tpm_put_ops(chip); + return rc; } static DEVICE_ATTR_RO(pcrs); static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct tpm_chip *chip = to_tpm_chip(dev); cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + + rc = tpm_getcap(chip, TPM_CAP_FLAG_PERM, &cap, "attempting to determine the permanent enabled state", sizeof(cap.perm_flags)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); +put_ops: + tpm_put_ops(chip); return rc; } static DEVICE_ATTR_RO(enabled); @@ -146,16 +171,25 @@ static DEVICE_ATTR_RO(enabled); static ssize_t active_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct tpm_chip *chip = to_tpm_chip(dev); cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap, + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + + rc = tpm_getcap(chip, TPM_CAP_FLAG_PERM, &cap, "attempting to determine the permanent active state", sizeof(cap.perm_flags)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); +put_ops: + tpm_put_ops(chip); return rc; } static DEVICE_ATTR_RO(active); @@ -163,16 +197,25 @@ static DEVICE_ATTR_RO(active); static ssize_t owned_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct tpm_chip *chip = to_tpm_chip(dev); cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap, + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + + rc = tpm_getcap(chip, TPM_CAP_PROP_OWNER, &cap, "attempting to determine the owner state", sizeof(cap.owned)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } rc = sprintf(buf, "%d\n", cap.owned); +put_ops: + tpm_put_ops(chip); return rc; } static DEVICE_ATTR_RO(owned); @@ -180,16 +223,25 @@ static DEVICE_ATTR_RO(owned); static ssize_t temp_deactivated_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct tpm_chip *chip = to_tpm_chip(dev); cap_t cap; ssize_t rc; - rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap, + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + + rc = tpm_getcap(chip, TPM_CAP_FLAG_VOL, &cap, "attempting to determine the temporary state", sizeof(cap.stclear_flags)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); +put_ops: + tpm_put_ops(chip); return rc; } static DEVICE_ATTR_RO(temp_deactivated); @@ -202,11 +254,18 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, ssize_t rc; char *str = buf; + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap, "attempting to determine the manufacturer", sizeof(cap.manufacturer_id)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } + str += sprintf(str, "Manufacturer: 0x%x\n", be32_to_cpu(cap.manufacturer_id)); @@ -226,8 +285,10 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap, "attempting to determine the 1.1 version", sizeof(cap.tpm_version)); - if (rc) - return 0; + if (rc) { + rc = 0; + goto put_ops; + } str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", cap.tpm_version.Major, @@ -236,7 +297,10 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, cap.tpm_version.revMinor); } - return str - buf; + rc = str - buf; +put_ops: + tpm_put_ops(chip); + return rc; } static DEVICE_ATTR_RO(caps); @@ -244,10 +308,17 @@ static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tpm_chip *chip = to_tpm_chip(dev); + ssize_t rc; + if (chip == NULL) return 0; + rc = tpm_try_get_ops(chip); + if (rc) + return rc; + chip->ops->cancel(chip); + tpm_put_ops(chip); return count; } static DEVICE_ATTR_WO(cancel); @@ -304,16 +375,6 @@ static const struct attribute_group tpm_dev_group = { void tpm_sysfs_add_device(struct tpm_chip *chip) { - /* XXX: If you wish to remove this restriction, you must first update - * tpm_sysfs to explicitly lock chip->ops. - */ - if (chip->flags & TPM_CHIP_FLAG_TPM2) - return; - - /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del - * is called before ops is null'd and the sysfs core synchronizes this - * removal so that no callbacks are running or can run again - */ WARN_ON(chip->groups_cnt != 0); chip->groups[chip->groups_cnt++] = &tpm_dev_group; }