From patchwork Wed Jul 30 01:34:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 4644311 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id B763FC033A for ; Wed, 30 Jul 2014 01:35:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EB2552012B for ; Wed, 30 Jul 2014 01:35:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1F2102012D for ; Wed, 30 Jul 2014 01:35:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754749AbaG3Bfp (ORCPT ); Tue, 29 Jul 2014 21:35:45 -0400 Received: from mail-qg0-f52.google.com ([209.85.192.52]:58065 "EHLO mail-qg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754652AbaG3Bfn (ORCPT ); Tue, 29 Jul 2014 21:35:43 -0400 Received: by mail-qg0-f52.google.com with SMTP id f51so667473qge.11 for ; Tue, 29 Jul 2014 18:35:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=4GpKIEYvKQZNi57WlZI44eDsX1t9VaTwXQr+Ga7swsw=; b=aVCJHT3Zj4EM9wkWxuCrzMouSxdu4geqB3HdMAzXeyUIU1A6VN3evwU58ARL3NKLGp iAhs9iUSty1pjjC6rnK7HtOCjSAnJ1rfVqZwrF+8HBxgEOac5/HHhaWKNqNe8vEI0oJb brEzeG9gYxzGZM+PwGPH3qMdbXjLho8ypGUEHIBw0t0yvPy19Lq7P7abERKW8v2MHxld 9WNdgXg5ZCd0F1GmYeYceY41yLYHKJNv14KwecVYYUOqhmoTh8mogjljDY7uprtn4otS I+58PudQE8hRwrJuagv7YbK3Hie7zdXyCbl0qTQmaWwo9GUjSsuJ6DvwnlZUInzyzFhq 8KFg== X-Gm-Message-State: ALoCoQm9Ey6ZvhfJ1iHqncpwSqsBrZGvIWqaMvJuJo6xRag7h6nG4P1NCcpoMsNIXA1KyEZDZAmK X-Received: by 10.224.22.134 with SMTP id n6mr1195128qab.27.1406684142754; Tue, 29 Jul 2014 18:35:42 -0700 (PDT) Received: from tlielax.poochiereds.net ([2001:470:8:d63:3a60:77ff:fe93:a95d]) by mx.google.com with ESMTPSA id 81sm860946qgw.21.2014.07.29.18.35.41 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Jul 2014 18:35:41 -0700 (PDT) From: Jeff Layton To: bfields@fieldses.org Cc: linux-nfs@vger.kernel.org, hch@infradead.org Subject: [PATCH v3 35/38] nfsd: close potential race in nfsd4_free_stateid Date: Tue, 29 Jul 2014 21:34:40 -0400 Message-Id: <1406684083-19736-36-git-send-email-jlayton@primarydata.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1406684083-19736-1-git-send-email-jlayton@primarydata.com> References: <1406684083-19736-1-git-send-email-jlayton@primarydata.com> Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Once we remove the client_mutex, it'll be possible for the sc_type of a lock stateid to change after it's found and checked, but before we can go to destroy it. If that happens, we can end up putting the persistent reference to the stateid more than once, and unhash it more than once. Fix this by unhashing the lock stateid prior to dropping the cl_lock but after finding it. Signed-off-by: Jeff Layton --- fs/nfsd/nfs4state.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9358cbe2283d..9c7dcbb68094 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4397,17 +4397,6 @@ unlock_state: return status; } -static __be32 -nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) -{ - struct nfs4_lockowner *lo = lockowner(stp->st_stateowner); - - if (check_for_locks(stp->st_stid.sc_file, lo)) - return nfserr_locks_held; - release_lock_stateid(stp); - return nfs_ok; -} - /* * Test if the stateid is valid */ @@ -4434,6 +4423,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stateid_t *stateid = &free_stateid->fr_stateid; struct nfs4_stid *s; struct nfs4_delegation *dp; + struct nfs4_ol_stateid *stp; struct nfs4_client *cl = cstate->session->se_client; __be32 ret = nfserr_bad_stateid; @@ -4456,8 +4446,15 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ret = check_stateid_generation(stateid, &s->sc_stateid, 1); if (ret) break; + stp = openlockstateid(s); + ret = nfserr_locks_held; + if (check_for_locks(stp->st_stid.sc_file, + lockowner(stp->st_stateowner))) + break; + unhash_lock_stateid(stp); spin_unlock(&cl->cl_lock); - ret = nfsd4_free_lock_stateid(openlockstateid(s)); + nfs4_put_stid(s); + ret = nfs_ok; goto out; case NFS4_REVOKED_DELEG_STID: dp = delegstateid(s);