Received: by 10.192.165.156 with SMTP id m28csp46942imm; Tue, 10 Apr 2018 16:06:08 -0700 (PDT) X-Google-Smtp-Source: AIpwx49MHUflDglhEinjVubbWA/f0RUnl80JCPjSm6qK8XKA2LG7TXcAId7US7hsXT7UtAgiKaze X-Received: by 10.98.67.217 with SMTP id l86mr1951725pfi.40.1523401568794; Tue, 10 Apr 2018 16:06:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523401568; cv=none; d=google.com; s=arc-20160816; b=jJ2ObCC2JQMcIYvXiWXsVTE2qLm+WS/42xfCMIYeCp0hVWFGc0hgcBnpfYIXCZDb8n n0aP7O4udkASERFkv+EwkIJ6ufK5XmbyBh3ipjC+h3+WEPcF4gI8vyT9gsKnFJtdfkdU WN/OJAz12sKaNKRUCT2SgYVurGHEFser1JEUnD9t7ghG9AKU33bm0fnIXCjnYcZpf6cw wt7Co6tOzMOorvxyYvoEOfomp83taRTtJJU+3LNGUCjiapdLgSDfhamUuy+cxFHUXgsW rEIO3mfc+414v74uYTKSzyXqXfuz20VU20BrYKm+J0RDRgDSIqTuV9zgniWuPOaIHAxx DHVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=21gzbpCqpAZyV6qkbJv8yGEg1NK2OTG8DUbExni2wb8=; b=ShC1h6wnBtZ5AQrlYaQPe5zPsb31kLO3DZLQmbNx2nE3Jjk1YI5SPjlxy7KzB4ftTO fTl+Ui5wD80d0IvMctrz1HjKZbFS7goBohjM1lsiG+qhEuLSBfLOSrKgOqaJwjUHddo3 03HxnohdXx2Cr1dTA7PyGq3Yv7PX9VZyqdua3eYWxvV88HQVx0++zVqnEbKkXLeZ9xmZ f9F3Ok5pK6psBZiacey9L/AggMsUh3N4T+Y6w3KU15LfQlPkrWyGssK1efEv1+DlB8TW PDafa/Z5YWVvHH+EY/5hAlR2fgsWV8GLhnJPFABi47IuEnQV05RfZf3L8qMIaHfTlN+f w8Hg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 97-v6si3791801plc.713.2018.04.10.16.05.31; Tue, 10 Apr 2018 16:06:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755573AbeDJWfg (ORCPT + 99 others); Tue, 10 Apr 2018 18:35:36 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:42194 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932266AbeDJWfe (ORCPT ); Tue, 10 Apr 2018 18:35:34 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id BB0B5DDF; Tue, 10 Apr 2018 22:35:33 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jason Gunthorpe , Javier Martinez Canillas , William Roberts , Philip Tricca , Jarkko Sakkinen , Sasha Levin Subject: [PATCH 4.14 045/138] tpm: return a TPM_RC_COMMAND_CODE response if command is not implemented Date: Wed, 11 Apr 2018 00:23:55 +0200 Message-Id: <20180410212907.338094843@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180410212902.121524696@linuxfoundation.org> References: <20180410212902.121524696@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Javier Martinez Canillas [ Upstream commit 095531f891e627e408606f2da4008d3d53e6748a ] According to the TPM Library Specification, a TPM device must do a command header validation before processing and return a TPM_RC_COMMAND_CODE code if the command is not implemented. So user-space will expect to handle that response as an error. But if the in-kernel resource manager is used (/dev/tpmrm?), an -EINVAL errno code is returned instead if the command isn't implemented. This confuses userspace since it doesn't expect that error value. This also isn't consistent with the behavior when not using TPM spaces and accessing the TPM directly (/dev/tpm?). In this case, the command is sent to the TPM even when not implemented and the TPM responds with an error. Instead of returning an -EINVAL errno code when the tpm_validate_command() function fails, synthesize a TPM command response so user-space can get a TPM_RC_COMMAND_CODE as expected when a chip doesn't implement the command. The TPM only sets 12 of the 32 bits in the TPM_RC response, so the TSS and TAB specifications define that higher layers in the stack should use some of the unused 20 bits to specify from which level of the stack the error is coming from. Since the TPM_RC_COMMAND_CODE response code is sent by the kernel resource manager, set the error level to the TAB/RM layer so user-space is aware of this. Suggested-by: Jason Gunthorpe Signed-off-by: Javier Martinez Canillas Reviewed-by: William Roberts Reviewed-by: Philip Tricca Reviewed-by: Jarkko Sakkinen Tested-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-interface.c | 28 ++++++++++++++++++++-------- drivers/char/tpm/tpm.h | 5 +++++ 2 files changed, 25 insertions(+), 8 deletions(-) --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -328,7 +328,7 @@ unsigned long tpm_calc_ordinal_duration( } EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); -static bool tpm_validate_command(struct tpm_chip *chip, +static int tpm_validate_command(struct tpm_chip *chip, struct tpm_space *space, const u8 *cmd, size_t len) @@ -340,10 +340,10 @@ static bool tpm_validate_command(struct unsigned int nr_handles; if (len < TPM_HEADER_SIZE) - return false; + return -EINVAL; if (!space) - return true; + return 0; if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) { cc = be32_to_cpu(header->ordinal); @@ -352,7 +352,7 @@ static bool tpm_validate_command(struct if (i < 0) { dev_dbg(&chip->dev, "0x%04X is an invalid command\n", cc); - return false; + return -EOPNOTSUPP; } attrs = chip->cc_attrs_tbl[i]; @@ -362,11 +362,11 @@ static bool tpm_validate_command(struct goto err_len; } - return true; + return 0; err_len: dev_dbg(&chip->dev, "%s: insufficient command length %zu", __func__, len); - return false; + return -EINVAL; } /** @@ -391,8 +391,20 @@ ssize_t tpm_transmit(struct tpm_chip *ch unsigned long stop; bool need_locality; - if (!tpm_validate_command(chip, space, buf, bufsiz)) - return -EINVAL; + rc = tpm_validate_command(chip, space, buf, bufsiz); + if (rc == -EINVAL) + return rc; + /* + * If the command is not implemented by the TPM, synthesize a + * response with a TPM2_RC_COMMAND_CODE return for user-space. + */ + if (rc == -EOPNOTSUPP) { + header->length = cpu_to_be32(sizeof(*header)); + header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); + header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | + TSS2_RESMGR_TPM_RC_LAYER); + return bufsiz; + } if (bufsiz > TPM_BUFSIZE) bufsiz = TPM_BUFSIZE; --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -93,12 +93,17 @@ enum tpm2_structures { TPM2_ST_SESSIONS = 0x8002, }; +/* Indicates from what layer of the software stack the error comes from */ +#define TSS2_RC_LAYER_SHIFT 16 +#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) + enum tpm2_return_codes { TPM2_RC_SUCCESS = 0x0000, TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ TPM2_RC_HANDLE = 0x008B, TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ TPM2_RC_DISABLED = 0x0120, + TPM2_RC_COMMAND_CODE = 0x0143, TPM2_RC_TESTING = 0x090A, /* RC_WARN */ TPM2_RC_REFERENCE_H0 = 0x0910, };