Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp3362043iob; Mon, 16 May 2022 20:41:41 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyQh/0M2YlvOT2QG+pNzW6msX0dWb/lGic/p//AKEQKFzObsA2AoFky8gFxS+8ytHBsMbO3 X-Received: by 2002:a17:907:6297:b0:6da:6388:dc58 with SMTP id nd23-20020a170907629700b006da6388dc58mr18187685ejc.472.1652758901466; Mon, 16 May 2022 20:41:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652758901; cv=none; d=google.com; s=arc-20160816; b=IiBoLEffMFjLte2Y9hlEKECb6YmG3JYoZJCkorxZtrJFEVoJthSdoPbGzlZD3w9KZT Z4L0fjIATz7l/RzhkOQvp2wb6Uil072j7/9OSDZ0VnKr6IFyhE6wdmJ6VW1Gomm9AsHO B2hB34tn6H3q/nEG6NaNEZ4nxWCeEK1HILnsKzzknmcttqck3mdTPCVdQcWEEmi5fU19 7qSYplZzPZi1/FEFMUa/4YILEhgu1c8VqIF0HvyA3t5njbNhwuVl+VOiLZygJDsivUDP nmL4RSxwPRJQqKiUQYb3qv+2bJujkGOXqZOW2pE+XqR0XN6bV0xjZd8Ab6SoXxXIcGcX nGhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=ZaFpGdNisOZZJtso2K/tn0KocBYbsJdGI/k71bPUs7I=; b=IH8bsuh+jztheR0KVkAaxGRz0arhsd0EZt9BYk8mct3r6vEQLYoWADslROX4Xxg2RP huVtLyKwN1bFMXk5i2kr3Pms4+btCPUr8FDlYop1uIBqk75+NVaD/n4cdxYPISh9ZspG 2OpPKKmikaY7Ghbooo33yGoOqYWD9F4cqxxsxJVIgfy2Fks16V5HP4nPoC2og7M35xVG Lg+IKEuMrcqdH3OkNOQ3L1dBdf1d4NdotY5jcvjt+i3guiRVlKHTmLLF0rlIIdwYJBym ZD40y0xdPWeM5Lnlvz1Er8AEEpTsxb3wcSVHQWcV3JF3Yv4/6uIJS6pHRZUivyl75t7s aIpQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=bitwise.fi Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id dm16-20020a170907949000b006e8310f72e9si1271690ejc.653.2022.05.16.20.41.16; Mon, 16 May 2022 20:41:41 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=bitwise.fi Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244046AbiEPN5b (ORCPT + 99 others); Mon, 16 May 2022 09:57:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237808AbiEPNyz (ORCPT ); Mon, 16 May 2022 09:54:55 -0400 Received: from mail.bitwise.fi (mail.bitwise.fi [109.204.228.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7AFB73915D; Mon, 16 May 2022 06:54:40 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by mail.bitwise.fi (Postfix) with ESMTP id BA982460028; Mon, 16 May 2022 16:48:59 +0300 (EEST) X-Virus-Scanned: Debian amavisd-new at Received: from mail.bitwise.fi ([127.0.0.1]) by localhost (mustetatti.dmz.bitwise.fi [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id mcG4Um4CIPgK; Mon, 16 May 2022 16:48:57 +0300 (EEST) Received: from localhost.net (fw1.dmz.bitwise.fi [192.168.69.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: anssiha) by mail.bitwise.fi (Postfix) with ESMTPSA id F214B46001C; Mon, 16 May 2022 16:48:56 +0300 (EEST) From: Anssi Hannula To: Jimmy Assarsson Cc: linux-can@vger.kernel.org, Marc Kleine-Budde , linux-kernel@vger.kernel.org Subject: [PATCH 01/12] can: kvaser_usb_leaf: Fix overread with an invalid command Date: Mon, 16 May 2022 16:47:37 +0300 Message-Id: <20220516134748.3724796-2-anssi.hannula@bitwise.fi> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220516134748.3724796-1-anssi.hannula@bitwise.fi> References: <20220516134748.3724796-1-anssi.hannula@bitwise.fi> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org For command events read from the device, kvaser_usb_leaf_read_bulk_callback() verifies that cmd->len does not exceed the size of the received data, but the actual kvaser_cmd handlers will happily read any kvaser_cmd fields without checking for cmd->len. This can cause an overread if the last cmd in the buffer is shorter than expected for the command type (with cmd->len showing the actual short size). Maximum overread seems to be 22 bytes (CMD_LEAF_LOG_MESSAGE), some of which are delivered to userspace as-is. Fix that by verifying the length of command before handling it. This issue can only occur after RX URBs have been set up, i.e. the interface has been opened at least once. Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") Signed-off-by: Anssi Hannula --- A simpler option would be to just zero-pad the data into a stack-allocated struct kvaser_cmd without knowledge of the needed minimum size (so no tables needed), though that would mean incomplete commands would get passed on silently. .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index c805b999c543..d9f40b9702a5 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -320,6 +320,38 @@ struct kvaser_cmd { } u; } __packed; +#define CMD_SIZE_ANY 0xff +#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field) + +static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple), + [CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple), + [CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo), + [CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header), + [CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.leaf.softinfo), + [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.leaf.rx_can), + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can), + [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, +}; + +static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { + [CMD_START_CHIP_REPLY] = kvaser_fsize(u.simple), + [CMD_STOP_CHIP_REPLY] = kvaser_fsize(u.simple), + [CMD_GET_CARD_INFO_REPLY] = kvaser_fsize(u.cardinfo), + [CMD_TX_ACKNOWLEDGE] = kvaser_fsize(u.tx_acknowledge_header), + [CMD_GET_SOFTWARE_INFO_REPLY] = kvaser_fsize(u.usbcan.softinfo), + [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), + /* ignored events: */ + [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, +}; + /* Summary of a kvaser error event, for a unified Leaf/Usbcan error * handling. Some discrepancies between the two families exist: * @@ -387,6 +419,43 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { .bittiming_const = &kvaser_usb_leaf_bittiming_const, }; +static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) +{ + /* buffer size >= cmd->len ensured by caller */ + u8 min_size = 0; + + switch (dev->card_data.leaf.family) { + case KVASER_LEAF: + if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf)) + min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id]; + break; + case KVASER_USBCAN: + if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan)) + min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id]; + break; + } + + if (min_size == CMD_SIZE_ANY) + return 0; + + if (min_size) { + min_size += CMD_HEADER_LEN; + if (cmd->len >= min_size) + return 0; + + dev_err_ratelimited(&dev->intf->dev, + "Received command %u too short (size %u, needed %u)", + cmd->id, cmd->len, min_size); + return -EIO; + } + + dev_warn_ratelimited(&dev->intf->dev, + "Unhandled command (%d, size %d)\n", + cmd->id, cmd->len); + return -EINVAL; +} + static void * kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, const struct sk_buff *skb, int *cmd_len, @@ -492,6 +561,9 @@ static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, end: kfree(buf); + if (err == 0) + err = kvaser_usb_leaf_verify_size(dev, cmd); + return err; } @@ -1113,6 +1185,9 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, const struct kvaser_cmd *cmd) { + if (kvaser_usb_leaf_verify_size(dev, cmd) < 0) + return; + switch (cmd->id) { case CMD_START_CHIP_REPLY: kvaser_usb_leaf_start_chip_reply(dev, cmd); -- 2.34.1