From patchwork Thu Jan 29 18:00:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yann Droneaud X-Patchwork-Id: 5744311 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9E0989F38B for ; Thu, 29 Jan 2015 18:02:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A941F200E5 for ; Thu, 29 Jan 2015 18:02:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E5D9D20259 for ; Thu, 29 Jan 2015 18:02:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753806AbbA2SCB (ORCPT ); Thu, 29 Jan 2015 13:02:01 -0500 Received: from smtpfb1-g21.free.fr ([212.27.42.9]:52356 "EHLO smtpfb1-g21.free.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753757AbbA2SB7 (ORCPT ); Thu, 29 Jan 2015 13:01:59 -0500 Received: from smtp4-g21.free.fr (smtp4-g21.free.fr [212.27.42.4]) by smtpfb1-g21.free.fr (Postfix) with ESMTP id 858FB77D937; Thu, 29 Jan 2015 19:01:56 +0100 (CET) Received: from localhost.localdomain (unknown [37.161.184.214]) by smtp4-g21.free.fr (Postfix) with ESMTP id EA0814C8085; Thu, 29 Jan 2015 18:59:25 +0100 (CET) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by localhost.localdomain (8.14.9/8.14.8) with ESMTP id t0TI1rCP026344; Thu, 29 Jan 2015 19:01:53 +0100 Received: (from ydroneaud@localhost) by localhost.localdomain (8.14.9/8.14.9/Submit) id t0TI1pj3026342; Thu, 29 Jan 2015 19:01:51 +0100 From: Yann Droneaud To: Sagi Grimberg , Shachar Raindel , Eli Cohen , Haggai Eran , Roland Dreier Cc: Yann Droneaud , linux-rdma@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v1 3/5] IB/uverbs: ex_query_device: answer must depend on response buffer's size Date: Thu, 29 Jan 2015 19:00:00 +0100 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 As specified in "Extending Verbs API" presentation [1] by Tzahi Oved during OFA International Developer Workshop 2013, the request's comp_mask should describe the request data: it's describe the availability of extended fields in the request. Conversely, the response's comp_mask should describe the presence of extended fields in the response. So instead of silently truncating extended QUERY_DEVICE uverb's response, see commit 5a77abf9a97a ("IB/core: Add support for extended query device caps")), this patch makes function ib_uverbs_ex_query_device() check the available space in the response buffer against the minimal response structure and fail with -ENOSPC if this base structure cannot be returned to userspace: it's required to be able to return the comp_mask's value, at least. For extended features, currently only IB_USER_VERBS_EX_QUERY_DEVICE_ODP per commit 860f10a799c8 ("IB/core: Add flags for on demand paging support"), the extension's data is returned if the needed space is available in the response buffer: it is expected that newer userspace program pass a bigger response buffer so that it can retrieve extended features. The comp_mask value will match the fields that were effectively returned to userspace. In the end: - userspace won't get truncated responses; - newer kernel would be able to support older binaries and older binaries will work flawlessly with newer kernel; - additionally, newer binaries would even be able to support older kernel, as far as they don't set new feature bit in request's comp_mask. Note: as offsetof() is used to retrieve the size of the lower chunk of the response, beware that it only works if the upper chunk is right after, without any implicit padding. And, as the size of the latter chunk is added to the base size, implicit padding at the end of the structure is not taken in account. Both point must be taken in account when extending the uverbs functionalities. [1] https://www.openfabrics.org/images/docs/2013_Dev_Workshop/Tues_0423/2013_Workshop_Tues_0830_Tzahi_Oved-verbs_extensions_ofa_2013-tzahio.pdf Link: http://mid.gmane.org/cover.1422553023.git.ydroneaud@opteya.com Cc: Sagi Grimberg Cc: Shachar Raindel Cc: Eli Cohen Cc: Haggai Eran Signed-off-by: Yann Droneaud Reviewed-by: Haggai Eran --- drivers/infiniband/core/uverbs_cmd.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index fbcc54b86795..81d8b5aa2eb6 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -3302,6 +3302,7 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, struct ib_uverbs_ex_query_device cmd; struct ib_device_attr attr; struct ib_device *device; + size_t resp_len; int err; device = file->device->ib_dev; @@ -3318,6 +3319,11 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, if (cmd.reserved) return -EINVAL; + resp_len = offsetof(typeof(resp), odp_caps); + + if (ucore->outlen < resp_len) + return -ENOSPC; + err = device->query_device(device, &attr); if (err) return err; @@ -3326,6 +3332,9 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, copy_query_dev_fields(file, &resp.base, &attr); resp.comp_mask = 0; + if (ucore->outlen < resp_len + sizeof(resp.odp_caps)) + goto end; + #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING resp.odp_caps.general_caps = attr.odp_caps.general_caps; resp.odp_caps.per_transport_caps.rc_odp_caps = @@ -3336,8 +3345,10 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file, attr.odp_caps.per_transport_caps.ud_odp_caps; #endif resp.comp_mask |= IB_USER_VERBS_EX_QUERY_DEVICE_ODP; + resp_len += sizeof(resp.odp_caps); - err = ib_copy_to_udata(ucore, &resp, sizeof(resp)); +end: + err = ib_copy_to_udata(ucore, &resp, resp_len); if (err) return err;