From patchwork Sun Jul 20 19:51:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yann Droneaud X-Patchwork-Id: 4592161 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (unknown [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 54B8AC0514 for ; Sun, 20 Jul 2014 19:57:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 457C8200FE for ; Sun, 20 Jul 2014 19:57:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 837A72010B for ; Sun, 20 Jul 2014 19:56:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753905AbaGTT4p (ORCPT ); Sun, 20 Jul 2014 15:56:45 -0400 Received: from smtp6-g21.free.fr ([212.27.42.6]:27552 "EHLO smtp6-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753823AbaGTT4o (ORCPT ); Sun, 20 Jul 2014 15:56:44 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e35:2e9f:6ac0:446c:9ad5:44d4:79a1]) by smtp6-g21.free.fr (Postfix) with ESMTP id 80BDB82259; Sun, 20 Jul 2014 21:56:36 +0200 (CEST) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by localhost.localdomain (8.14.8/8.14.7) with ESMTP id s6KJtKlm006152; Sun, 20 Jul 2014 21:55:30 +0200 Received: (from ydroneaud@localhost) by localhost.localdomain (8.14.8/8.14.8/Submit) id s6KJtKZ8006151; Sun, 20 Jul 2014 21:55:20 +0200 From: Yann Droneaud To: Roland Dreier , Sean Hefty , Hal Rosenstock Cc: linux-rdma@vger.kernel.org, Yann Droneaud , Eli Cohen , Or Gerlitz , Sagi Grimberg Subject: [PATCH 4/4] IB/uverbs: subtract command header from input size Date: Sun, 20 Jul 2014 21:51:12 +0200 Message-Id: X-Mailer: git-send-email 1.9.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Spam-Status: No, score=-5.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY, URIBL_RHS_DOB autolearn=ham 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 The uverbs handler functions are given a pointer to the command buffer, which point right after the command header. But the size given to the function is the total size, including the command header size. The size of the command header must be subtracted from the input length before calling the uverbs handler function so that the parameters are in par. This patch makes ib_uverbs_write() subtract the header size from the total size when calling uverbs function. As the return value from the uverbs function will be the size without the header (or a negative value), it must not be used as-is. Instead the function use the total size as return value when no error occurred. Additionally, drivers (mthca, mlx5) taking the size of command header in account in their size checks are modified accordingly. Note: once the input size is correct, input size check in uverbs functions might become effective. Cc: Eli Cohen Cc: Or Gerlitz Cc: Sagi Grimberg Link: http://marc.info/?i=cover.1405884453.git.ydroneaud@opteya.com Signed-off-by: Yann Droneaud --- drivers/infiniband/core/uverbs_main.c | 18 +++++++++++++----- drivers/infiniband/hw/mlx5/cq.c | 6 ++---- drivers/infiniband/hw/mlx5/main.c | 2 +- drivers/infiniband/hw/mlx5/srq.c | 6 ++---- drivers/infiniband/hw/mthca/mthca_provider.c | 2 +- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 08219fb3338b..577f236d47e9 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -592,6 +592,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, { struct ib_uverbs_file *file = filp->private_data; struct ib_uverbs_cmd_hdr hdr; + const size_t written_count = count; __u32 flags; if (count < sizeof hdr) @@ -605,6 +606,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if (!flags) { __u32 command; + ssize_t err; if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK | IB_USER_VERBS_CMD_COMMAND_MASK)) @@ -626,10 +628,17 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if (hdr.in_words * 4 != count) return -EINVAL; - return uverbs_cmd_table[command](file, - buf + sizeof(hdr), - hdr.in_words * 4, - hdr.out_words * 4); + count -= sizeof(hdr); + buf += sizeof(hdr); + + err = uverbs_cmd_table[command](file, + buf, + count, + hdr.out_words * 4); + if (err < 0) + return err; + + return written_count; } else if (flags == IB_USER_VERBS_CMD_FLAG_EXTENDED) { __u32 command; @@ -638,7 +647,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, struct ib_udata ucore; struct ib_udata uhw; int err; - size_t written_count = count; if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK | IB_USER_VERBS_CMD_COMMAND_MASK)) diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index 8ae4f896cb41..898877a4f04d 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -609,10 +609,8 @@ static int create_cq_user(struct mlx5_ib_dev *dev, struct ib_udata *udata, int ncont; int err; - ucmdlen = - (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) < - sizeof(ucmd)) ? (sizeof(ucmd) - - sizeof(ucmd.reserved)) : sizeof(ucmd); + ucmdlen = (udata->inlen < sizeof(ucmd)) ? + (sizeof(ucmd) - sizeof(ucmd.reserved)) : sizeof(ucmd); if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) return -EFAULT; diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index 364d4b6937f5..59b6ee53df96 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -563,7 +563,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, return ERR_PTR(-EAGAIN); memset(&req, 0, sizeof(req)); - reqlen = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr); + reqlen = udata->inlen; if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req)) ver = 0; else if (reqlen == sizeof(struct mlx5_ib_alloc_ucontext_req_v2)) diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c index 384af6dec5eb..37ab42d1d30b 100644 --- a/drivers/infiniband/hw/mlx5/srq.c +++ b/drivers/infiniband/hw/mlx5/srq.c @@ -86,10 +86,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, int ncont; u32 offset; - ucmdlen = - (udata->inlen - sizeof(struct ib_uverbs_cmd_hdr) < - sizeof(ucmd)) ? (sizeof(ucmd) - - sizeof(ucmd.reserved)) : sizeof(ucmd); + ucmdlen = (udata->inlen < sizeof(ucmd)) ? + (sizeof(ucmd) - sizeof(ucmd.reserved)) : sizeof(ucmd); if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) { mlx5_ib_dbg(dev, "failed copy udata\n"); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 415f8e1a54db..e5933b032fc3 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -986,7 +986,7 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, int err = 0; int write_mtt_size; - if (udata->inlen - sizeof (struct ib_uverbs_cmd_hdr) < sizeof ucmd) { + if (udata->inlen < sizeof ucmd) { if (!to_mucontext(pd->uobject->context)->reg_mr_warned) { mthca_warn(dev, "Process '%s' did not pass in MR attrs.\n", current->comm);