cifs: fix use-after-free bug in find_writable_file
Subsystems (2)
PATCH 1/1 cifs: fix use-after-free bug in find_writable_file
Under intermittent network outages, find_writable_file() is susceptible to the following race condition, which results in a user-after-free in the cifs_writepages code-path:
Thread 1 Thread 2
======== ========
inv_file = NULL
refind = 0spin_lock(&cifs_file_list_lock)
// invalidHandle found on openFileList
inv_file = open_file
// inv_file->count currently 1
cifsFileInfo_get(inv_file)
// inv_file->count = 2
spin_unlock(&cifs_file_list_lock);
cifs_reopen_file() cifs_close()
// fails (rc != 0) ->cifsFileInfo_put()
spin_lock(&cifs_file_list_lock)
// inv_file->count = 1
spin_unlock(&cifs_file_list_lock)spin_lock(&cifs_file_list_lock);
list_move_tail(&inv_file->flist,
&cifs_inode->openFileList);
spin_unlock(&cifs_file_list_lock);
cifsFileInfo_put(inv_file);
->spin_lock(&cifs_file_list_lock)
// inv_file->count = 0 list_del(&cifs_file->flist); // cleanup!! kfree(cifs_file); spin_unlock(&cifs_file_list_lock);
spin_lock(&cifs_file_list_lock);
++refind;
// refind = 1
goto refind_writable;
At this point we loop back through with an invalid inv_file pointer and a refind value of 1. On second pass, inv_file is not overwritten on openFileList traversal, and is subsequently dereferenced.
--- fs/cifs/file.c | 1 + 1 file changed, 1 insertion(+)
fs/cifs/file.c +1 -0
@@ -1823,6 +1823,7 @@ refind_writable:cifsFileInfo_put (inv_file);spin_lock (&cifs_file_list_lock); ++refind; + inv_file =NULL ; goto refind_writable; } }
Signature · 1 line
2.1.4
A message that is not in the archive (sent off-list or not yet received): 1426252829-31444-1-git-send-email-ddiss-l3A5Bk7waGM@public.gmane.org
Jeff Layton
Reviewed-byQuoted 61 lines · On Fri, 13 Mar 2015 14:20:29 +0100 David Disseldorp…
Under intermittent network outages,
find_writable_file()is susceptible to the following race condition, which results in a user-after-free in thecifs_writepagescode-path:Thread 1 Thread 2
======== ========
inv_file= NULL
refind = 0spin_lock(&cifs_file_list_lock)// invalidHandle found on openFileList
inv_file=open_file
//inv_file->countcurrently 1
cifsFileInfo_get(inv_file)
//inv_file->count= 2
spin_unlock(&cifs_file_list_lock);
cifs_reopen_file()cifs_close()
// fails (rc != 0) ->cifsFileInfo_put()spin_lock(&cifs_file_list_lock) // inv_file->count = 1 spin_unlock(&cifs_file_list_lock)
spin_lock(&cifs_file_list_lock);
list_move_tail(&inv_file->flist,&cifs_inode->openFileList);
spin_unlock(&cifs_file_list_lock);
cifsFileInfo_put(inv_file);
->spin_lock(&cifs_file_list_lock)// inv_file->count = 0 list_del(&cifs_file->flist); // cleanup!! kfree(cifs_file); spin_unlock(&cifs_file_list_lock);
spin_lock(&cifs_file_list_lock);
++refind;
// refind = 1
gotorefind_writable;At this point we loop back through with an invalid
inv_filepointer and a refind value of 1. On second pass,inv_fileis not overwritten on openFileList traversal, and is subsequently dereferenced.Signed-off-by David Disseldorp <[email protected]>--- fs/cifs/file.c | 1 + 1 file changed, 1 insertion(+)fs/cifs/file.c +0
-0
fs/cifs/file.c refind_writable: · line 1829
Quoted 7 lines
fs/cifs/file.c +1
-0@@ -1823,6 +1823,7 @@ refind_writable:cifsFileInfo_put (inv_file);spin_lock (&cifs_file_list_lock); ++refind; + inv_file =NULL ; goto refind_writable; } }
Looks right. Probably also a stable candidate?
A message that is not in the archive (sent off-list or not yet received): 20150314084523.7c615d42-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org
Steve French
Appliedmerged into cifs-2.6.git
added cc:stable
Quoted 79 lines · Jeff Layton
Quoted 61 lines · On Fri, 13 Mar 2015 14:20:29 +0100 David Disseldorp…
Under intermittent network outages,
find_writable_file()is susceptible to the following race condition, which results in a user-after-free in thecifs_writepagescode-path:Thread 1 Thread 2
======== ========
inv_file= NULL
refind = 0spin_lock(&cifs_file_list_lock)// invalidHandle found on openFileList
inv_file=open_file
//inv_file->countcurrently 1
cifsFileInfo_get(inv_file)
//inv_file->count= 2
spin_unlock(&cifs_file_list_lock);
cifs_reopen_file()cifs_close()
// fails (rc != 0) ->cifsFileInfo_put()spin_lock(&cifs_file_list_lock) // inv_file->count = 1 spin_unlock(&cifs_file_list_lock)
spin_lock(&cifs_file_list_lock);
list_move_tail(&inv_file->flist,&cifs_inode->openFileList);
spin_unlock(&cifs_file_list_lock);
cifsFileInfo_put(inv_file);
->spin_lock(&cifs_file_list_lock)// inv_file->count = 0 list_del(&cifs_file->flist); // cleanup!! kfree(cifs_file); spin_unlock(&cifs_file_list_lock);
spin_lock(&cifs_file_list_lock);
++refind;
// refind = 1
gotorefind_writable;At this point we loop back through with an invalid
inv_filepointer and a refind value of 1. On second pass,inv_fileis not overwritten on openFileList traversal, and is subsequently dereferenced.Signed-off-by David Disseldorp <[email protected]>--- fs/cifs/file.c | 1 + 1 file changed, 1 insertion(+)fs/cifs/file.c +0
-0fs/cifs/file.c refind_writable: · line 1829
Quoted 7 lines
fs/cifs/file.c +1
-0@@ -1823,6 +1823,7 @@ refind_writable:cifsFileInfo_put (inv_file);spin_lock (&cifs_file_list_lock); ++refind; + inv_file =NULL ; goto refind_writable; } }Looks right. Probably also a stable candidate?
Reviewed-by Jeff Layton <[email protected]>--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 3 lines
Thanks, Steve