Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752017AbdCCJJS (ORCPT ); Fri, 3 Mar 2017 04:09:18 -0500 Received: from mga05.intel.com ([192.55.52.43]:27410 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751637AbdCCJHU (ORCPT ); Fri, 3 Mar 2017 04:07:20 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,236,1484035200"; d="scan'208";a="1117935833" From: Elena Reshetova To: linux-kernel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, peterz@infradead.org, gregkh@linuxfoundation.org, miklos@szeredi.hu, Elena Reshetova , Hans Liljestrand , Kees Cook , David Windsor Subject: [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t Date: Fri, 3 Mar 2017 11:04:03 +0200 Message-Id: <1488531845-23463-2-git-send-email-elena.reshetova@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1488531845-23463-1-git-send-email-elena.reshetova@intel.com> References: <1488531845-23463-1-git-send-email-elena.reshetova@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2323 Lines: 78 refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova Signed-off-by: Hans Liljestrand Signed-off-by: Kees Cook Signed-off-by: David Windsor --- fs/fuse/file.c | 8 ++++---- fs/fuse/fuse_i.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ec238fb..70770a0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -58,7 +58,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) } INIT_LIST_HEAD(&ff->write_entry); - atomic_set(&ff->count, 1); + refcount_set(&ff->count, 1); RB_CLEAR_NODE(&ff->polled_node); init_waitqueue_head(&ff->poll_wait); @@ -77,7 +77,7 @@ void fuse_file_free(struct fuse_file *ff) static struct fuse_file *fuse_file_get(struct fuse_file *ff) { - atomic_inc(&ff->count); + refcount_inc(&ff->count); return ff; } @@ -88,7 +88,7 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) static void fuse_file_put(struct fuse_file *ff, bool sync) { - if (atomic_dec_and_test(&ff->count)) { + if (refcount_dec_and_test(&ff->count)) { struct fuse_req *req = ff->reserved_req; if (ff->fc->no_open) { @@ -293,7 +293,7 @@ static int fuse_release(struct inode *inode, struct file *file) void fuse_sync_release(struct fuse_file *ff, int flags) { - WARN_ON(atomic_read(&ff->count) != 1); + WARN_ON(refcount_read(&ff->count) > 1); fuse_prepare_release(ff, flags, FUSE_RELEASE); /* * iput(NULL) is a no-op and since the refcount is 1 and everything's diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 32ac2c9..1d6d67e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -24,6 +24,7 @@ #include #include #include +#include /** Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -137,7 +138,7 @@ struct fuse_file { u64 nodeid; /** Refcount */ - atomic_t count; + refcount_t count; /** FOPEN_* flags returned by open */ u32 open_flags; -- 2.7.4