]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2014 00:34:31 +0000 (16:34 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2014 00:34:31 +0000 (16:34 -0800)
added patches:
hpfs-deadlock-and-race-in-directory-lseek.patch

queue-3.4/hpfs-deadlock-and-race-in-directory-lseek.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/hpfs-deadlock-and-race-in-directory-lseek.patch b/queue-3.4/hpfs-deadlock-and-race-in-directory-lseek.patch
new file mode 100644 (file)
index 0000000..27f70d7
--- /dev/null
@@ -0,0 +1,61 @@
+From 31abdab9c11bb1694ecd1476a7edbe8e964d94ac Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 18 May 2013 02:38:52 -0400
+Subject: hpfs: deadlock and race in directory lseek()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 31abdab9c11bb1694ecd1476a7edbe8e964d94ac upstream.
+
+For one thing, there's an ABBA deadlock on hpfs fs-wide lock and i_mutex
+in hpfs_dir_lseek() - there's a lot of methods that grab the former with
+the caller already holding the latter, so it must take i_mutex first.
+
+For another, locking the damn thing, carefully validating the offset,
+then dropping locks and assigning the offset is obviously racy.
+
+Moreover, we _must_ do hpfs_add_pos(), or the machinery in dnode.c
+won't modify the sucker on B-tree surgeries.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hpfs/dir.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/hpfs/dir.c
++++ b/fs/hpfs/dir.c
+@@ -33,25 +33,27 @@ static loff_t hpfs_dir_lseek(struct file
+       if (whence == SEEK_DATA || whence == SEEK_HOLE)
+               return -EINVAL;
++      mutex_lock(&i->i_mutex);
+       hpfs_lock(s);
+       /*printk("dir lseek\n");*/
+       if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
+-      mutex_lock(&i->i_mutex);
+       pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
+       while (pos != new_off) {
+               if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
+               else goto fail;
+               if (pos == 12) goto fail;
+       }
+-      mutex_unlock(&i->i_mutex);
++      hpfs_add_pos(i, &filp->f_pos);
+ ok:
++      filp->f_pos = new_off;
+       hpfs_unlock(s);
+-      return filp->f_pos = new_off;
+-fail:
+       mutex_unlock(&i->i_mutex);
++      return new_off;
++fail:
+       /*printk("illegal lseek: %016llx\n", new_off);*/
+       hpfs_unlock(s);
++      mutex_unlock(&i->i_mutex);
+       return -ESPIPE;
+ }
index b0930ed45f2194e1699c517416beb1483a43de26..c86d09fae9eae3aa55c3938268e6bd0e661ae136 100644 (file)
@@ -20,3 +20,4 @@ drm-radeon-skip-colorbuffer-checking-if-color_info.format-is-set-to-invalid.patc
 drm-radeon-set-the-full-cache-bit-for-fences-on-r7xx.patch
 drm-radeon-dce4-clear-bios-scratch-dpms-bit-v2.patch
 pci-enable-ari-if-dev-and-upstream-bridge-support-it-disable-otherwise.patch
+hpfs-deadlock-and-race-in-directory-lseek.patch