From patchwork Mon May 4 13:00:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yann Droneaud X-Patchwork-Id: 6326701 Return-Path: X-Original-To: patchwork-linux-rdma@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 5F0A5BEEE1 for ; Mon, 4 May 2015 13:01:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 712BD20383 for ; Mon, 4 May 2015 13:01:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 409712037C for ; Mon, 4 May 2015 13:01:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752847AbbEDNBv (ORCPT ); Mon, 4 May 2015 09:01:51 -0400 Received: from smtp2-g21.free.fr ([212.27.42.2]:32181 "EHLO smtp2-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752829AbbEDNBv (ORCPT ); Mon, 4 May 2015 09:01:51 -0400 Received: from localhost.localdomain (unknown [37.162.185.86]) by smtp2-g21.free.fr (Postfix) with ESMTPS id 36F814B01DD; Mon, 4 May 2015 15:01:16 +0200 (CEST) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by localhost.localdomain (8.14.9/8.14.8) with ESMTP id t44D1iVg006847; Mon, 4 May 2015 15:01:44 +0200 Received: (from ydroneaud@localhost) by localhost.localdomain (8.14.9/8.14.9/Submit) id t44D1hIj006846; Mon, 4 May 2015 15:01:43 +0200 From: Yann Droneaud To: Doug Ledford , Roland Dreier Cc: linux-rdma@vger.kernel.org, Yann Droneaud Subject: [PATCHv1 3/6] IB/uverbs: check userspace output buffer size in ib_uverbs_poll_cq() Date: Mon, 4 May 2015 15:00:49 +0200 Message-Id: X-Mailer: git-send-email 2.1.0 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=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 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 writing 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; } The provided patch will make it impossible to do it on patched kernels. Applications using libibverbs are not going to be affected by this patch, but unknown broken applications using directly kernel uverbs API may fail. Link: http://marc.info/?i=cover.1430743694.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 a3a3b6eafd1d..147f61c8692b 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1563,6 +1563,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;