From patchwork Sat Oct 7 04:59:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Limonciello, Mario" X-Patchwork-Id: 9991153 X-Patchwork-Delegate: dvhart@infradead.org 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 812F760231 for ; Sat, 7 Oct 2017 05:01:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 744D328D31 for ; Sat, 7 Oct 2017 05:01:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6939D28D39; Sat, 7 Oct 2017 05:01:26 +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=unavailable 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 0AF2028D31 for ; Sat, 7 Oct 2017 05:01:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753173AbdJGFBA (ORCPT ); Sat, 7 Oct 2017 01:01:00 -0400 Received: from esa4.dell-outbound.iphmx.com ([68.232.149.214]:39160 "EHLO esa4.dell-outbound.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751431AbdJGFAS (ORCPT ); Sat, 7 Oct 2017 01:00:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=dell.com; i=@dell.com; q=dns/txt; s=smtpout; t=1507352418; x=1538888418; h=from:to:cc:subject:date:message-id; bh=n6EorLhEpbPuGQ8DaTAERCA2xHM/WmRkrTtHSqDHCto=; b=F1KsKrREa6tvizrvwvPPLY86kUUhMmexiP3A6MEUgwOMDUFkRT68O8sP 27XMkfAvph1Ls9HaWkTc8EhRZE1gLB1iWJrrugGEdEbUol9crUD4w4+ro 13ZGouvTuBMH+00BXF5Enx8+5XXbPFKOSQErJcYQh++BTtTZ9ta+GBSQZ o=; Received: from esa4.dell-outbound2.iphmx.com ([68.232.154.98]) by esa4.dell-outbound.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Oct 2017 00:00:17 -0500 Received: from ausxipps306.us.dell.com ([143.166.148.156]) by esa4.dell-outbound2.iphmx.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Oct 2017 11:00:16 +0600 X-LoopCount0: from 10.208.86.39 X-IronPort-AV: E=Sophos;i="5.42,487,1500958800"; d="scan'208";a="156909674" X-DLP: DLP_GlobalPCIDSS From: Mario Limonciello To: dvhart@infradead.org, Andy Shevchenko Cc: LKML , platform-driver-x86@vger.kernel.org, Andy Lutomirski , quasisec@google.com, pali.rohar@gmail.com, rjw@rjwysocki.net, mjg59@google.com, hch@lst.de, Greg KH , Mario Limonciello Subject: [PATCH v5 10/14] platform/x86: dell-smbios: add filtering capability for requests Date: Fri, 6 Oct 2017 23:59:54 -0500 Message-Id: <169beca316d562d00dc3dfb45248f42c9dc5d368.1507350554.git.mario.limonciello@dell.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP There are some categories of tokens and SMBIOS calls that it makes sense to protect userspace from accessing. These are calls that may write to one time use fields or activate hardware debugging capabilities. They are not intended for general purpose use. This same functionality may be be later extended to also intercept calls that may cause kernel functionality to get out of sync if the same functions are used by other drivers. Signed-off-by: Mario Limonciello --- drivers/platform/x86/dell-smbios.c | 76 ++++++++++++++++++++++++++++++++++++++ drivers/platform/x86/dell-smbios.h | 2 + 2 files changed, 78 insertions(+) diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c index 2f90ba5346bc..d1908f159be3 100644 --- a/drivers/platform/x86/dell-smbios.c +++ b/drivers/platform/x86/dell-smbios.c @@ -32,6 +32,7 @@ struct calling_interface_structure { struct calling_interface_token tokens[]; } __packed; +static u32 da_supported_commands; static int da_command_address; static int da_command_code; static int da_num_tokens; @@ -45,6 +46,14 @@ struct smbios_device { int (*call_fn)(struct calling_interface_buffer *); }; +static u32 token_black[] = { + 0x0175, 0x0176, 0x0195, 0x0196, 0x0197, 0x01DC, 0x01DD, 0x027D, 0x027E, + 0x027F, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x02E3, 0x02FF, 0x0300, + 0x0301, 0x0302, 0x0325, 0x0326, 0x0332, 0x0333, 0x0334, 0x0335, 0x0350, + 0x0363, 0x0368, 0x03F6, 0x03F7, 0x049E, 0x049F, 0x04A0, 0x04A1, 0x04A2, + 0x04A3, 0x04E6, 0x04E7, 0x9000, 0x9001 +}; + static LIST_HEAD(smbios_device_list); void dell_smbios_get_smm_address(int *address, int *code) @@ -104,6 +113,65 @@ void dell_smbios_unregister_device(struct device *d) } EXPORT_SYMBOL_GPL(dell_smbios_unregister_device); +int dell_smbios_call_filter(struct device *d, + struct calling_interface_buffer *buffer) +{ + int i; + int j; + u32 t; + + /* can't make calls over 30 */ + if (buffer->class > 30) { + dev_dbg(d, "buffer->class too big: %d\n", buffer->class); + return -EINVAL; + } + + /* supported calls on the particular system */ + if (!(da_supported_commands & (1 << buffer->class))) { + dev_dbg(d, "invalid command, supported commands: 0x%8x\n", + da_supported_commands); + return -EINVAL; + } + + /* diagonstics, debugging information or write once */ + if ((buffer->class == 01 && buffer->select == 07) || + (buffer->class == 06 && buffer->select == 05) || + (buffer->class == 11 && buffer->select == 03) || + (buffer->class == 11 && buffer->select == 07) || + (buffer->class == 11 && buffer->select == 11) || + buffer->class == 19) { + dev_dbg(d, "blacklisted command: %d/%d\n", + buffer->class, buffer->select); + return -EINVAL; + } + + /* reading/writing tokens*/ + if ((buffer->class == 0 && buffer->select < 3) || + (buffer->class == 1 && buffer->select < 3)) { + for (i = 0; i < da_num_tokens; i++) { + if (da_tokens[i].location != buffer->input[0]) + continue; + /*blacklist reading and writing these */ + t = da_tokens[i].tokenID; + if ((t >= 0x4000 && t <= 0x7FFF) || + (t >= 0xA000 && t <= 0xBFFF) || + (t >= 0xEFF0 && t <= 0xEFFF)) + return -EINVAL; + for (j = 0; j < ARRAY_SIZE(token_black); j++) + if (t == token_black[j]) + return -EINVAL; + /* token exists and is OK */ + return 0; + } + /* token didn't exist */ + dev_dbg(d, "token at location %u doesn't exist\n", + buffer->input[0]); + return -EINVAL; + } + return 0; +} +EXPORT_SYMBOL_GPL(dell_smbios_call_filter); + int dell_smbios_call(struct calling_interface_buffer *buffer) { int (*call_fn)(struct calling_interface_buffer *) = NULL; @@ -127,6 +195,13 @@ int dell_smbios_call(struct calling_interface_buffer *buffer) goto out_smbios_call; } + if (dell_smbios_call_filter(selected_dev, buffer)) { + ret = -EINVAL; + dev_err(selected_dev, "Invalid call %d/%d:%8x\n", + buffer->class, buffer->select, buffer->input[0]); + goto out_smbios_call; + } + ret = call_fn(buffer); out_smbios_call: @@ -184,6 +259,7 @@ static void __init parse_da_table(const struct dmi_header *dm) da_command_address = table->cmdIOAddress; da_command_code = table->cmdIOCode; + da_supported_commands = table->supportedCmds; new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) * sizeof(struct calling_interface_token), diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h index fe28964da499..c743c58831e5 100644 --- a/drivers/platform/x86/dell-smbios.h +++ b/drivers/platform/x86/dell-smbios.h @@ -45,6 +45,8 @@ void dell_smbios_unregister_device(struct device *d); void dell_smbios_get_smm_address(int *address, int *command); int dell_smbios_error(int value); +int dell_smbios_call_filter(struct device *d, + struct calling_interface_buffer *buffer); int dell_smbios_call(struct calling_interface_buffer *buffer); struct calling_interface_token *dell_smbios_find_token(int tokenid);