linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] fs, fuse subsystem refcount conversions
@ 2017-03-03  9:04 Elena Reshetova
  2017-03-03  9:04 ` [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t Elena Reshetova
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Elena Reshetova @ 2017-03-03  9:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-fsdevel, peterz, gregkh, miklos, Elena Reshetova

Now when new refcount_t type and API are finally merged
(see include/linux/refcount.h), the following
patches convert various refcounters in the fuse filesystem from atomic_t
to refcount_t. By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The below patches are fully independent and can be cherry-picked separately.
Since we convert all kernel subsystems in the same fashion, resulting
in about 300 patches, we have to group them for sending at least in some
fashion to be manageable. Please excuse the long cc list.

These patches have been tested using tests supplied with libfuse.
Not sure if this is the right way to test it. No output or failures
with result to refcount conversions. refcount WARNs were on.


Elena Reshetova (3):
  fs, fuse: convert fuse_file.count from atomic_t to refcount_t
  fs, fuse: convert fuse_req.count from atomic_t to refcount_t
  fs, fuse: convert fuse_conn.count from atomic_t to refcount_t

 fs/fuse/dev.c    | 10 +++++-----
 fs/fuse/file.c   |  8 ++++----
 fs/fuse/fuse_i.h |  7 ++++---
 fs/fuse/inode.c  |  6 +++---
 4 files changed, 16 insertions(+), 15 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t
  2017-03-03  9:04 [PATCH 0/3] fs, fuse subsystem refcount conversions Elena Reshetova
@ 2017-03-03  9:04 ` Elena Reshetova
  2017-03-03  9:04 ` [PATCH 2/3] fs, fuse: convert fuse_req.count " Elena Reshetova
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Elena Reshetova @ 2017-03-03  9:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, miklos, Elena Reshetova,
	Hans Liljestrand, Kees Cook, David Windsor

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 <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
 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 <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/xattr.h>
+#include <linux/refcount.h>
 
 /** 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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] fs, fuse: convert fuse_req.count from atomic_t to refcount_t
  2017-03-03  9:04 [PATCH 0/3] fs, fuse subsystem refcount conversions Elena Reshetova
  2017-03-03  9:04 ` [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t Elena Reshetova
@ 2017-03-03  9:04 ` Elena Reshetova
  2017-03-03  9:04 ` [PATCH 3/3] fs, fuse: convert fuse_conn.count " Elena Reshetova
  2017-03-03 16:05 ` [PATCH 0/3] fs, fuse subsystem refcount conversions Miklos Szeredi
  3 siblings, 0 replies; 5+ messages in thread
From: Elena Reshetova @ 2017-03-03  9:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, miklos, Elena Reshetova,
	Hans Liljestrand, Kees Cook, David Windsor

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 <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
 fs/fuse/dev.c    | 10 +++++-----
 fs/fuse/fuse_i.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index f117926..3e67205 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -44,7 +44,7 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages,
 	INIT_LIST_HEAD(&req->list);
 	INIT_LIST_HEAD(&req->intr_entry);
 	init_waitqueue_head(&req->waitq);
-	atomic_set(&req->count, 1);
+	refcount_set(&req->count, 1);
 	req->pages = pages;
 	req->page_descs = page_descs;
 	req->max_pages = npages;
@@ -101,14 +101,14 @@ void fuse_request_free(struct fuse_req *req)
 
 void __fuse_get_request(struct fuse_req *req)
 {
-	atomic_inc(&req->count);
+	refcount_inc(&req->count);
 }
 
 /* Must be called with > 1 refcount */
 static void __fuse_put_request(struct fuse_req *req)
 {
-	BUG_ON(atomic_read(&req->count) < 2);
-	atomic_dec(&req->count);
+	BUG_ON(refcount_read(&req->count) < 2);
+	refcount_dec(&req->count);
 }
 
 static void fuse_req_init_context(struct fuse_req *req)
@@ -263,7 +263,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
-	if (atomic_dec_and_test(&req->count)) {
+	if (refcount_dec_and_test(&req->count)) {
 		if (test_bit(FR_BACKGROUND, &req->flags)) {
 			/*
 			 * We get here in the unlikely case that a background
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 1d6d67e..9d43740 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -307,7 +307,7 @@ struct fuse_req {
 	struct list_head intr_entry;
 
 	/** refcount */
-	atomic_t count;
+	refcount_t count;
 
 	/** Unique ID for the interrupt request */
 	u64 intr_unique;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] fs, fuse: convert fuse_conn.count from atomic_t to refcount_t
  2017-03-03  9:04 [PATCH 0/3] fs, fuse subsystem refcount conversions Elena Reshetova
  2017-03-03  9:04 ` [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t Elena Reshetova
  2017-03-03  9:04 ` [PATCH 2/3] fs, fuse: convert fuse_req.count " Elena Reshetova
@ 2017-03-03  9:04 ` Elena Reshetova
  2017-03-03 16:05 ` [PATCH 0/3] fs, fuse subsystem refcount conversions Miklos Szeredi
  3 siblings, 0 replies; 5+ messages in thread
From: Elena Reshetova @ 2017-03-03  9:04 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-fsdevel, peterz, gregkh, miklos, Elena Reshetova,
	Hans Liljestrand, Kees Cook, David Windsor

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 <elena.reshetova@intel.com>
Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
 fs/fuse/fuse_i.h | 2 +-
 fs/fuse/inode.c  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 9d43740..6c649f0 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -449,7 +449,7 @@ struct fuse_conn {
 	spinlock_t lock;
 
 	/** Refcount */
-	atomic_t count;
+	refcount_t count;
 
 	/** Number of fuse_dev's */
 	atomic_t dev_count;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6fe6a88..3961c5f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -608,7 +608,7 @@ void fuse_conn_init(struct fuse_conn *fc)
 	memset(fc, 0, sizeof(*fc));
 	spin_lock_init(&fc->lock);
 	init_rwsem(&fc->killsb);
-	atomic_set(&fc->count, 1);
+	refcount_set(&fc->count, 1);
 	atomic_set(&fc->dev_count, 1);
 	init_waitqueue_head(&fc->blocked_waitq);
 	init_waitqueue_head(&fc->reserved_req_waitq);
@@ -631,7 +631,7 @@ EXPORT_SYMBOL_GPL(fuse_conn_init);
 
 void fuse_conn_put(struct fuse_conn *fc)
 {
-	if (atomic_dec_and_test(&fc->count)) {
+	if (refcount_dec_and_test(&fc->count)) {
 		if (fc->destroy_req)
 			fuse_request_free(fc->destroy_req);
 		fc->release(fc);
@@ -641,7 +641,7 @@ EXPORT_SYMBOL_GPL(fuse_conn_put);
 
 struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
 {
-	atomic_inc(&fc->count);
+	refcount_inc(&fc->count);
 	return fc;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_get);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] fs, fuse subsystem refcount conversions
  2017-03-03  9:04 [PATCH 0/3] fs, fuse subsystem refcount conversions Elena Reshetova
                   ` (2 preceding siblings ...)
  2017-03-03  9:04 ` [PATCH 3/3] fs, fuse: convert fuse_conn.count " Elena Reshetova
@ 2017-03-03 16:05 ` Miklos Szeredi
  3 siblings, 0 replies; 5+ messages in thread
From: Miklos Szeredi @ 2017-03-03 16:05 UTC (permalink / raw)
  To: Elena Reshetova; +Cc: linux-kernel, linux-fsdevel, peterz, Greg Kroah-Hartman

On Fri, Mar 3, 2017 at 10:04 AM, Elena Reshetova
<elena.reshetova@intel.com> wrote:
> Now when new refcount_t type and API are finally merged
> (see include/linux/refcount.h), the following
> patches convert various refcounters in the fuse filesystem from atomic_t
> to refcount_t. By doing this we prevent intentional or accidental
> underflows or overflows that can led to use-after-free vulnerabilities.
>
> The below patches are fully independent and can be cherry-picked separately.
> Since we convert all kernel subsystems in the same fashion, resulting
> in about 300 patches, we have to group them for sending at least in some
> fashion to be manageable. Please excuse the long cc list.
>
> These patches have been tested using tests supplied with libfuse.
> Not sure if this is the right way to test it. No output or failures
> with result to refcount conversions. refcount WARNs were on.

Thanks, queued.

Miklos

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-03-03 16:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03  9:04 [PATCH 0/3] fs, fuse subsystem refcount conversions Elena Reshetova
2017-03-03  9:04 ` [PATCH 1/3] fs, fuse: convert fuse_file.count from atomic_t to refcount_t Elena Reshetova
2017-03-03  9:04 ` [PATCH 2/3] fs, fuse: convert fuse_req.count " Elena Reshetova
2017-03-03  9:04 ` [PATCH 3/3] fs, fuse: convert fuse_conn.count " Elena Reshetova
2017-03-03 16:05 ` [PATCH 0/3] fs, fuse subsystem refcount conversions Miklos Szeredi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).