linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
@ 2018-12-26 13:56 Jia-Ju Bai
  2019-01-02  9:34 ` David Howells
  2019-01-04  0:47 ` Benjamin Herrenschmidt
  0 siblings, 2 replies; 7+ messages in thread
From: Jia-Ju Bai @ 2018-12-26 13:56 UTC (permalink / raw)
  To: benh, dhowells, joel, eajames, andrew; +Cc: linux-kernel, Jia-Ju Bai

In drivers/fsi/fsi-sbefifo.c, the functions sbefifo_user_release(), 
sbefifo_user_read() and sbefifo_user_write() may be concurrently executed.

sbefifo_user_release()
  sbefifo_release_command()
    vfree(user->pending_cmd);

sbefifo_user_read()
  mutex_lock();
  rc = __sbefifo_submit(sbefifo, user->pending_cmd, ...);

sbefifo_user_write()
  mutex_lock();
  user->pending_cmd = user->cmd_page;
  user->pending_cmd = vmalloc(len);

Thus, possible concurrency use-after-free bugs may occur in
sbefifo_user_release().

To fix these bugs, the calls to mutex_lock() and mutex_unlock() are
added in sbefifo_user_release().


Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
 drivers/fsi/fsi-sbefifo.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index d92f5b87c251..e278a9014b8f 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -900,8 +900,10 @@ static int sbefifo_user_release(struct inode *inode, struct file *file)
 	if (!user)
 		return -EINVAL;
 
+	mutex_lock(&user->file_lock);
 	sbefifo_release_command(user);
 	free_page((unsigned long)user->cmd_page);
+	mutex_unlock(&user->file_lock);
 	kfree(user);
 
 	return 0;
-- 
2.17.0


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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2018-12-26 13:56 [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release Jia-Ju Bai
@ 2019-01-02  9:34 ` David Howells
  2019-01-03  3:27   ` Benjamin Herrenschmidt
  2019-01-04  0:47 ` Benjamin Herrenschmidt
  1 sibling, 1 reply; 7+ messages in thread
From: David Howells @ 2019-01-02  9:34 UTC (permalink / raw)
  To: Jia-Ju Bai; +Cc: dhowells, benh, joel, eajames, andrew, linux-kernel

Jia-Ju Bai <baijiaju1990@gmail.com> wrote:

> +	mutex_lock(&user->file_lock);
>  	sbefifo_release_command(user);
>  	free_page((unsigned long)user->cmd_page);
> +	mutex_unlock(&user->file_lock);

It shouldn't be necessary to do the free_page() call inside the locked
section.

David

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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2019-01-02  9:34 ` David Howells
@ 2019-01-03  3:27   ` Benjamin Herrenschmidt
  2019-01-03  4:26     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 7+ messages in thread
From: Benjamin Herrenschmidt @ 2019-01-03  3:27 UTC (permalink / raw)
  To: David Howells, Jia-Ju Bai; +Cc: joel, eajames, andrew, linux-kernel

On Wed, 2019-01-02 at 09:34 +0000, David Howells wrote:
> Jia-Ju Bai <baijiaju1990@gmail.com> wrote:
> 
> > +	mutex_lock(&user->file_lock);
> >  	sbefifo_release_command(user);
> >  	free_page((unsigned long)user->cmd_page);
> > +	mutex_unlock(&user->file_lock);
> 
> It shouldn't be necessary to do the free_page() call inside the locked
> section.

True. However, I didn't realize read/write could be concurrent with
release so we have another problem.

I assume when release is called, no new read/write can be issued, I am
correct ? So all we have to protect against is a read/write that has
started prior to release being called, right ?

In that case, what can happen is that release() wins the race on the
mutex, frees everything, then read or write starts using feed stuff.

This is nasty to fix because the mutex is in the user structure,
so even looking at the mutex is racy if release is called.

The right fix, would be, I think, for "user" (pointed to by file-
>private_data) to be protected by a kref. That doesn't close it
completely as the free in release() can still lead to the structure
becoming re-used before read/write tries to get the kref but after it
has NULL checked the private data.

So to make that solid, I would also RCU-defer the actual freeing and
use RCU around dereferencing file->private_data

Now, I yet have to see other chardevs do any of the above, do that mean
they are all hopelessly racy ?

Cheers,
Ben.


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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2019-01-03  3:27   ` Benjamin Herrenschmidt
@ 2019-01-03  4:26     ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 7+ messages in thread
From: Benjamin Herrenschmidt @ 2019-01-03  4:26 UTC (permalink / raw)
  To: David Howells, Jia-Ju Bai; +Cc: joel, eajames, andrew, linux-kernel

On Thu, 2019-01-03 at 14:27 +1100, Benjamin Herrenschmidt wrote:
> On Wed, 2019-01-02 at 09:34 +0000, David Howells wrote:
> > Jia-Ju Bai <baijiaju1990@gmail.com> wrote:
> > 
> > > +	mutex_lock(&user->file_lock);
> > >  	sbefifo_release_command(user);
> > >  	free_page((unsigned long)user->cmd_page);
> > > +	mutex_unlock(&user->file_lock);
> > 
> > It shouldn't be necessary to do the free_page() call inside the locked
> > section.
> 
> True. However, I didn't realize read/write could be concurrent with
> release so we have another problem.
> 
> I assume when release is called, no new read/write can be issued, I am
> correct ? So all we have to protect against is a read/write that has
> started prior to release being called, right ?

Hrm... looking briefly at the vfs, read/write are wrapped in
fdget/fdput, so release shouldn't happen concurrently or am I missing
something here ?

Cheers,
Ben.



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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2018-12-26 13:56 [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release Jia-Ju Bai
  2019-01-02  9:34 ` David Howells
@ 2019-01-04  0:47 ` Benjamin Herrenschmidt
  2019-01-04  2:26   ` Jia-Ju Bai
  1 sibling, 1 reply; 7+ messages in thread
From: Benjamin Herrenschmidt @ 2019-01-04  0:47 UTC (permalink / raw)
  To: Jia-Ju Bai, dhowells, joel, eajames, andrew; +Cc: linux-kernel

On Wed, 2018-12-26 at 21:56 +0800, Jia-Ju Bai wrote:
> In drivers/fsi/fsi-sbefifo.c, the functions sbefifo_user_release(), 
> sbefifo_user_read() and sbefifo_user_write() may be concurrently executed.

So after refreshing my mind, looking at the code and talking with Al, I
really dont' see what race you are trying to fix here.

read/write should never be concurrent with release for a given file and
the stuff we are protecting here is local to the file instance.

Do you have an actual problem you observed ?

Cheers,
Ben.

> sbefifo_user_release()
>   sbefifo_release_command()
>     vfree(user->pending_cmd);
> 
> sbefifo_user_read()
>   mutex_lock();
>   rc = __sbefifo_submit(sbefifo, user->pending_cmd, ...);
> 
> sbefifo_user_write()
>   mutex_lock();
>   user->pending_cmd = user->cmd_page;
>   user->pending_cmd = vmalloc(len);
> 
> Thus, possible concurrency use-after-free bugs may occur in
> sbefifo_user_release().
> 
> To fix these bugs, the calls to mutex_lock() and mutex_unlock() are
> added in sbefifo_user_release().
> 
> 
> Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
> ---
>  drivers/fsi/fsi-sbefifo.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
> index d92f5b87c251..e278a9014b8f 100644
> --- a/drivers/fsi/fsi-sbefifo.c
> +++ b/drivers/fsi/fsi-sbefifo.c
> @@ -900,8 +900,10 @@ static int sbefifo_user_release(struct inode *inode, struct file *file)
>  	if (!user)
>  		return -EINVAL;
>  
> +	mutex_lock(&user->file_lock);
>  	sbefifo_release_command(user);
>  	free_page((unsigned long)user->cmd_page);
> +	mutex_unlock(&user->file_lock);
>  	kfree(user);
>  
>  	return 0;


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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2019-01-04  0:47 ` Benjamin Herrenschmidt
@ 2019-01-04  2:26   ` Jia-Ju Bai
  2019-01-04  3:26     ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 7+ messages in thread
From: Jia-Ju Bai @ 2019-01-04  2:26 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, dhowells, joel, eajames, andrew; +Cc: linux-kernel



On 2019/1/4 8:47, Benjamin Herrenschmidt wrote:
> On Wed, 2018-12-26 at 21:56 +0800, Jia-Ju Bai wrote:
>> In drivers/fsi/fsi-sbefifo.c, the functions sbefifo_user_release(),
>> sbefifo_user_read() and sbefifo_user_write() may be concurrently executed.
> So after refreshing my mind, looking at the code and talking with Al, I
> really dont' see what race you are trying to fix here.
>
> read/write should never be concurrent with release for a given file and
> the stuff we are protecting here is local to the file instance.
>
> Do you have an actual problem you observed ?
>

Thanks for the reply.

In fact, this report is found by a static tool written by myself, 
instead of real execution.
My tool found that in some drivers, for the structure "struct 
file_operations", the code in intetrfaces ".read" , "write" and 
".release" are protected by the same lock.
The functions kcs_bmc_read(), kcs_bmc_write() and kcs_bmc_release() are 
examples.
Thus, my tool inferred that the intetrfaces ".read" , "write" and 
".release" of "struct file_operations" can be concurrently executed, and 
generated this report.
I manually checked this report, but I was not very sure of it, so I 
marked it as a "possible bug" and reported it.

 From your message, now I know my report is false, and ".read" , "write" 
cannot be concurrently executed with ".release" for a given file.
Sorry for my false report, and thanks for your message.


Best wishes,
Jia-Ju Bai

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

* Re: [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release
  2019-01-04  2:26   ` Jia-Ju Bai
@ 2019-01-04  3:26     ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 7+ messages in thread
From: Benjamin Herrenschmidt @ 2019-01-04  3:26 UTC (permalink / raw)
  To: Jia-Ju Bai, dhowells, joel, eajames, andrew; +Cc: linux-kernel

On Fri, 2019-01-04 at 10:26 +0800, Jia-Ju Bai wrote:
> 
> On 2019/1/4 8:47, Benjamin Herrenschmidt wrote:
> > On Wed, 2018-12-26 at 21:56 +0800, Jia-Ju Bai wrote:
> > > In drivers/fsi/fsi-sbefifo.c, the functions sbefifo_user_release(),
> > > sbefifo_user_read() and sbefifo_user_write() may be concurrently executed.
> > So after refreshing my mind, looking at the code and talking with Al, I
> > really dont' see what race you are trying to fix here.
> > 
> > read/write should never be concurrent with release for a given file and
> > the stuff we are protecting here is local to the file instance.
> > 
> > Do you have an actual problem you observed ?
> > 
> 
> Thanks for the reply.
> 
> In fact, this report is found by a static tool written by myself, 
> instead of real execution.
> My tool found that in some drivers, for the structure "struct 
> file_operations", the code in intetrfaces ".read" , "write" and 
> ".release" are protected by the same lock.
> The functions kcs_bmc_read(), kcs_bmc_write() and kcs_bmc_release() are 
> examples.
> Thus, my tool inferred that the intetrfaces ".read" , "write" and 
> ".release" of "struct file_operations" can be concurrently executed, and 
> generated this report.
> I manually checked this report, but I was not very sure of it, so I 
> marked it as a "possible bug" and reported it.

So what happens is that they cannot be executed concurrently for a
given struct file. But they can be for separate files.

In the fsi-sbefifo case, all of the data and the lock are part of a
private structure which is allocated in open() and thus is per-file
instance, so there should be no race.

In the example you gave, kcs_bmc.c, the data and lock are part of a
per-device (struct kcs_bmc) and thus shared by all file instances. So
in that case, the race does exist.

>  From your message, now I know my report is false, and ".read" , "write" 
> cannot be concurrently executed with ".release" for a given file.
> Sorry for my false report, and thanks for your message.

Right, your tool is valuable as pre-screening but you need in addition
to check (probably manually) whether the data accessed (and lock) are
shared by multiple open file instances or are entirely local to a given
file instance.

Cheers,
Ben.


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

end of thread, other threads:[~2019-01-04  3:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-26 13:56 [PATCH] fsi:fsi-sbefifo: Fix possible concurrency use-after-free bugs in sbefifo_user_release Jia-Ju Bai
2019-01-02  9:34 ` David Howells
2019-01-03  3:27   ` Benjamin Herrenschmidt
2019-01-03  4:26     ` Benjamin Herrenschmidt
2019-01-04  0:47 ` Benjamin Herrenschmidt
2019-01-04  2:26   ` Jia-Ju Bai
2019-01-04  3:26     ` Benjamin Herrenschmidt

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).