Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp206416pxb; Mon, 25 Oct 2021 06:47:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwJNw22Spqqo+ZJH7v/Flcq7zvyW1liqlBU1ZCcweNGhiFSp0kLf0HorakSP+DD/BgOQ8Yt X-Received: by 2002:a17:906:48ce:: with SMTP id d14mr23047693ejt.336.1635169625887; Mon, 25 Oct 2021 06:47:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635169625; cv=none; d=google.com; s=arc-20160816; b=oDlzdebZzFGLn09OBFOMjHM+EhPfB8iN4FON2/NrGimnyjOUY6B8p8BwrFsUGmleJh CR61Lk/PJ3Cch1jCM4fFL4AB+B8JSEO+5choohw6HOb6xnoQsohfG/21jhh0TCXrFH+L i7lNjtSYmWn38650HzBjVo4zzO8/nDxSUDXN8HKM0jezxpkjJgTRzgllzVnE1MLgLZ7B OgE3h7r106OpNV8VW7iyBy/o7dPUvokGPP8QA+JACUB7+ra1d0m2wfvRnqSZnH3JQ1u+ cmQ+P9UhUz8SFLQfHQNX8fHnSen0uRgZe7vlg+vGOrJ5tJXMb5hTXu7Ez07b/uhavyRG ul0Q== 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 :dkim-signature; bh=D9+ZX1xr8qmPLXdw61Fvpfe7B7BTK1qkSP1UfzvitE0=; b=vo5HJ/4LfOpbDmoFKW0IwhRSFqSVOmf2l4fKmCLgSeYodYJAI56ZAhD5/pGsI1W9B0 LOWYmnQ4Az+44Dx2brtx7LEQaFLYBJSpknmBEzvSnxzinDA3nc18j9Ok4H5ci9SsPjeS RitUzPspyPWrgBJAT5F1X+nFwX24I6H/eemNAf/FBbN0KgL0cbx5JI9FXrMToOCoi9q2 wvthaBMePpN9fDH134EXEQk0thWKcv1/SD8+ZvPesBSkogjqGEAys3Lqahs2x0zCvmmX PJ62VY9R5dgyJy4F1ELZZ+iFUIWohCHTTnkBd4ecD6IZletcKqYSpCbAJ42yh5Sx06g9 xhLg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="g/++Infa"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u19si2443190edo.288.2021.10.25.06.46.42; Mon, 25 Oct 2021 06:47:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="g/++Infa"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232829AbhJYLs5 (ORCPT + 99 others); Mon, 25 Oct 2021 07:48:57 -0400 Received: from mail.kernel.org ([198.145.29.99]:39188 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233244AbhJYLsn (ORCPT ); Mon, 25 Oct 2021 07:48:43 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7BBB861040; Mon, 25 Oct 2021 11:46:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1635162381; bh=C6b6shzhRQx1x+0AH40ydkjoZdICJyhayKRWOP2YLnA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g/++InfaFv2Agba1fI6fsz7SMriqU/xMfqpXpelu/zgLmNiLQN7vHR8ipHAyikUv8 8VEhBiC33AwOlFF1jIirj6Jat/mYbZPIwIIJ0LG2TlnXUJ0uZA48GobAQ1nPeyr8Rj QINwcd3VDgh2Z2FOLcfBRxhwSufCyR9zHl43JqYmQS3LQ6rDE459LXdJ4HvukAABBG WmgJ71jdDASRiA6N+nAR+Hpl2YlbqMo5bqFUBfd4QMSY9S3TiO3ISznvm5uRWcnL5K 8Zsoh5QEFkwj2BtodIrJbWBRHJJD9CKTc+ENxBsWD66Ek/x7I2vYQFO9HYILryYjKi MlhVPQE76/pBg== Received: from johan by xi.lan with local (Exim 4.94.2) (envelope-from ) id 1meyQW-0001DF-7e; Mon, 25 Oct 2021 13:46:04 +0200 From: Johan Hovold To: Ian Abbott , H Hartley Sweeten Cc: Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Johan Hovold , stable@vger.kernel.org Subject: [PATCH 2/5] comedi: dt9812: fix DMA buffers on stack Date: Mon, 25 Oct 2021 13:45:29 +0200 Message-Id: <20211025114532.4599-3-johan@kernel.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20211025114532.4599-1-johan@kernel.org> References: <20211025114532.4599-1-johan@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org USB transfer buffers are typically mapped for DMA and must not be allocated on the stack or transfers will fail. Allocate proper transfer buffers in the various command helpers and return an error on short transfers instead of acting on random stack data. Note that this also fixes a stack info leak on systems where DMA is not used as 32 bytes are always sent to the device regardless of how short the command is. Fixes: 63274cd7d38a ("Staging: comedi: add usb dt9812 driver") Cc: stable@vger.kernel.org # 2.6.29 Signed-off-by: Johan Hovold --- drivers/comedi/drivers/dt9812.c | 109 ++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/drivers/comedi/drivers/dt9812.c b/drivers/comedi/drivers/dt9812.c index 634f57730c1e..f15c306f2d06 100644 --- a/drivers/comedi/drivers/dt9812.c +++ b/drivers/comedi/drivers/dt9812.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "../comedi_usb.h" @@ -237,22 +238,41 @@ static int dt9812_read_info(struct comedi_device *dev, { struct usb_device *usb = comedi_to_usb_dev(dev); struct dt9812_private *devpriv = dev->private; - struct dt9812_usb_cmd cmd; + struct dt9812_usb_cmd *cmd; int count, ret; + u8 *tbuf; - cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA); - cmd.u.flash_data_info.address = + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->cmd = cpu_to_le32(DT9812_R_FLASH_DATA); + cmd->u.flash_data_info.address = cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset); - cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size); + cmd->u.flash_data_info.numbytes = cpu_to_le16(buf_size); /* DT9812 only responds to 32 byte writes!! */ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), - &cmd, 32, &count, DT9812_USB_TIMEOUT); + cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + kfree(cmd); if (ret) return ret; - return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), - buf, buf_size, &count, DT9812_USB_TIMEOUT); + tbuf = kmalloc(buf_size, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), + tbuf, buf_size, &count, DT9812_USB_TIMEOUT); + if (!ret) { + if (count == buf_size) + memcpy(buf, tbuf, buf_size); + else + ret = -EREMOTEIO; + } + kfree(tbuf); + + return ret; } static int dt9812_read_multiple_registers(struct comedi_device *dev, @@ -261,22 +281,41 @@ static int dt9812_read_multiple_registers(struct comedi_device *dev, { struct usb_device *usb = comedi_to_usb_dev(dev); struct dt9812_private *devpriv = dev->private; - struct dt9812_usb_cmd cmd; + struct dt9812_usb_cmd *cmd; int i, count, ret; + u8 *buf; - cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); - cmd.u.read_multi_info.count = reg_count; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + cmd->cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG); + cmd->u.read_multi_info.count = reg_count; for (i = 0; i < reg_count; i++) - cmd.u.read_multi_info.address[i] = address[i]; + cmd->u.read_multi_info.address[i] = address[i]; /* DT9812 only responds to 32 byte writes!! */ ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), - &cmd, 32, &count, DT9812_USB_TIMEOUT); + cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + kfree(cmd); if (ret) return ret; - return usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), - value, reg_count, &count, DT9812_USB_TIMEOUT); + buf = kmalloc(reg_count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, devpriv->cmd_rd.addr), + buf, reg_count, &count, DT9812_USB_TIMEOUT); + if (!ret) { + if (count == reg_count) + memcpy(value, buf, reg_count); + else + ret = -EREMOTEIO; + } + kfree(buf); + + return ret; } static int dt9812_write_multiple_registers(struct comedi_device *dev, @@ -285,19 +324,27 @@ static int dt9812_write_multiple_registers(struct comedi_device *dev, { struct usb_device *usb = comedi_to_usb_dev(dev); struct dt9812_private *devpriv = dev->private; - struct dt9812_usb_cmd cmd; + struct dt9812_usb_cmd *cmd; int i, count; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; - cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); - cmd.u.read_multi_info.count = reg_count; + cmd->cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG); + cmd->u.read_multi_info.count = reg_count; for (i = 0; i < reg_count; i++) { - cmd.u.write_multi_info.write[i].address = address[i]; - cmd.u.write_multi_info.write[i].value = value[i]; + cmd->u.write_multi_info.write[i].address = address[i]; + cmd->u.write_multi_info.write[i].value = value[i]; } /* DT9812 only responds to 32 byte writes!! */ - return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), - &cmd, 32, &count, DT9812_USB_TIMEOUT); + ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), + cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + kfree(cmd); + + return ret; } static int dt9812_rmw_multiple_registers(struct comedi_device *dev, @@ -306,17 +353,25 @@ static int dt9812_rmw_multiple_registers(struct comedi_device *dev, { struct usb_device *usb = comedi_to_usb_dev(dev); struct dt9812_private *devpriv = dev->private; - struct dt9812_usb_cmd cmd; + struct dt9812_usb_cmd *cmd; int i, count; + int ret; + + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; - cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); - cmd.u.rmw_multi_info.count = reg_count; + cmd->cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG); + cmd->u.rmw_multi_info.count = reg_count; for (i = 0; i < reg_count; i++) - cmd.u.rmw_multi_info.rmw[i] = rmw[i]; + cmd->u.rmw_multi_info.rmw[i] = rmw[i]; /* DT9812 only responds to 32 byte writes!! */ - return usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), - &cmd, 32, &count, DT9812_USB_TIMEOUT); + ret = usb_bulk_msg(usb, usb_sndbulkpipe(usb, devpriv->cmd_wr.addr), + cmd, sizeof(*cmd), &count, DT9812_USB_TIMEOUT); + kfree(cmd); + + return ret; } static int dt9812_digital_in(struct comedi_device *dev, u8 *bits) -- 2.32.0