From patchwork Sun Jul 20 19:51:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yann Droneaud X-Patchwork-Id: 4592151 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 9D646C0514 for ; Sun, 20 Jul 2014 19:55:53 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C9C1D200FE for ; Sun, 20 Jul 2014 19:55:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0360D200F0 for ; Sun, 20 Jul 2014 19:55:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753338AbaGTTzg (ORCPT ); Sun, 20 Jul 2014 15:55:36 -0400 Received: from smtp6-g21.free.fr ([212.27.42.6]:24563 "EHLO smtp6-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753008AbaGTTzf (ORCPT ); Sun, 20 Jul 2014 15:55:35 -0400 Received: from localhost.localdomain (unknown [IPv6:2a01:e35:2e9f:6ac0:446c:9ad5:44d4:79a1]) by smtp6-g21.free.fr (Postfix) with ESMTP id D54C882293; Sun, 20 Jul 2014 21:55:30 +0200 (CEST) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by localhost.localdomain (8.14.8/8.14.7) with ESMTP id s6KJsPjQ006119; Sun, 20 Jul 2014 21:54:30 +0200 Received: (from ydroneaud@localhost) by localhost.localdomain (8.14.8/8.14.8/Submit) id s6KJsOuX006118; Sun, 20 Jul 2014 21:54:24 +0200 From: Yann Droneaud To: Roland Dreier , Sean Hefty , Hal Rosenstock Cc: linux-rdma@vger.kernel.org, Yann Droneaud Subject: [PATCH 3/4] IB/uverbs: check userspace output buffer size in ib_uverbs_poll_cq() Date: Sun, 20 Jul 2014 21:51:11 +0200 Message-Id: <5e4defa2410d0a5b3f3a28508e850dd5d6c287b1.1405884453.git.ydroneaud@opteya.com> 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 Makes ib_uverbs_poll_cq() check the length of the output buffer against number of wc: this will prevent the function from writing past userspace provided buffer. Note that it might affect existing userspace programs that were setting 'struct ibv_poll_cq' field 'ne' to a value too large compared to the size of the buffer allocated to hold the work completion items. Perhaps such userspace programs were hoping to have allocated enough memory to hold the maximum number of work completions that can be returned on this particular completion queue or it would have been broken with random memory corruption due to the kernel writting past the response buffer. Example: int vendor_poll_cq_broken(struct ibv_cq *cq, int ne, struct ibv_wc *wc) { struct ibv_poll_cq cmd; struct ibv_poll_cq_resp *resp; int resp_size; ssize_t sret; int ret = -1; cmd.cq_handle = cq->handle; cmd.ne = ne; /* forget about ne * sizeof(struct ibv_kern_wc) */ resp_size = sizeof(*resp); resp = malloc(resp_size); assert(resp != NULL); IBV_INIT_CMD_RESP(&cmd, sizeof(cmd), POLL_CQ, resp, resp_size); sret = write(cq->context->cmd_fd, &cmd, sizeof(cmd)); if (sret != sizeof(cmd)) goto leave; ret = resp->count; /* ignore the response */ leave: free(resp); return ret; } Since libibverbs is the most common (if not the only) userspace component that access the uverbs API directly, it should be safe to have the kernel ensure coherency between the request number of entries and the size of the response buffer that will be used to hold the entries. Link: http://marc.info/?i=cover.1405884453.git.ydroneaud@opteya.com Signed-off-by: Yann Droneaud --- drivers/infiniband/core/uverbs_cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 9b971514db88..3626143db6ef 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1427,6 +1427,9 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; + if ((out_len - sizeof resp)/(sizeof(struct ib_uverbs_wc)) < cmd.ne) + return -ENOSPC; + cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); if (!cq) return -EINVAL;