From patchwork Tue May 23 00:14:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Osipenko X-Patchwork-Id: 9741667 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 D985C60210 for ; Tue, 23 May 2017 01:03:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CF0C82864A for ; Tue, 23 May 2017 01:03:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C3F292868D; Tue, 23 May 2017 01:03:02 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3F03E2864A for ; Tue, 23 May 2017 01:03:02 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2676589CCB; Tue, 23 May 2017 01:01:28 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf0-x241.google.com (mail-lf0-x241.google.com [IPv6:2a00:1450:4010:c07::241]) by gabe.freedesktop.org (Postfix) with ESMTPS id B282189C1C for ; Tue, 23 May 2017 00:15:20 +0000 (UTC) Received: by mail-lf0-x241.google.com with SMTP id m18so6671166lfj.0 for ; Mon, 22 May 2017 17:15:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=NGYvT3Ai9T1vbv1jtQQXSFLS3JbgN+GGhdAwoMtzvGY=; b=oqBsOqRy1FmJMNSRCazwPwbjbDcYEEbjvokZpBxgtI/6nkv0az00wgV8L4kG+Jznmx Y2tltf0WbuzkVmB4Khj9cGg1HfT+gdsVixDmvoWV1sjDiCqWVNb87nwjOzVUJODpn3km 3zmCm4MaN1eGu5RcgLoSFlT1/k4dqNUTj39zUFcM+CaOB21iMqGbEIyWrt7B1xCulKKm OMnINu0/R9Iyd+EzyYvfqLiz7xuuFwLcm05Ofdi/tB3OSxQXAWIrzpcJFs36wL7Qlzrt xJvZrb3RGDHX0Hnsdp3ZSiznxgerzMC/0JaFGSiL5WdToZJ9NRsS79Ec37UR/YBtdN6a aMYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=NGYvT3Ai9T1vbv1jtQQXSFLS3JbgN+GGhdAwoMtzvGY=; b=sWsf1641zNu4hYkKC6IEFm70RfsFVluWoI96pswqENc5OfMNMLSnuXYJcaXjnbK+WT 5nMKtziIJ5MeVNPTLahJ2OAVnG0WuiqkptmNdqV+Qr56lLpKCHy0AajDiiJS3ZFaIz27 PY2AHa6LL8malSiQzttoBnvNFnKTT3unbzjxjAZWBG1krPft7xhB6tAxbx6mdUVta1UR 9kOq7ylfMqzRvhugF03DONXfj8iMJuC14lldhqFp6sxhRCMFIQFsr2jgVEPgQxY8TYzv 677E1AnjCaMt/Jrn9Ls+Ir6YDqWAYeEZDteaQrpq8BJ9IvxwMNJDnYEapmt/9CFb8huD Rmgw== X-Gm-Message-State: AODbwcDz40fnq7SyRrNA/J9WOMncidTcyhHkwoRSqRWOV2sRR+r4YEBF 5Wh4VY2SGNclfQ== X-Received: by 10.25.99.28 with SMTP id x28mr6186671lfb.59.1495498519104; Mon, 22 May 2017 17:15:19 -0700 (PDT) Received: from localhost.localdomain (ppp109-252-91-175.pppoe.spdop.ru. [109.252.91.175]) by smtp.gmail.com with ESMTPSA id v30sm3440904ljd.9.2017.05.22.17.15.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 22 May 2017 17:15:18 -0700 (PDT) From: Dmitry Osipenko To: Thierry Reding , Mikko Perttunen Subject: [PATCH 04/22] drm/tegra: Check for malformed offsets and sizes in the 'submit' IOCTL Date: Tue, 23 May 2017 03:14:19 +0300 Message-Id: <801e3023e6fe11744c7e675ca7b9c5890e3210f2.1495498184.git.digetx@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: References: In-Reply-To: References: X-Mailman-Approved-At: Tue, 23 May 2017 00:59:38 +0000 Cc: linux-tegra@vger.kernel.org, DRI Development X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP If commands buffer claims a number of words that is higher than its BO can fit, a kernel OOPS will be fired on the out-of-bounds BO access. This was triggered by an opentegra Xorg driver that erroneously pushed too many commands to the pushbuf. The CMDA commands buffer address is 4 bytes aligned, so check its alignment. The maximum number of the CDMA gather fetches is 16383, add a check for it. Add a sanity check for the relocations in a same way. [ 46.829393] Unable to handle kernel paging request at virtual address f09b2000 ... [] (host1x_job_pin) from [] (tegra_drm_submit+0x474/0x510) [] (tegra_drm_submit) from [] (tegra_submit+0x50/0x6c) [] (tegra_submit) from [] (drm_ioctl+0x1e4/0x3ec) [] (drm_ioctl) from [] (do_vfs_ioctl+0x9c/0x8e4) [] (do_vfs_ioctl) from [] (SyS_ioctl+0x34/0x5c) [] (SyS_ioctl) from [] (ret_fast_syscall+0x0/0x3c) Signed-off-by: Dmitry Osipenko Reviewed-by: Erik Faye-Lund Reviewed-by: Mikko Perttunen --- drivers/gpu/drm/tegra/drm.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/gem.c | 5 ----- drivers/gpu/drm/tegra/gem.h | 5 +++++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index f9282da94a1f..7e4559ec824d 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -26,6 +26,7 @@ #define DRIVER_PATCHLEVEL 0 #define CARVEOUT_SZ SZ_64M +#define CDMA_GATHER_FETCHES_MAX_NB 16383 struct tegra_drm_file { struct idr contexts; @@ -383,18 +384,41 @@ int tegra_drm_submit(struct tegra_drm_context *context, while (num_cmdbufs) { struct drm_tegra_cmdbuf cmdbuf; struct host1x_bo *bo; + struct tegra_bo *obj; + u64 offset; if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) { err = -EFAULT; goto fail; } + /* + * The maximum number of CDMA gather fetches is 16383, a higher + * value means the words count is malformed. + */ + if (cmdbuf.words > CDMA_GATHER_FETCHES_MAX_NB) { + err = -EINVAL; + goto fail; + } + bo = host1x_bo_lookup(file, cmdbuf.handle); if (!bo) { err = -ENOENT; goto fail; } + offset = (u64)cmdbuf.offset + (u64)cmdbuf.words * sizeof(u32); + obj = host1x_to_tegra_bo(bo); + + /* + * The CDMA base address if 4-bytes aligned, unaligned offset + * is malformed. + */ + if (offset & 3 || offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } + host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); num_cmdbufs--; cmdbufs++; @@ -402,11 +426,35 @@ int tegra_drm_submit(struct tegra_drm_context *context, /* copy and resolve relocations from submit */ while (num_relocs--) { + struct host1x_reloc *reloc; + struct tegra_bo *obj; + err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], &relocs[num_relocs], drm, file); if (err < 0) goto fail; + + reloc = &job->relocarray[num_relocs]; + obj = host1x_to_tegra_bo(reloc->cmdbuf.bo); + + /* + * The unaligned cmdbuf offset will cause an unaligned write + * during of the relocations patching, corrupting the commands + * stream. + */ + if (reloc->cmdbuf.offset & 3 || + reloc->cmdbuf.offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } + + obj = host1x_to_tegra_bo(reloc->target.bo); + + if (reloc->target.offset >= obj->gem.size) { + err = -EINVAL; + goto fail; + } } if (copy_from_user(job->waitchk, waitchks, diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index ca0d4439e97b..6a855b2f07fb 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -20,11 +20,6 @@ #include "drm.h" #include "gem.h" -static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) -{ - return container_of(bo, struct tegra_bo, base); -} - static void tegra_bo_put(struct host1x_bo *bo) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 6c5f12ac0087..8b32a6fd586d 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -52,6 +52,11 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) return container_of(gem, struct tegra_bo, gem); } +static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) +{ + return container_of(bo, struct tegra_bo, base); +} + struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size, unsigned long flags); struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file,