Received: by 2002:a05:6358:45e:b0:b5:b6eb:e1f9 with SMTP id 30csp2468490rwe; Sun, 28 Aug 2022 12:20:51 -0700 (PDT) X-Google-Smtp-Source: AA6agR5kcGakKZ08KI0TlJoSUzJaiCGMyBS7kj1S1hIVME4LBi7lHbyDN8xai50toWOv/4j93vab X-Received: by 2002:a17:90a:6d90:b0:1fb:17ab:9f61 with SMTP id a16-20020a17090a6d9000b001fb17ab9f61mr15317066pjk.232.1661714450930; Sun, 28 Aug 2022 12:20:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1661714450; cv=none; d=google.com; s=arc-20160816; b=lzSOD6g3+nB3IFcGGpdQH3AZhIoZBG7v2Ik+L4lG5+LAYWikxEg6l+/4pCAZr7TZXN aR38rYHRPxNmno43Hva2R8hfJ+z7ZPojpBoc8OUqSKiNdrpzCUqVw8kuddhfMc4rI2mK U/wroLSYrKfYREgA/6npcGv3jvXH/rbir8qWJ0dkv9cZn4ZbX3BfS3PVl3m4lYJ7NGYI +q3aq5gWLIuM2ViwCC9cbDay/ulfqZ4H9QsU4dFVH0wbH71WGqi9AnsfWsMo84eycf4q sGJM+QOUQY7SBjDAOiKdYVJM1+UHU62G6+YadSLFhFg3hEDO5kfZyY/yhPvvK7gbrTQW 63mw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:to:from:subject; bh=+dMNUkGWCHZk/xmHnWxxv0ZwkwXwRRbPHc18YA+8UH4=; b=GnE2Mt/ug2zFd8RodLHScoKqOLRWFFdQgMkVSbDEmICrO0vEVXfduucU35T29BN3tC Vw3JnIa9mmJg+gBGxGvYDGZoIDNpJCulc4q4OuRkMDd5hcyuqlNqtA3AMz553PtgeDn7 x+bUXz8CnJYHm+DVu776yWrAPEaafHRGUYLIkwCSeBNsIOVx8IGvHFLo5jeD7wNfoTLu G8tSqUzN2J885OFExSUtTsmiAEa2HDEecOxyr/IWrTSk8mr5cHGFMsPsmYWobNK10eYe 2nHBP8bxJK9O41nvqZu5MM/W4DQmvtsIn13Zit9oXQJBKgEAkjJmzKii+Umf+pa1wqtB A79A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s13-20020a056a00194d00b0052daa005a8asi8048749pfk.374.2022.08.28.12.20.37; Sun, 28 Aug 2022 12:20:50 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229901AbiH1Sul (ORCPT + 99 others); Sun, 28 Aug 2022 14:50:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36772 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229547AbiH1Suj (ORCPT ); Sun, 28 Aug 2022 14:50:39 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A025B7EB for ; Sun, 28 Aug 2022 11:50:38 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0D2F0B80B87 for ; Sun, 28 Aug 2022 18:50:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A5574C433C1; Sun, 28 Aug 2022 18:50:35 +0000 (UTC) Subject: [PATCH v2 3/7] NFSD: Protect against READDIR send buffer overflow From: Chuck Lever To: linux-nfs@vger.kernel.org Date: Sun, 28 Aug 2022 14:50:34 -0400 Message-ID: <166171263459.21449.18044553311121354704.stgit@manet.1015granger.net> In-Reply-To: <166171174172.21449.5036120183381273656.stgit@manet.1015granger.net> References: <166171174172.21449.5036120183381273656.stgit@manet.1015granger.net> User-Agent: StGit/1.5.dev2+g9ce680a5 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_HI,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org For many years, NFSD has conserved the number of pages held by each nfsd thread by combining the RPC receive and send buffers into a single array of pages. The dividing line between the receive and send buffer is pointed to by svc_rqst::rq_respages. Thus the send buffer shrinks when the received RPC record containing the RPC Call is large. nfsd3_init_dirlist_pages() needs to account for the space in the svc_rqst::rq_pages array already consumed by the RPC receive buffer. Otherwise READDIR reply encoding can wander off the end of the page array. Thanks to Aleksi Illikainen and Kari Hulkko for discovering this issue. Reported-by: Ben Ronallo Fixes: f5dcccd647da ("NFSD: Update the NFSv2 READDIR entry encoder to use struct xdr_stream") Fixes: 7f87fc2d34d4 ("NFSD: Update NFSv3 READDIR entry encoders to use struct xdr_stream") Signed-off-by: Chuck Lever --- fs/nfsd/nfs3proc.c | 5 ++--- fs/nfsd/nfsproc.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index a41cca619338..fab87e9e0b20 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -564,12 +564,11 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, struct xdr_buf *buf = &resp->dirlist; struct xdr_stream *xdr = &resp->xdr; - count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); - memset(buf, 0, sizeof(*buf)); /* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count - XDR_UNIT * 2; + buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), rqstp->rq_res.buflen); + buf->buflen -= XDR_UNIT * 2; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 7381972f1677..23c273cb68a9 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -567,12 +567,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, struct xdr_buf *buf = &resp->dirlist; struct xdr_stream *xdr = &resp->xdr; - count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); - memset(buf, 0, sizeof(*buf)); /* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count - XDR_UNIT * 2; + buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), rqstp->rq_res.buflen); + buf->buflen -= XDR_UNIT * 2; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page++;