From patchwork Thu Feb 9 07:38:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Windsor X-Patchwork-Id: 9567863 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 645F660231 for ; Sat, 11 Feb 2017 06:23:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A9B8285A7 for ; Sat, 11 Feb 2017 06:23:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2CC05285CC; Sat, 11 Feb 2017 06:23:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00, DATE_IN_PAST_24_48, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 2659B285A7 for ; Sat, 11 Feb 2017 06:23:24 +0000 (UTC) Received: (qmail 1911 invoked by uid 550); 11 Feb 2017 06:23:22 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 1880 invoked from network); 11 Feb 2017 06:23:20 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=nJpOrvLZ9OB5ApbrzrF0d85BlIjPrLIHOXEeU8y0WYg=; b=VZ4H1P+vvYYulTTUGbF+ApPAywhuURgayAZIR0TXI2WkOBaFUwSp8q/ORrLY3pSYgQ Uc/IsprN7DY9AOUk3/1V39qqifRDRZPjIJFOUUVs5IXnKG77YPc6i6/urwzPOw144sSk /rdSpuH7KnvUk4KbHZkBWKHevDoAJFVH2uiy42dm9ajyM99jbugzJlprnQPeyrApZxl3 k1/4Vx1z6m+BVeuGvFtAdGOUAEi6+8e4yG1M7qkfi+/rFn11m/HqOeh3inIcsVNpR7gO f6RuRZBglDyf2O3xjjYPyDUMR7fy4khH67QL9b+XBYrtfhQZ6vzKBGiz4qUULgLDvZbX GLoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=nJpOrvLZ9OB5ApbrzrF0d85BlIjPrLIHOXEeU8y0WYg=; b=YijfoQ6BuC63/LLOCAgEXqhHzDM75yXA+ca8kyixqInma+sAo7Ms7sFouPICzB0rZm 9SALdP0AtvgaEpt5cPKldFs7yWG4hcBg4SUfypGDNZD+9PUGfTVM2LMZJ8k+RWtz165t cDfAOgk6ys7mqDsV80WC4xCv/iLIwW7RPq1lY3Db9O2Bnm+LGKksJ0jl5TjkgFLfSbOl X1Rtbj2oQnc5S5B09jOuDijzX8BnFNqByQno264puBTMwq78SRRGeUflhN9PIrwkYbaZ r5ub1NNzfWbk/FtV+ZF1v513pfGhXb4u/TkeoQWlLhQV3juC9TKsgbz6pnjTVNTkzHz5 gKWQ== X-Gm-Message-State: AMke39mlRZyx7hciBqGPSE5xnzXna1SummeE9aawgEjGtPmfiH30JVpzVRIcMDE8Yn2lnA== X-Received: by 10.13.247.134 with SMTP id h128mr10661165ywf.56.1486794188638; Fri, 10 Feb 2017 22:23:08 -0800 (PST) From: David Windsor To: linux-nfs@vger.kernel.org, netdev@vger.kernel.org Cc: kernel-hardening@lists.openwall.com, bfields@fieldses.org, jlayton@poochiereds.net, keescook@chromium.org, elena.reshetova@intel.com, dwindsor@gmail.com Date: Thu, 9 Feb 2017 02:38:21 -0500 Message-Id: <1486625901-10094-1-git-send-email-dwindsor@gmail.com> X-Mailer: git-send-email 2.7.4 Subject: [kernel-hardening] [RFC][PATCH] nfsd: add +1 to reference counting scheme for struct nfsd4_session X-Virus-Scanned: ClamAV using ClamSMTP In furtherance of the KSPP effort to add overflow protection to kernel reference counters, a new type (refcount_t) and API have been created. Part of the refcount_t API is refcount_inc(), which will not increment a refcount_t variable if its value is 0 (as this would indicate a possible use-after-free condition). In auditing the kernel for refcounting corner cases, we've come across the case of struct nfsd4_session. From fs/nfsd/state.h: /* * Representation of a v4.1+ session. These are refcounted in a similar * fashion to the nfs4_client. References are only taken when the server * is actively working on the object (primarily during the processing of * compounds). */ struct nfsd4_session { atomic_t se_ref; ... }; From fs/nfsd/nfs4state.c: static void init_session(..., struct nfsd4_session *new, ...) { ... atomic_set(&new->se_ref, 0); ... } Since nfsd4_session objects are initialized with refcount = 0, subsequent increments will fail using the new refcount_t API. Being largely unfamiliar with this subsystem's garbage collection mechanism, I'm unsure how to best fix this. Attached is a patch that performs a logical +1 on struct nfsd4_session's reference counting scheme. If this is the correct route to take, I will resubmit this patch with updated comments for how struct nfsd4_session is refcounted (see the above comment from fs/nsfd/state.h). This is in preparation for the previously mentioned refcount_t API series. Thanks, David Windsor Signed-off-by: David Windsor --- fs/nfsd/nfs4state.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a0dee8a..b0f3010 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -196,7 +196,7 @@ static void nfsd4_put_session_locked(struct nfsd4_session *ses) lockdep_assert_held(&nn->client_lock); - if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses)) + if (!atomic_add_unless(&ses->se_ref, -1, 1) && is_session_des(ses)) free_session(ses); put_client_renew_locked(clp); } @@ -1645,7 +1645,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru new->se_flags = cses->flags; new->se_cb_prog = cses->callback_prog; new->se_cb_sec = cses->cb_sec; - atomic_set(&new->se_ref, 0); + atomic_set(&new->se_ref, 1); idx = hash_sessionid(&new->se_sessionid); list_add(&new->se_hash, &nn->sessionid_hashtbl[idx]); spin_lock(&clp->cl_lock); @@ -1792,7 +1792,7 @@ free_client(struct nfs4_client *clp) ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, se_perclnt); list_del(&ses->se_perclnt); - WARN_ON_ONCE(atomic_read(&ses->se_ref)); + WARN_ON_ONCE((atomic_read(&ses->se_ref) > 1)); free_session(ses); } rpc_destroy_wait_queue(&clp->cl_cb_waitq);