All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cifs: guard against entries being deleted from open file list
@ 2011-04-18 13:44 shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w
       [not found] ` <1303134275-12587-1-git-send-email-shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w @ 2011-04-18 13:44 UTC (permalink / raw)
  To: smfrench-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA, Shirish Pargaonkar

From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>


It is possible that a close can occur while a file is
being reopened which can result in list entry deleted
from the list and an oops.
Use list_for_each_entry_safe instead.


Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 fs/cifs/file.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index faf5952..aa29167 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
 					bool fsuid_only)
 {
-	struct cifsFileInfo *open_file;
+	struct cifsFileInfo *open_file, *tmpf;
 	struct cifs_sb_info *cifs_sb;
 	bool any_available = false;
 	int rc;
@@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
 
 	spin_lock(&cifs_file_list_lock);
 refind_writable:
-	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
+	list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
+									flist) {
 		if (!any_available && open_file->pid != current->tgid)
 			continue;
 		if (fsuid_only && open_file->uid != current_fsuid())
-- 
1.6.0.2

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

* Re: [PATCH] cifs: guard against entries being deleted from open file list
       [not found] ` <1303134275-12587-1-git-send-email-shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2011-04-18 14:21   ` Steve French
       [not found]     ` <BANLkTi=dVQt1GQmrG+x0PF8Akq_hbvE7cQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2011-04-18 14:50   ` Jeff Layton
  1 sibling, 1 reply; 6+ messages in thread
From: Steve French @ 2011-04-18 14:21 UTC (permalink / raw)
  To: shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

Is there a reproduction scenario or bug report for this (or was it
noted by inspection)?

On Mon, Apr 18, 2011 at 8:44 AM,  <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>
>
> It is possible that a close can occur while a file is
> being reopened which can result in list entry deleted
> from the list and an oops.
> Use list_for_each_entry_safe instead.
>
>
> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  fs/cifs/file.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index faf5952..aa29167 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
>  struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>                                        bool fsuid_only)
>  {
> -       struct cifsFileInfo *open_file;
> +       struct cifsFileInfo *open_file, *tmpf;
>        struct cifs_sb_info *cifs_sb;
>        bool any_available = false;
>        int rc;
> @@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>
>        spin_lock(&cifs_file_list_lock);
>  refind_writable:
> -       list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> +       list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
> +                                                                       flist) {
>                if (!any_available && open_file->pid != current->tgid)
>                        continue;
>                if (fsuid_only && open_file->uid != current_fsuid())
> --
> 1.6.0.2
>
>



-- 
Thanks,

Steve

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

* Re: [PATCH] cifs: guard against entries being deleted from open file list
       [not found]     ` <BANLkTi=dVQt1GQmrG+x0PF8Akq_hbvE7cQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-04-18 14:24       ` Shirish Pargaonkar
  0 siblings, 0 replies; 6+ messages in thread
From: Shirish Pargaonkar @ 2011-04-18 14:24 UTC (permalink / raw)
  To: Steve French; +Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Mon, Apr 18, 2011 at 9:21 AM, Steve French <smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Is there a reproduction scenario or bug report for this (or was it
> noted by inspection)?
>
> On Mon, Apr 18, 2011 at 8:44 AM,  <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>
>>
>> It is possible that a close can occur while a file is
>> being reopened which can result in list entry deleted
>> from the list and an oops.
>> Use list_for_each_entry_safe instead.
>>
>>
>> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>  fs/cifs/file.c |    5 +++--
>>  1 files changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index faf5952..aa29167 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
>>  struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>>                                        bool fsuid_only)
>>  {
>> -       struct cifsFileInfo *open_file;
>> +       struct cifsFileInfo *open_file, *tmpf;
>>        struct cifs_sb_info *cifs_sb;
>>        bool any_available = false;
>>        int rc;
>> @@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>>
>>        spin_lock(&cifs_file_list_lock);
>>  refind_writable:
>> -       list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
>> +       list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
>> +                                                                       flist) {
>>                if (!any_available && open_file->pid != current->tgid)
>>                        continue;
>>                if (fsuid_only && open_file->uid != current_fsuid())
>> --
>> 1.6.0.2
>>
>>
>
>
>
> --
> Thanks,
>
> Steve
>

Steve,

IBM internal bugzilla 71379.

I think a stressed CIFS/SMB server can make cifs client this way!
Perhaps harder to recreate strating 1.69 version of cifs
(which has Jeff's patches for a slow server).

Regards,

Shirish

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

* Re: [PATCH] cifs: guard against entries being deleted from open file list
       [not found] ` <1303134275-12587-1-git-send-email-shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2011-04-18 14:21   ` Steve French
@ 2011-04-18 14:50   ` Jeff Layton
       [not found]     ` <20110418105025.2b62fa69-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
  1 sibling, 1 reply; 6+ messages in thread
From: Jeff Layton @ 2011-04-18 14:50 UTC (permalink / raw)
  To: shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Mon, 18 Apr 2011 08:44:35 -0500
shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:

> From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> 
> 
> It is possible that a close can occur while a file is
> being reopened which can result in list entry deleted
> from the list and an oops.
> Use list_for_each_entry_safe instead.
> 
> 
> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  fs/cifs/file.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index faf5952..aa29167 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
>  struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>  					bool fsuid_only)
>  {
> -	struct cifsFileInfo *open_file;
> +	struct cifsFileInfo *open_file, *tmpf;
>  	struct cifs_sb_info *cifs_sb;
>  	bool any_available = false;
>  	int rc;
> @@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>  
>  	spin_lock(&cifs_file_list_lock);
>  refind_writable:
> -	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> +	list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
> +									flist) {
>  		if (!any_available && open_file->pid != current->tgid)
>  			continue;
>  		if (fsuid_only && open_file->uid != current_fsuid())

I don't think this is a real fix for this problem, and may cause other
issues. list_for_each_entry_safe is only protects you when you are
iterating over a list (usually while holding a lock) and removing those
entries. The *_safe part makes it ok to remove the entry that you're
currently dealing with from the list.

Now, that can happen if you find an entry, do a cifsFileInfo_get, drop
the spinlock and then calling cifsFileInfo_put and putting the last
reference afterward. Here's the problem though -- once you drop the
spinlock, there's nothing that says that the next entry in the list is
necessarily still valid once you move to that entry.

What if the entry *after* the one that you're currently dealing with is
removed from the list while you're iterating over it? This patch will
cause an oops in that situation now when it didn't before. So, I think
this patch will probably just trade one set of problems for another.

I think the real fix is overhauling how all of the reopen_file stuff
works, but fixing it looks anything but straightforward.

-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

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

* Re: [PATCH] cifs: guard against entries being deleted from open file list
       [not found]     ` <20110418105025.2b62fa69-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
@ 2011-04-19  3:02       ` Shirish Pargaonkar
       [not found]         ` <BANLkTimuLqbz6fj9SuV+_3KmuJ9Keh_9hg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Shirish Pargaonkar @ 2011-04-19  3:02 UTC (permalink / raw)
  To: Jeff Layton
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Mon, Apr 18, 2011 at 9:50 AM, Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> On Mon, 18 Apr 2011 08:44:35 -0500
> shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
>
>> From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>
>>
>> It is possible that a close can occur while a file is
>> being reopened which can result in list entry deleted
>> from the list and an oops.
>> Use list_for_each_entry_safe instead.
>>
>>
>> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> ---
>>  fs/cifs/file.c |    5 +++--
>>  1 files changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
>> index faf5952..aa29167 100644
>> --- a/fs/cifs/file.c
>> +++ b/fs/cifs/file.c
>> @@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
>>  struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>>                                       bool fsuid_only)
>>  {
>> -     struct cifsFileInfo *open_file;
>> +     struct cifsFileInfo *open_file, *tmpf;
>>       struct cifs_sb_info *cifs_sb;
>>       bool any_available = false;
>>       int rc;
>> @@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
>>
>>       spin_lock(&cifs_file_list_lock);
>>  refind_writable:
>> -     list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
>> +     list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
>> +                                                                     flist) {
>>               if (!any_available && open_file->pid != current->tgid)
>>                       continue;
>>               if (fsuid_only && open_file->uid != current_fsuid())
>
> I don't think this is a real fix for this problem, and may cause other
> issues. list_for_each_entry_safe is only protects you when you are
> iterating over a list (usually while holding a lock) and removing those
> entries. The *_safe part makes it ok to remove the entry that you're
> currently dealing with from the list.
>
> Now, that can happen if you find an entry, do a cifsFileInfo_get, drop
> the spinlock and then calling cifsFileInfo_put and putting the last
> reference afterward. Here's the problem though -- once you drop the
> spinlock, there's nothing that says that the next entry in the list is
> necessarily still valid once you move to that entry.
>
> What if the entry *after* the one that you're currently dealing with is
> removed from the list while you're iterating over it? This patch will
> cause an oops in that situation now when it didn't before. So, I think
> this patch will probably just trade one set of problems for another.
>
> I think the real fix is overhauling how all of the reopen_file stuff
> works, but fixing it looks anything but straightforward.
>
> --
> Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
>

Jeff, I do not mind taking a stab at it.  Do you have suggestsion/ideas
about how to approach it?

Regards,

Shirish

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

* Re: [PATCH] cifs: guard against entries being deleted from open file list
       [not found]         ` <BANLkTimuLqbz6fj9SuV+_3KmuJ9Keh_9hg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2011-04-19 11:49           ` Jeff Layton
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Layton @ 2011-04-19 11:49 UTC (permalink / raw)
  To: Shirish Pargaonkar
  Cc: smfrench-Re5JQEeQqe8AvxtiuMwx3w, linux-cifs-u79uwXL29TY76Z2rM5mHXA

On Mon, 18 Apr 2011 22:02:21 -0500
Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:

> On Mon, Apr 18, 2011 at 9:50 AM, Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> > On Mon, 18 Apr 2011 08:44:35 -0500
> > shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org wrote:
> >
> >> From: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >>
> >>
> >> It is possible that a close can occur while a file is
> >> being reopened which can result in list entry deleted
> >> from the list and an oops.
> >> Use list_for_each_entry_safe instead.
> >>
> >>
> >> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> >> ---
> >>  fs/cifs/file.c |    5 +++--
> >>  1 files changed, 3 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> >> index faf5952..aa29167 100644
> >> --- a/fs/cifs/file.c
> >> +++ b/fs/cifs/file.c
> >> @@ -1056,7 +1056,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
> >>  struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
> >>                                       bool fsuid_only)
> >>  {
> >> -     struct cifsFileInfo *open_file;
> >> +     struct cifsFileInfo *open_file, *tmpf;
> >>       struct cifs_sb_info *cifs_sb;
> >>       bool any_available = false;
> >>       int rc;
> >> @@ -1079,7 +1079,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
> >>
> >>       spin_lock(&cifs_file_list_lock);
> >>  refind_writable:
> >> -     list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
> >> +     list_for_each_entry_safe(open_file, tmpf, &cifs_inode->openFileList,
> >> +                                                                     flist) {
> >>               if (!any_available && open_file->pid != current->tgid)
> >>                       continue;
> >>               if (fsuid_only && open_file->uid != current_fsuid())
> >
> > I don't think this is a real fix for this problem, and may cause other
> > issues. list_for_each_entry_safe is only protects you when you are
> > iterating over a list (usually while holding a lock) and removing those
> > entries. The *_safe part makes it ok to remove the entry that you're
> > currently dealing with from the list.
> >
> > Now, that can happen if you find an entry, do a cifsFileInfo_get, drop
> > the spinlock and then calling cifsFileInfo_put and putting the last
> > reference afterward. Here's the problem though -- once you drop the
> > spinlock, there's nothing that says that the next entry in the list is
> > necessarily still valid once you move to that entry.
> >
> > What if the entry *after* the one that you're currently dealing with is
> > removed from the list while you're iterating over it? This patch will
> > cause an oops in that situation now when it didn't before. So, I think
> > this patch will probably just trade one set of problems for another.
> >
> > I think the real fix is overhauling how all of the reopen_file stuff
> > works, but fixing it looks anything but straightforward.
> >
> > --
> > Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
> >
> 
> Jeff, I do not mind taking a stab at it.  Do you have suggestsion/ideas
> about how to approach it?
> 

One idea might be to break up the openFileList into two lists. One for
valid handles and one for invalid ones. When you mark the file invalid,
move it to the other list.

When calling find_writable_file, walk the list of valid handles first,
and then walk the other list and start reclaiming filehandles and
moving them back to the openFileList if you don't find one on the first
pass.

Getting the locking right on all of that will be "fun", though.

While you're at it, it might also be a good time to get rid of some of
these global locks. The cifs_file_list_lock for instance could probably
stand to be more granular.

Some of the callers of find_writable_file could also be eliminated --
the ones in the setattr codepath, specifically by having them use
iattr->ia_file field.

It also wouldn't hurt to merge find_readable_file and
find_writable_file into a single function that takes a fmode_t argument.

Or, consider something more general -- a generic filehandle acquisition
layer that looks for open files that meet criteria that can be used by
any opener or current caller of find_*_file.

The possibilities for glory are endless here...

-- 
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>

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

end of thread, other threads:[~2011-04-19 11:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-18 13:44 [PATCH] cifs: guard against entries being deleted from open file list shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w
     [not found] ` <1303134275-12587-1-git-send-email-shirishpargaonkar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2011-04-18 14:21   ` Steve French
     [not found]     ` <BANLkTi=dVQt1GQmrG+x0PF8Akq_hbvE7cQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-04-18 14:24       ` Shirish Pargaonkar
2011-04-18 14:50   ` Jeff Layton
     [not found]     ` <20110418105025.2b62fa69-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2011-04-19  3:02       ` Shirish Pargaonkar
     [not found]         ` <BANLkTimuLqbz6fj9SuV+_3KmuJ9Keh_9hg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-04-19 11:49           ` Jeff Layton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.