Received: by 2002:a05:6358:1087:b0:cb:c9d3:cd90 with SMTP id j7csp3886741rwi; Sat, 22 Oct 2022 01:34:16 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6ZgUqapMKQQsyM8QCFK3E9sTEiLh7W3YO0OL9S+1QScRgYAMwbjOk72PzMiT5QLHmx2hzw X-Received: by 2002:a05:6402:1a42:b0:458:b430:7e70 with SMTP id bf2-20020a0564021a4200b00458b4307e70mr21138732edb.293.1666427656093; Sat, 22 Oct 2022 01:34:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666427656; cv=none; d=google.com; s=arc-20160816; b=h7HcDuQAE/vjxZur6DMM6XRYzy+M/+WWI4+0v/j7PuekqCqqqNlEUtVodkhUV7GrtY b1pHFzix47+OwYnags+FOUsr/5aMponSCuWfv0z1qZ5HNu4fZ0zEh/bZEAjK+zAB19gI 5A7SOy2TtzWsmQN3fFEpy21Nt81+zvb76fvb49IuQeZTMka3WmyYiwelWVsaAkc4Fju7 F7dzrTYnJHXV7DzUpRSg12NIOp2manRV6rCB/e9l8OwyFLArh3rio2a6xS3/rCI7HuDV JP0duLlrqFkhHYML36JFHVyUhVV4FeWKETza6dvwKwjC8fSueEmDPuQK+KgfgLv8d5ce 3PiA== 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:subject:cc:to :from:dkim-signature; bh=mWNjloKPgPd4iBHya7kVtYZQfvGjUXr8ML9bpgElIyI=; b=ihDAYn7hkFH40vYVrKqwVazQs9tRHwfsqygdMzjZP4Jtl0nyiGEFEQkmllYIGjgATZ SQq/wBUM1jwkSqB1xwiscX6tizXnxYRG1GEz3LaOxEE2H0qbzj3Tr1iqEy8UVbJBBkRq BUCzCMi0QZLEhb/hmRNo/uBx0ZTEvMCI31NOAVxCLX+GgIuhpzqsAELfCaRA+0gIiuyK X6gceKUxW8tSm9+iG6yWllDof43c4iD0bMarQuoV72jlBPiAfkPqtfu4q3RNHEVUGxoK SWIYZ/mEOuWFJ4Jx6GbikAxZzIlTpz6rcHnt2Uaeh6KQpjtaPmDzsoIMDrnoXs1FoF7N 5FYQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=WNrtlmty; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id r7-20020a05640251c700b0045d4f995ac0si21052140edd.588.2022.10.22.01.33.45; Sat, 22 Oct 2022 01:34:16 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-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; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=WNrtlmty; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231995AbiJVHxZ (ORCPT + 99 others); Sat, 22 Oct 2022 03:53:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231819AbiJVHvL (ORCPT ); Sat, 22 Oct 2022 03:51:11 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2B890AC283; Sat, 22 Oct 2022 00:46:33 -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 dfw.source.kernel.org (Postfix) with ESMTPS id D6B0060BA0; Sat, 22 Oct 2022 07:44:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E984BC433D6; Sat, 22 Oct 2022 07:44:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1666424652; bh=2EhvjNtORN3r16Cix0wrloC5od6db+mEbJMl0K4QFlI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WNrtlmtya+1gue/j+IZZ75HoKc8KqvyOwsFs8Mub5TinvHDjIXYIzmoDF+JTzgD+T B9ZfLhg2YiENs35gMsyCzbo/V722z9g2uFNMKOwj6CpGkczNYSty4700mfFZptLCVF EfZg+GMRf5+oKsSqfZGy5gzAmkRfrIku4P9Id/oI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Bruce Fields , Chuck Lever , Sasha Levin Subject: [PATCH 5.19 198/717] NFSD: Fix handling of oversized NFSv4 COMPOUND requests Date: Sat, 22 Oct 2022 09:21:17 +0200 Message-Id: <20221022072450.511212061@linuxfoundation.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221022072415.034382448@linuxfoundation.org> References: <20221022072415.034382448@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS 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-kernel@vger.kernel.org From: Chuck Lever [ Upstream commit 7518a3dc5ea249d4112156ce71b8b184eb786151 ] If an NFS server returns NFS4ERR_RESOURCE on the first operation in an NFSv4 COMPOUND, there's no way for a client to know where the problem is and then simplify the compound to make forward progress. So instead, make NFSD process as many operations in an oversized COMPOUND as it can and then return NFS4ERR_RESOURCE on the first operation it did not process. pynfs NFSv4.0 COMP6 exercises this case, but checks only for the COMPOUND status code, not whether the server has processed any of the operations. pynfs NFSv4.1 SEQ6 and SEQ7 exercise the NFSv4.1 case, which detects too many operations per COMPOUND by checking against the limits negotiated when the session was created. Suggested-by: Bruce Fields Fixes: 0078117c6d91 ("nfsd: return RESOURCE not GARBAGE_ARGS on too many ops") Signed-off-by: Chuck Lever Signed-off-by: Sasha Levin --- fs/nfsd/nfs4proc.c | 19 +++++++++++++------ fs/nfsd/nfs4xdr.c | 12 +++--------- fs/nfsd/xdr4.h | 3 ++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 3895eb52d2b1..c12e66cc58a2 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2663,9 +2663,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = nfserr_minor_vers_mismatch; if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0) goto out; - status = nfserr_resource; - if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND) - goto out; status = nfs41_check_op_ordering(args); if (status) { @@ -2678,10 +2675,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) rqstp->rq_lease_breaker = (void **)&cstate->clp; - trace_nfsd_compound(rqstp, args->opcnt); + trace_nfsd_compound(rqstp, args->client_opcnt); while (!status && resp->opcnt < args->opcnt) { op = &args->ops[resp->opcnt++]; + if (unlikely(resp->opcnt == NFSD_MAX_OPS_PER_COMPOUND)) { + /* If there are still more operations to process, + * stop here and report NFS4ERR_RESOURCE. */ + if (cstate->minorversion == 0 && + args->client_opcnt > resp->opcnt) { + op->status = nfserr_resource; + goto encode_op; + } + } + /* * The XDR decode routines may have pre-set op->status; * for example, if there is a miscellaneous XDR error @@ -2757,8 +2764,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = op->status; } - trace_nfsd_compound_status(args->opcnt, resp->opcnt, status, - nfsd4_op_name(op->opnum)); + trace_nfsd_compound_status(args->client_opcnt, resp->opcnt, + status, nfsd4_op_name(op->opnum)); nfsd4_cstate_clear_replay(cstate); nfsd4_increment_op_stats(op->opnum); diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2acea7792bb2..eef98e3f4ae5 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2347,16 +2347,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0) return false; - if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0) + if (xdr_stream_decode_u32(argp->xdr, &argp->client_opcnt) < 0) return false; - - /* - * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS - * here, so we return success at the xdr level so that - * nfsd4_proc can handle this is an NFS-level error. - */ - if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND) - return true; + argp->opcnt = min_t(u32, argp->client_opcnt, + NFSD_MAX_OPS_PER_COMPOUND); if (argp->opcnt > ARRAY_SIZE(argp->iops)) { argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 7b744011f2d3..77286e8c9ab0 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -689,9 +689,10 @@ struct nfsd4_compoundargs { struct svcxdr_tmpbuf *to_free; struct svc_rqst *rqstp; - u32 taglen; char * tag; + u32 taglen; u32 minorversion; + u32 client_opcnt; u32 opcnt; struct nfsd4_op *ops; struct nfsd4_op iops[8]; -- 2.35.1