From patchwork Thu Nov 16 21:25:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 10062115 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 DF7A96023A for ; Thu, 16 Nov 2017 21:25:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BCC622A753 for ; Thu, 16 Nov 2017 21:25:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B025F2AB1D; Thu, 16 Nov 2017 21:25:09 +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 AE8862A753 for ; Thu, 16 Nov 2017 21:25:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758755AbdKPVZI (ORCPT ); Thu, 16 Nov 2017 16:25:08 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:44916 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751840AbdKPVZG (ORCPT ); Thu, 16 Nov 2017 16:25:06 -0500 Received: by mail-pg0-f68.google.com with SMTP id c123so284517pga.11; Thu, 16 Nov 2017 13:25:06 -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=2+hv35Mmn8fAIL79SAAbkntD0gPyD0F2KCr9d15Citc=; b=iTwvB1dKMkguTHdETCnPv49lfwkTm3oSaZKC5c9kT7tvE4/KOKCfV7JZhSE2nZEQ0x sYfHHkPidd4UGXAxuSKehvLbwWfHlhK6lyr/QJ1+RKtxeSZYzJp88zYilXWQS9UrIlaH foR7C726lbBTRcoskTpcKRFCM3wY69IaFkEPHyMLXC7kWs14rTMeEqOHsuAbT1C+ua0N 54wr6v1cmyi7W0gi9rJg7byDk458FbKLEoAdVAxAE2rwvpiBytev4xleJOkXjCJ8wap1 4GruNcGFernmGpNisqOlu8NNpvxaLtzGK6Gwx7JM8ZgpKFDxb0sQfA9BMz2xY1FsHMJu FrJw== 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=2+hv35Mmn8fAIL79SAAbkntD0gPyD0F2KCr9d15Citc=; b=pzEGSmNybw7ZftXiK+tEvXw4M5w6j9Qu1/sW3RJR4FH+74iB12IwE+IrvFDdB6Jrwf orJGfLCT2/1KKgS1oRAaDTYaaqNg2egjxNfSApSgg1T+nOXYFIfnHpD6wsm09A6OUVzo H2D0M6FFea4LKmieEeu9NutbtiVT94wFEWHFaDfsDePO0k36DEgGWfEqnsrzzsHFtQDP j2AQsSyr6N7VfbMpFp0DIg4QLRC6dEL4ltra+y59/VE6Ymgb4Gj3OryTq8WCquYBqi1F 5X04UiWsLu+IPrHDpK+7yTDSzp98yyOl2E3LU7nu16Y0XkAq9Vq+uYNvM9BWuRSj1beb LEfg== X-Gm-Message-State: AJaThX5bSyZWf1qgky9V4A4jjXY6GHcxihVKrFpuX6+2wu5VEWn1XatD D8SNntdLy+B/croFyxUAFEw= X-Google-Smtp-Source: AGs4zMYQs6qI6lw95+/w2RahLbcAd0F9jc4IaZtGGTwutW0XZY/JE8WP8xfxKqGSvRn9GMbRDDQHgA== X-Received: by 10.99.119.73 with SMTP id s70mr2896163pgc.451.1510867506193; Thu, 16 Nov 2017 13:25:06 -0800 (PST) Received: from localhost (108-223-40-66.lightspeed.sntcca.sbcglobal.net. [108.223.40.66]) by smtp.gmail.com with ESMTPSA id k89sm4297491pfb.104.2017.11.16.13.25.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Nov 2017 13:25:03 -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] tpm: Add explicit chip->ops locking for sysfs attributes. Date: Thu, 16 Nov 2017 13:25:01 -0800 Message-Id: <1510867501-9498-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 --- drivers/char/tpm/tpm-chip.c | 4 -- drivers/char/tpm/tpm-sysfs.c | 125 ++++++++++++++++++++++++++++++++----------- 2 files changed, 93 insertions(+), 36 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..292d5bbf79a8 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; + 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; }