Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp1760884ybz; Sat, 18 Apr 2020 07:57:35 -0700 (PDT) X-Google-Smtp-Source: APiQypKIM5XY7w8TvWALftjCE3ohUWBTo8rjXM5LLvLCrBsHr6ZMzUEgBILCMaHkWYV+NLYYj9ZY X-Received: by 2002:a50:b061:: with SMTP id i88mr7512460edd.325.1587221855547; Sat, 18 Apr 2020 07:57:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1587221855; cv=none; d=google.com; s=arc-20160816; b=ndCp7lVOQsQHhRRcZt8mPUmg0E7ASXs8BFoXgI8bZH4C2/XYxwA3xHqo5xF/lB6C73 L0/WwZERWaMLZAQDHoEZ2MUur+DxEgDElHkzTYtyNn1Qfca6vc2SGEyOF6xBN5QNi0QO zC9qbtcJkzxYg6B+pd+uEHw/j56rtfV9gpKVPFdBP810QSO7uyqSkJsWwS9RnHzuE7Zy A4EwnkPptjaZxzd9tqYCDHLZLLW48MfLpXkz1wd+sAbjpsE/h306fkSDklFavQFWAIoa 85YpGtRIVGb6MJQXfx0pvUoRA6P7WfCgwGSu7wnwjZ3WwJc8+U+lTKFfumGodZxM8jUQ jagQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=h5lRxMwAmcGNCasTDJ5SyLQxgGrRrSSp4Y6OLRTLRow=; b=It34BgKip6Dw1fyBfTX4YwgQRxogtAJI88GccTiE8L2gZQaIZGzI1BwibsQCun4ryl FI1lB7PsfIglkyk5lzhlxo7E0QS6Ve1ltMWu39Rzg24rddQxruJY4hmJEkadeD+/2nQB tMPRkxYQla374E+3Diqt61i17zCz06WZG7mV3Jd3xsO0nQGO6Z5JU0p0GEC4u7uhtZOu M642Qdb23EGLz9XBtCMRH8uJU9/wEOZbzXoLphu/qmzQ760E20gXKSXAQ8X0OtA1mb6r vrXk4Ndeyj2nCOj3y2c8ZXyzbFZT7SYqKCoYJtuXAQqaEScqHGoDr+tIspie1W8MUaU6 iYBw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=1bfIXMn4; 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 k5si16129448ejk.345.2020.04.18.07.57.13; Sat, 18 Apr 2020 07:57:35 -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=default header.b=1bfIXMn4; 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 S1728407AbgDROyb (ORCPT + 99 others); Sat, 18 Apr 2020 10:54:31 -0400 Received: from mail.kernel.org ([198.145.29.99]:50858 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728019AbgDROlh (ORCPT ); Sat, 18 Apr 2020 10:41:37 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B1A2E21974; Sat, 18 Apr 2020 14:41:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1587220896; bh=00ddRN8yKxFktcawj18Tti3yNrlFwEtVI74FidDtGrE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=1bfIXMn4sCYcuaXcIlV30SmUhwZ7Qv8XeZ/XQjWPgE8jwBm2x/D6llPpVjJoKh+XZ Jxgr/C4VgeJNhZ9NUuTr4oq7n6U7yY/pfJ5TitYIjmvgBpJNpq7O/LKlHbWKxoWPJ7 nDcFtWHXj09bBLDfw0aKGlZ+wx3k91vKKm79FF+E= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Nick Bowler , Christoph Hellwig , Sasha Levin , linux-nvme@lists.infradead.org Subject: [PATCH AUTOSEL 5.4 38/78] nvme: fix compat address handling in several ioctls Date: Sat, 18 Apr 2020 10:40:07 -0400 Message-Id: <20200418144047.9013-38-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200418144047.9013-1-sashal@kernel.org> References: <20200418144047.9013-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Nick Bowler [ Upstream commit c95b708d5fa65b4e51f088ee077d127fd5a57b70 ] On a 32-bit kernel, the upper bits of userspace addresses passed via various ioctls are silently ignored by the nvme driver. However on a 64-bit kernel running a compat task, these upper bits are not ignored and are in fact required to be zero for the ioctls to work. Unfortunately, this difference matters. 32-bit smartctl submits the NVME_IOCTL_ADMIN_CMD ioctl with garbage in these upper bits because it seems the pointer value it puts into the nvme_passthru_cmd structure is sign extended. This works fine on 32-bit kernels but fails on a 64-bit one because (at least on my setup) the addresses smartctl uses are consistently above 2G. For example: # smartctl -x /dev/nvme0n1 smartctl 7.1 2019-12-30 r5022 [x86_64-linux-5.5.11] (local build) Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org Read NVMe Identify Controller failed: NVME_IOCTL_ADMIN_CMD: Bad address Since changing 32-bit kernels to actually check all of the submitted address bits now would break existing userspace, this patch fixes the compat problem by explicitly zeroing the upper bits in the compat case. This enables 32-bit smartctl to work on a 64-bit kernel. Signed-off-by: Nick Bowler Signed-off-by: Christoph Hellwig Signed-off-by: Sasha Levin --- drivers/nvme/host/core.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index b8fe42f4b3c5b..f97c48fd3edae 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -1244,6 +1245,18 @@ static void nvme_enable_aen(struct nvme_ctrl *ctrl) queue_work(nvme_wq, &ctrl->async_event_work); } +/* + * Convert integer values from ioctl structures to user pointers, silently + * ignoring the upper bits in the compat case to match behaviour of 32-bit + * kernels. + */ +static void __user *nvme_to_user_ptr(uintptr_t ptrval) +{ + if (in_compat_syscall()) + ptrval = (compat_uptr_t)ptrval; + return (void __user *)ptrval; +} + static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) { struct nvme_user_io io; @@ -1267,7 +1280,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) length = (io.nblocks + 1) << ns->lba_shift; meta_len = (io.nblocks + 1) * ns->ms; - metadata = (void __user *)(uintptr_t)io.metadata; + metadata = nvme_to_user_ptr(io.metadata); if (ns->ext) { length += meta_len; @@ -1290,7 +1303,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) c.rw.appmask = cpu_to_le16(io.appmask); return nvme_submit_user_cmd(ns->queue, &c, - (void __user *)(uintptr_t)io.addr, length, + nvme_to_user_ptr(io.addr), length, metadata, meta_len, lower_32_bits(io.slba), NULL, 0); } @@ -1410,9 +1423,9 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns, effects = nvme_passthru_start(ctrl, ns, cmd.opcode); status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c, - (void __user *)(uintptr_t)cmd.addr, cmd.data_len, - (void __user *)(uintptr_t)cmd.metadata, - cmd.metadata_len, 0, &result, timeout); + nvme_to_user_ptr(cmd.addr), cmd.data_len, + nvme_to_user_ptr(cmd.metadata), cmd.metadata_len, + 0, &result, timeout); nvme_passthru_end(ctrl, effects); if (status >= 0) { @@ -1457,8 +1470,8 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns, effects = nvme_passthru_start(ctrl, ns, cmd.opcode); status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c, - (void __user *)(uintptr_t)cmd.addr, cmd.data_len, - (void __user *)(uintptr_t)cmd.metadata, cmd.metadata_len, + nvme_to_user_ptr(cmd.addr), cmd.data_len, + nvme_to_user_ptr(cmd.metadata), cmd.metadata_len, 0, &cmd.result, timeout); nvme_passthru_end(ctrl, effects); -- 2.20.1