Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp3929829ybe; Mon, 16 Sep 2019 03:56:37 -0700 (PDT) X-Google-Smtp-Source: APXvYqzGEddZOHFESeYUmS4pMoavNI3x/fqdFKdiwGj0W4hVPU1UBYmtIdFiNUsMhpOT5l+hM+fu X-Received: by 2002:a50:c3c7:: with SMTP id i7mr6019657edf.138.1568631397875; Mon, 16 Sep 2019 03:56:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1568631397; cv=none; d=google.com; s=arc-20160816; b=yAxX8RDwo50wPK0wzjNvd6tATh8/u3I4NQgKHSumx6n4hj5A9kHZnW3ywYQqOnhLaO IoNg9zXKmxezK3PmlM2dtQWDHakk8iwUVLGAMkPaAroyjiD7OhMqObC878CiUsbT3tVy 99Q9Z0+/B4Jy8JmDALz7XRIj3ClbT4eJJu4cvcSZRRxNrv7xwhGftirwGwSL33zNLyyN yLJxW4NLVOelUCx7WGxjxvCvwTJDzv0BJwdf854Rl9SIytamK0r0KrIglaXJIA3XWfZK QC2SLHe/dk55CzxAwY6KdTU7eiyZwGpF6BGrzomkhutfu0k/ZX7oKmkK6+eM7lFio3ME ZeDw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=ImxRRsRmrP5tzwByJAmA5XWzceaZ3qco2KJmpDfNxZE=; b=ueL6yiKXHpihJVsZu/Vb+4yKT2g0qCJM8m2Q7S04BSvkdwlJbaDkRLdOGVYZtphgVg MjWlTCASMDrs+lpqKAf0TWne5veRQDM/BNZ/6G9sM6RQON4wuUZh8es/2okMiFN53NJN eoc8ApkfthKnZEI3We3Hmq96R/pFAr1H+Y43GaD7kYVfgYXLuyNV7Rqc1jqiHm5eaN5T cYvdJpIQxBiaxoL4xmtn6cdZPQG3ccLt3+H5Q7qyxzx32VdcFwye/a2dt1hcH9IGfRWS A5CS2Eh6x0zhnpXjL8sGUEMv5vtOguCHg21Rcrnycin1+5PJCxmBJjukTEA8lGroHOAC W6FQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c25si3659341edv.307.2019.09.16.03.56.04; Mon, 16 Sep 2019 03:56:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-nfs-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725850AbfIPKiB (ORCPT + 99 others); Mon, 16 Sep 2019 06:38:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40446 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726604AbfIPKiB (ORCPT ); Mon, 16 Sep 2019 06:38:01 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 695D9307D8B9; Mon, 16 Sep 2019 10:38:00 +0000 (UTC) Received: from [172.16.176.1] (ovpn-64-2.rdu2.redhat.com [10.10.64.2]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 17336600F8; Mon, 16 Sep 2019 10:37:58 +0000 (UTC) From: "Benjamin Coddington" To: "Trond Myklebust" , chuck.lever@oracle.com Cc: tibbs@math.uh.edu, bfields@fieldses.org, linux-nfs@vger.kernel.org, anna.schumaker@netapp.com, km@cm4all.com Subject: Re: [PATCH v2 1/2] SUNRPC: Fix buffer handling of GSS MIC without slack Date: Mon, 16 Sep 2019 06:37:59 -0400 Message-ID: In-Reply-To: <444c663d56f9f8292d233ec903b39871df14826a.camel@hammerspace.com> References: <9f9848f4cbb03b09c7f28f8a43fb27120703ae49.1568557832.git.bcodding@redhat.com> <8350AC46-9CFA-410D-AC0C-EF2ACE24FD74@oracle.com> <444c663d56f9f8292d233ec903b39871df14826a.camel@hammerspace.com> MIME-Version: 1.0 Content-Type: text/plain X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Mon, 16 Sep 2019 10:38:01 +0000 (UTC) Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org On 15 Sep 2019, at 13:30, Trond Myklebust wrote: > On Sun, 2019-09-15 at 12:43 -0400, Chuck Lever wrote: >> Hi Ben- >> >> >>> On Sep 15, 2019, at 11:41 AM, Benjamin Coddington < >>> bcodding@redhat.com> wrote: >>> >>> The GSS Message Integrity Check data for krb5i may lie partially in >>> the XDR >>> reply buffer's pages and tail. If so, we try to copy the entire >>> MIC into >>> free space in the tail. But as the estimations of the slack space >>> required >>> for authentication and verification have improved there may be less >>> free >>> space in the tail to complete this copy -- see commit 2c94b8eca1a2 >>> ("SUNRPC: Use au_rslack when computing reply buffer size"). In >>> fact, there >>> may only be room in the tail for a single copy of the MIC, and not >>> part of >>> the MIC and then another complete copy. >>> >>> The real world failure reported is that `ls` of a directory on NFS >>> may >>> sometimes return -EIO, which can be traced back to >>> xdr_buf_read_netobj() >>> failing to find available free space in the tail to copy the MIC. >>> >>> Fix this by checking for the case of the MIC crossing the >>> boundaries of >>> head, pages, and tail. If so, shift the buffer until the MIC is >>> contained >>> completely within the pages or tail. This allows the remainder of >>> the >>> function to create a sub buffer that directly address the complete >>> MIC. >>> >>> Signed-off-by: Benjamin Coddington >>> Cc: stable@vger.kernel.org # v5.1 >>> --- >>> net/sunrpc/xdr.c | 32 +++++++++++++++++++------------- >>> 1 file changed, 19 insertions(+), 13 deletions(-) >>> >>> diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c >>> index 48c93b9e525e..a29ce73c3029 100644 >>> --- a/net/sunrpc/xdr.c >>> +++ b/net/sunrpc/xdr.c >>> @@ -1237,16 +1237,29 @@ xdr_encode_word(struct xdr_buf *buf, >>> unsigned int base, u32 obj) >>> EXPORT_SYMBOL_GPL(xdr_encode_word); >>> >>> /* If the netobj starting offset bytes from the start of xdr_buf is >>> contained >>> - * entirely in the head or the tail, set object to point to it; >>> otherwise >>> - * try to find space for it at the end of the tail, copy it there, >>> and >>> - * set obj to point to it. */ >>> + * entirely in the head, pages, or tail, set object to point to >>> it; otherwise >>> + * shift the buffer until it is contained entirely within the >>> pages or tail. >>> + */ >>> int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj >>> *obj, unsigned int offset) >>> { >>> struct xdr_buf subbuf; >>> + unsigned int boundary; >>> >>> if (xdr_decode_word(buf, offset, &obj->len)) >>> return -EFAULT; >>> - if (xdr_buf_subsegment(buf, &subbuf, offset + 4, obj->len)) >>> + offset += 4; >>> + >>> + /* Is the obj partially in the head? */ >>> + boundary = buf->head[0].iov_len; >>> + if (offset < boundary && (offset + obj->len) > boundary) >>> + xdr_shift_buf(buf, boundary - offset); >>> + >>> + /* Is the obj partially in the pages? */ >>> + boundary += buf->page_len; >>> + if (offset < boundary && (offset + obj->len) > boundary) >>> + xdr_shrink_pagelen(buf, boundary - offset); >>> + >>> + if (xdr_buf_subsegment(buf, &subbuf, offset, obj->len)) >>> return -EFAULT; >>> >>> /* Is the obj contained entirely in the head? */ >>> @@ -1258,17 +1271,10 @@ int xdr_buf_read_netobj(struct xdr_buf >>> *buf, struct xdr_netobj *obj, unsigned in >>> if (subbuf.tail[0].iov_len == obj->len) >>> return 0; >>> >>> - /* use end of tail as storage for obj: >>> - * (We don't copy to the beginning because then we'd have >>> - * to worry about doing a potentially overlapping copy. >>> - * This assumes the object is at most half the length of the >>> - * tail.) */ >>> + /* obj is in the pages: move to end of the tail */ >> >> How about "/* Find a contiguous area in @buf to hold all of @obj */" >> ? >> >>> if (obj->len > buf->buflen - buf->len) >>> return -ENOMEM; >>> - if (buf->tail[0].iov_len != 0) >>> - obj->data = buf->tail[0].iov_base + buf- >>>> tail[0].iov_len; >>> - else >>> - obj->data = buf->head[0].iov_base + buf- >>>> head[0].iov_len; >>> + obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len; >> >> Your new code assumes that when krb5i is in use, the upper layer will >> always provide a non-NULL tail->iov_len. I wouldn't swear that will >> always be true: The reason for the "if (buf->tail[0].iov_len)" check is >> to see whether the upper layer indeed has set up a tail. iov_len will be >> non-zero only when the upper layer has provided a tail buffer. Alright.. I'll bring the test back on v3. > For the case where we only have kvec data, then xdr_buf_init() assigns > all the allocated buffer to the header, so the mic should be > contiguously buffered there. > > If we have page data, then the fact that auth->au_rslack > auth- >> au_ralign should ensure that we have allocated a sufficiently large > tail buffer (see rpc_prepare_reply_pages()). > > BTW: this also means we should really only need to move the mic in the > case where buf->page_len != 0. > It also means that we should probably change xdr_inline_pages() to be a > static function, since the assumption above fails if the user does not > call rpc_prepare_reply_pages() in order to calculate the header > alignment correctly. Sounds like a third patch would make this series even better.. thanks for the review and advice! I'll send a v3 with Chuck's suggestions this morning and put the optimizations Trond would like to see together in a third patch when I have some slack time. Ben