From patchwork Tue Jul 29 20:34:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 4642691 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 9FD71C0338 for ; Tue, 29 Jul 2014 20:35:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DCB5F200D0 for ; Tue, 29 Jul 2014 20:35:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 063702008F for ; Tue, 29 Jul 2014 20:35:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754432AbaG2UfZ (ORCPT ); Tue, 29 Jul 2014 16:35:25 -0400 Received: from mail-qg0-f51.google.com ([209.85.192.51]:58825 "EHLO mail-qg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754396AbaG2UfW (ORCPT ); Tue, 29 Jul 2014 16:35:22 -0400 Received: by mail-qg0-f51.google.com with SMTP id a108so315361qge.10 for ; Tue, 29 Jul 2014 13:35:22 -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=V9z4Y9873cHEv2uoIGu3MysroHpbWZ6UCi0uwRMWJk+VrlfJ5reFPPPBszJucTGuJB TuTHNJPmverip0rQLngXtowpGzqAu6j/B3ETVt8zjTAXHVCksnHQad8jWGSxq+dQpLNk BGUVBouqncs6qC7rbb7cWmiYil8qxz52WgYiGlEfnr2tItZ60LuB8OOIpToa25p+l2Qq rsq4penzq8t+GjtJiuo82BRG/T3F8tkWYWWSMnzrAQp8vFS59d7LwbjgNkPcqUactl0q /rzLYSeUbPRVwwco5yLJtISMfIWF5UNew+mCatP6Dvjw1/X6e45QuzEOg5HygVMkVHcq vyNw== X-Gm-Message-State: ALoCoQnUoROkUwZ5GxOS5IZEm3ajansmj1IK3km5kxRaJck7x4WjDetujSd2m03ueHGDn0uDzqzs X-Received: by 10.229.226.135 with SMTP id iw7mr7506466qcb.13.1406666122021; Tue, 29 Jul 2014 13:35:22 -0700 (PDT) Received: from tlielax.poochiereds.net ([2001:470:8:d63:3a60:77ff:fe93:a95d]) by mx.google.com with ESMTPSA id 98sm74611qgh.5.2014.07.29.13.35.20 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Jul 2014 13:35:21 -0700 (PDT) From: Jeff Layton To: bfields@fieldses.org Cc: linux-nfs@vger.kernel.org, hch@infradead.org Subject: [PATCH v2 35/38] nfsd: close potential race in nfsd4_free_stateid Date: Tue, 29 Jul 2014 16:34:18 -0400 Message-Id: <1406666061-14175-36-git-send-email-jlayton@primarydata.com> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1406666061-14175-1-git-send-email-jlayton@primarydata.com> References: <1406666061-14175-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);