Received: by 2002:a05:7412:a9a2:b0:e2:908c:2ebd with SMTP id o34csp1284828rdh; Fri, 27 Oct 2023 09:33:14 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFHS4bulh+3ISmSlAzQtjQYN49uKVRKqGjjPY+GSuqNYBi/a03P1w4ap5mElrjGoHYR3v7V X-Received: by 2002:a05:6902:18ce:b0:d9c:7d7d:1ac9 with SMTP id ck14-20020a05690218ce00b00d9c7d7d1ac9mr3680571ybb.14.1698424393876; Fri, 27 Oct 2023 09:33:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698424393; cv=none; d=google.com; s=arc-20160816; b=SwGJn29IXTM/Bhbqs0Lxiv6Nzazr1n/D4mUomx75U6CR/3RLmppxRR8ZqvDOX3E/4k cPgJTmdfEuttdRIS1BvrNMqnqydMO2qDS8TT5pCZYb7nUO8g2pdwkYcBWbpUFKBv448n r6VJhbG7eyFZ3pdO8+koN+5QLX7+U72HFpX6GZo1Ae3ZPjza001Faxg3gpLESNB4kgAY 0hSrWbp0ZHOmJeqJKuYrlNtvKycZQQjv634vc5cB+fS9tqW1eN63dsZK/kO3vnOLbY2+ 8VCnBtYutCq673bKi63hKP1wo1y5asuJURJW3ygbTvOf89WGnik+K7J1Y6pMBKQzdA+x bJBQ== 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:dkim-signature; bh=X6A1dRo2zc1qaKcqf/skJr6rp8v0o5PzlwpEzirurOc=; fh=hWUvAMKdIbFWqZMMPEz2fWGHXd70qWWU1EROluuOyAI=; b=AoZ2/CdhNQDoYO96ycBqB4/++UBpXhx9nTTALHMkIlYfEBDf8M6diH6yFkt3gsNcFh vpKILyj3gHc8ktILUQcluCESnMhCXFki7FL8XkYH1pbjj4Kn74qrioQbvPJw5c2cKKHD ZXaFFqAsUUzSgcYJj8CkH9GfN00PsbkNaVtseR0NBp6tOsCUqz/4AZl7u1F9qZ3nbQ2J HyxMHqmKxsK+urTdTuQb5yy7HXgqhaZzWT7+EJhV5ki37KKp+ztkKdTIGck2P0rB5gSc NpeTlE1jSaymW5FyVtRTeIfL5TWqQnturA/OSJtbymD8bjrFBfGUa+vjJKkPimLkFjQf a54A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=nAlRrSe9; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from howler.vger.email (howler.vger.email. [23.128.96.34]) by mx.google.com with ESMTPS id h184-20020a2521c1000000b00d9abff76f57si2790199ybh.199.2023.10.27.09.32.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 09:33:13 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) client-ip=23.128.96.34; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=nAlRrSe9; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.34 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id A7B778374E41; Fri, 27 Oct 2023 09:32:46 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231649AbjJ0Qcm (ORCPT + 99 others); Fri, 27 Oct 2023 12:32:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232079AbjJ0Qck (ORCPT ); Fri, 27 Oct 2023 12:32:40 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2BE8F1A5 for ; Fri, 27 Oct 2023 09:32:38 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35400C433C8; Fri, 27 Oct 2023 16:32:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1698424357; bh=bvcLB87EpiqMop2KcgSWPaepucbenRNUuyGDBtNBqt8=; h=Subject:From:To:Cc:Date:From; b=nAlRrSe9OO5EiNEbyVaRx8+lhhx2+7u9Uca754hTUhkzG3RieeLx5+KBD9rrnRXT3 lLuUwMPTLflMMHUEbXHiwZQxfWb3cXkA2/xBJZ/JjwLBck8BDnWlI+mbvExhpTwmUS Ds1X9K8+m3sfI4TNGNXIYCwAIrEqG6npzARI+iZT/arVrerVsShrmmUvPerYWSMTXU xC1HEzIC6XXzzIqVwQtpBUbqnJtFC5lsuCgrR6VuRDGaHjL8x00UKzAPIx8lazc7op /NU8oFrZ57uUSm39MmAMy/bR+v182bsqE0pOBPgkUtLcN3/4ER6GnwnWcqP4yX+vFV tEAi4rmbj+VCQ== Subject: [PATCH RFC] SunRPC: Split server-side GSS sequence number window update From: Chuck Lever To: linux-nfs@vger.kernel.org Cc: Russell Cattelan , David Howells , Simo Sorce , Chuck Lever Date: Fri, 27 Oct 2023 12:32:36 -0400 Message-ID: <169842400684.2384.5932301559665706233.stgit@91.116.238.104.host.secureserver.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=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on howler.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Fri, 27 Oct 2023 09:32:47 -0700 (PDT) From: Chuck Lever RFC 2203 Section 5.3.3.1 says that the sequence number window check on a server can advance the highest received sequence number only if GSS_VerifyMIC() returns GSS_S_COMPLETE. Thus NFSD's implementation calls GSS_VerifyMIC() first, then checks and updates the sequence window under a spin lock. The problem with this arrangement is that the kernel's implementation of GSS_VerifyMIC() can sleep and schedule. Or a version of checksum verification that hides timing could be in use. Sometimes it can take several milliseconds for GSS_VerifyMIC() to return. By that time, on a fast transport, the client has advanced the GSS sequence number until the current sequence number being checked falls below the current window. RFC 2203 mandates that the server silently discard the request in that case, which translates to a dropped connection and retransmit. In some cases this leads to spurious I/O errors or even data corruption. This issue affects all NFS versions using GSS Kerberos. To avoid the latency of GSS_VerifyMIC() triggering GSS sequence window bounds check failures, perform the lower bound check /before/ calling gss_verify_mic(). Closes: https://bugzilla.linux-nfs.org/show_bug.cgi?id=416 Cc: Russell Cattelan Cc: David Howells Cc: Simo Sorce Signed-off-by: Chuck Lever --- net/sunrpc/auth_gss/svcauth_gss.c | 63 ++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) This is untested, but it's a possible way to reduce spurious failures seen when using sec=krb5[ip]. At this point, I'm interested in thoughts and comments. diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 18734e70c5dd..ebaa5c68d22f 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -640,7 +640,38 @@ gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) } /** - * gss_check_seq_num - GSS sequence number window check + * gss_seq_num_lower_bound - GSS sequence number window check + * @rqstp: RPC Call to use when reporting errors + * @rsci: cached GSS context state (updated on return) + * @seq_num: sequence number to check + * + * Implements the lower bound check part of the sequence number + * algorithm as specified in RFC 2203, Section 5.3.3.1. "Context + * Management". This is lockless since we're not updating the + * window here. Also, it happens before GSS_VerifyMIC() since MIC + * verification can take a long time during which the window can + * advance considerably. + * + * Return values: + * %true: @rqstp's GSS sequence number is inside the window + * %false: @rqstp's GSS sequence number is below the window + */ +static bool gss_seq_num_lower_bound(const struct svc_rqst *rqstp, + const struct rsc *rsci, u32 seq_num) +{ + const struct gss_svc_seq_data *sd = &rsci->seqdata; + unsigned int max = READ_ONCE(sd->sd_max); + + if (seq_num + GSS_SEQ_WIN <= max) { + trace_rpcgss_svc_seqno_low(rqstp, seq_num, + max - GSS_SEQ_WIN, max); + return false; + } + return true; +} + +/** + * gss_seq_num_update - GSS sequence number window update * @rqstp: RPC Call to use when reporting errors * @rsci: cached GSS context state (updated on return) * @seq_num: sequence number to check @@ -652,8 +683,8 @@ gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) * %true: @rqstp's GSS sequence number is inside the window * %false: @rqstp's GSS sequence number is outside the window */ -static bool gss_check_seq_num(const struct svc_rqst *rqstp, struct rsc *rsci, - u32 seq_num) +static bool gss_seq_num_update(const struct svc_rqst *rqstp, struct rsc *rsci, + u32 seq_num) { struct gss_svc_seq_data *sd = &rsci->seqdata; bool result = false; @@ -669,8 +700,6 @@ static bool gss_check_seq_num(const struct svc_rqst *rqstp, struct rsc *rsci, } __set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win); goto ok; - } else if (seq_num + GSS_SEQ_WIN <= sd->sd_max) { - goto toolow; } if (__test_and_set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win)) goto alreadyseen; @@ -681,11 +710,6 @@ static bool gss_check_seq_num(const struct svc_rqst *rqstp, struct rsc *rsci, spin_unlock(&sd->sd_lock); return result; -toolow: - trace_rpcgss_svc_seqno_low(rqstp, seq_num, - sd->sd_max - GSS_SEQ_WIN, - sd->sd_max); - goto out; alreadyseen: trace_rpcgss_svc_seqno_seen(rqstp, seq_num); goto out; @@ -709,6 +733,14 @@ svcauth_gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci, struct xdr_netobj checksum; struct kvec iov; + if (unlikely(gc->gc_seq > MAXSEQ)) { + trace_rpcgss_svc_seqno_large(rqstp, gc->gc_seq); + rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem; + return SVC_DENIED; + } + if (!gss_seq_num_lower_bound(rqstp, rsci, gc->gc_seq)) + return SVC_DROP; + /* * Compute the checksum of the incoming Call from the * XID field to credential field: @@ -738,12 +770,11 @@ svcauth_gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci, return SVC_DENIED; } - if (gc->gc_seq > MAXSEQ) { - trace_rpcgss_svc_seqno_large(rqstp, gc->gc_seq); - rqstp->rq_auth_stat = rpcsec_gsserr_ctxproblem; - return SVC_DENIED; - } - if (!gss_check_seq_num(rqstp, rsci, gc->gc_seq)) + /* + * RFC 2203 states that the sequence number window should + * be updated only if GSS_VerifyMIC returns GSS_S_COMPLETE. + */ + if (!gss_seq_num_update(rqstp, rsci, gc->gc_seq)) return SVC_DROP; return SVC_OK; }