From patchwork Thu Jun 11 15:19:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Carpenter X-Patchwork-Id: 6589191 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 3F8E0C0020 for ; Thu, 11 Jun 2015 15:19:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 41717205C1 for ; Thu, 11 Jun 2015 15:19:29 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 355862058A for ; Thu, 11 Jun 2015 15:19:28 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B87CA6E4DF; Thu, 11 Jun 2015 08:19:26 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by gabe.freedesktop.org (Postfix) with ESMTP id 21CA06E4DF for ; Thu, 11 Jun 2015 08:19:24 -0700 (PDT) Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id t5BFJCWc025762 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 11 Jun 2015 15:19:12 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id t5BFJBue011876 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 11 Jun 2015 15:19:11 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id t5BFJBBu007006; Thu, 11 Jun 2015 15:19:11 GMT Received: from mwanda (/154.0.139.178) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 11 Jun 2015 08:19:10 -0700 Date: Thu, 11 Jun 2015 18:19:02 +0300 From: Dan Carpenter To: Oded Gabbay , Yair Shachar Subject: [patch] drm/amdkfd: fix some range checks in address watch ioctl Message-ID: <20150611151902.GF12192@mwanda> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-Source-IP: userv0021.oracle.com [156.151.31.71] Cc: kernel-janitors@vger.kernel.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP ->buf_size_in_bytes must be large enough to hold ->num_watch_points and ->watch_mode so I have added a sizeof(int) * 2 to the minimum size. Also we have to subtract sizeof(*args) from the max args_idx limit so that it matches the allocation. Also I changed a > to >= for the last compare. I moved the if (aw_info.num_watch_points > MAX_WATCH_ADDRESSES) { check here so that we don't get an integer overflow on 32bit systems. It's harmless because we would have caught it later but it causes a static checker warning. I had to add a new include to get the MAX_WATCH_ADDRESSES define. Signed-off-by: Dan Carpenter --- I feel like this patch is probably not going to be merged without changes. Also we seem to set ->watch_address to the last address in the buffer instead of the first? It is very strange. I am going on vacation so I will be offline for a week. Yair, if this patch isn't right then feel free to fix it and give me a Reported-by tag. Otherwise, I will see everyone on the flip side. :) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 96c904b..54a608a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -36,6 +36,7 @@ #include "kfd_priv.h" #include "kfd_device_queue_manager.h" #include "kfd_dbgmgr.h" +#include "../../radeon/cik_reg.h" static long kfd_ioctl(struct file *, unsigned int, unsigned long); static int kfd_open(struct inode *, struct file *); @@ -553,7 +554,7 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, /* Validate arguments */ if ((args->buf_size_in_bytes > MAX_ALLOWED_AW_BUFF_SIZE) || - (args->buf_size_in_bytes <= sizeof(*args)) || + (args->buf_size_in_bytes <= sizeof(*args) + sizeof(int) * 2) || (cmd_from_user == NULL)) return -EINVAL; @@ -576,6 +577,11 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, aw_info.process = p; aw_info.num_watch_points = *((uint32_t *)(&args_buff[args_idx])); + if (aw_info.num_watch_points == 0 || + aw_info.num_watch_points > MAX_WATCH_ADDRESSES) { + kfree(args_buff); + return -EINVAL; + } args_idx += sizeof(aw_info.num_watch_points); aw_info.watch_mode = (enum HSA_DBG_WATCH_MODE *) &args_buff[args_idx]; @@ -590,7 +596,7 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, /* skip over the addresses buffer */ args_idx += sizeof(aw_info.watch_address) * aw_info.num_watch_points; - if (args_idx >= args->buf_size_in_bytes) { + if (args_idx >= args->buf_size_in_bytes - sizeof(*args)) { kfree(args_buff); return -EINVAL; } @@ -614,7 +620,7 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, args_idx += sizeof(aw_info.watch_mask); } - if (args_idx > args->buf_size_in_bytes) { + if (args_idx >= args->buf_size_in_bytes - sizeof(args)) { kfree(args_buff); return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index 96153f2..d366757 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -301,12 +301,6 @@ static int dbgdev_address_watch_nodiq(struct kfd_dbgdev *dbgdev, addrLo.u32All = 0; cntl.u32All = 0; - if ((adw_info->num_watch_points > MAX_WATCH_ADDRESSES) || - (adw_info->num_watch_points == 0)) { - pr_err("amdkfd: num_watch_points is invalid\n"); - return -EINVAL; - } - if ((adw_info->watch_mode == NULL) || (adw_info->watch_address == NULL)) { pr_err("amdkfd: adw_info fields are not valid\n"); @@ -369,12 +363,6 @@ static int dbgdev_address_watch_diq(struct kfd_dbgdev *dbgdev, addrLo.u32All = 0; cntl.u32All = 0; - if ((adw_info->num_watch_points > MAX_WATCH_ADDRESSES) || - (adw_info->num_watch_points == 0)) { - pr_err("amdkfd: num_watch_points is invalid\n"); - return -EINVAL; - } - if ((NULL == adw_info->watch_mode) || (NULL == adw_info->watch_address)) { pr_err("amdkfd: adw_info fields are not valid\n");