Received: by 2002:a05:6358:bb9e:b0:b9:5105:a5b4 with SMTP id df30csp3489733rwb; Mon, 5 Sep 2022 12:38:40 -0700 (PDT) X-Google-Smtp-Source: AA6agR5d9PAZ1w52euFXeXSr3jFf7MalLBr82FqwctXtPGtF9KzQ3qSqSigKOPyopHv23j1pQkxG X-Received: by 2002:a17:907:7e92:b0:741:5f7e:f1ac with SMTP id qb18-20020a1709077e9200b007415f7ef1acmr29640671ejc.176.1662406719820; Mon, 05 Sep 2022 12:38:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1662406719; cv=none; d=google.com; s=arc-20160816; b=h2IZfHajCFzxAbQvtRrCUEJ9Yn6ftMQHW04upq4AhYD0a6dOYKRmLxJPFODYsb6Auy x4RpK6NmyMvAmfmvv31PMPafF7/4J87fVvMH/of6huuKH+FKnmULVEwzO0clmU4qZ5YF 7NWUTAUdvQscaKUaR3QtOrLtOKiBZ6JkaWDVS1OA/wqyFmmqRNN8Ezrqa+Cni1vgJ39H HcySPGUYsAcY4BJk1jW+GY6bZ63MJjKEhyUM3ppZlxVwNsWQQP1aAMkVNG3FtBMQC+07 dNI+Xzdxz4sl0ohsWG4OmykjbJirraB2jaeJUm36aC9eK1HtmlpGTHAD5tLAUE+Q7CPM lspw== 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:message-id:date:cc:to:from:subject; bh=U/RZENMAt59oJbG6N1m0Ri5dqL9gg23CpNXZwd4S/JM=; b=PT6j2cfC9uaB+/lDccCP1jOGpSsoFrt+A4KP0JyMUABjqnkYTIyBzraLXJgi2+LDGF LmStGCsUoTmR4FN0ogwM2PzilIF1DqQ0Czflkn0tXmPn3QSc+X7UoBGAH7fSNY18Pg8Y +Dp4VSe19n/jvZt3j9YiBk9tWoQf0sf0cN+Imlh8UQaHJSKlJWSkrjc6UiCOWDEHRi+/ V7FGUVI7/nfiz4RfVI5zL4GKKLOXSyW43glY6FZsYNvP/kEc9qfo4ksg4OfsYLxhPQGS xO1urSjEt9BDYV5IwlPbpONvfsG12gG7dQMhs3S1dNwl5cfm4pH235cgGps5r/tZY3KJ af6g== 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 e6-20020a056402190600b0043c30afc919si8355448edz.438.2022.09.05.12.38.02; Mon, 05 Sep 2022 12:38:39 -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 S232042AbiIETdn (ORCPT + 99 others); Mon, 5 Sep 2022 15:33:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53048 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232592AbiIETdk (ORCPT ); Mon, 5 Sep 2022 15:33:40 -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 8227247B95 for ; Mon, 5 Sep 2022 12:33:37 -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 A5BD4B811FE for ; Mon, 5 Sep 2022 19:33:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3149CC433C1; Mon, 5 Sep 2022 19:33:34 +0000 (UTC) Subject: [PATCH v1] NFSD: Fix handling of oversized NFSv4 COMPOUND requests From: Chuck Lever To: linux-nfs@vger.kernel.org Cc: bfields@fieldses.org Date: Mon, 05 Sep 2022 15:33:32 -0400 Message-ID: <166240641266.2834.1862985890566562958.stgit@bazille.1015granger.net> User-Agent: StGit/1.5 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 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 --- 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 7055e1c91d0e..6ef0795fefb4 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2631,9 +2631,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) { @@ -2646,10 +2643,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 @@ -2725,8 +2732,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 4b69e86240eb..09519b4a860a 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2359,16 +2359,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 = vcalloc(argp->opcnt, sizeof(*argp->ops)); diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 96267258e629..466e2786fc97 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -717,9 +717,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];