]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.27 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 28 Jan 2009 02:03:07 +0000 (18:03 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 28 Jan 2009 02:03:07 +0000 (18:03 -0800)
queue-2.6.27/fuse-destroy-bdi-on-umount.patch [new file with mode: 0644]
queue-2.6.27/fuse-fix-missing-fput-on-error.patch [new file with mode: 0644]
queue-2.6.27/fuse-fix-null-deref-in-fuse_file_alloc.patch [new file with mode: 0644]
queue-2.6.27/inotify-clean-up-inotify_read-and-fix-locking-problems.patch [new file with mode: 0644]
queue-2.6.27/mac80211-decrement-ref-count-to-netdev-after-launching-mesh-discovery.patch [new file with mode: 0644]
queue-2.6.27/series [new file with mode: 0644]
queue-2.6.27/sysfs-fix-problems-with-binary-files.patch [new file with mode: 0644]
queue-2.6.27/x86-mm-fix-pte_free.patch [new file with mode: 0644]

diff --git a/queue-2.6.27/fuse-destroy-bdi-on-umount.patch b/queue-2.6.27/fuse-destroy-bdi-on-umount.patch
new file mode 100644 (file)
index 0000000..ee424a4
--- /dev/null
@@ -0,0 +1,59 @@
+From 26c3679101dbccc054dcf370143941844ba70531 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Mon, 26 Jan 2009 15:00:59 +0100
+Subject: fuse: destroy bdi on umount
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 26c3679101dbccc054dcf370143941844ba70531 upstream.
+
+If a fuse filesystem is unmounted but the device file descriptor
+remains open and a new mount reuses the old device number, then the
+mount fails with EEXIST and the following warning is printed in the
+kernel log:
+
+  WARNING: at fs/sysfs/dir.c:462 sysfs_add_one+0x35/0x3d()
+  sysfs: duplicate filename '0:15' can not be created
+
+The cause is that the bdi belonging to the fuse filesystem was
+destoryed only after the device file was released.  Fix this by
+calling bdi_destroy() from fuse_put_super() instead.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fuse/dev.c   |    3 ++-
+ fs/fuse/inode.c |    2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/fuse/dev.c
++++ b/fs/fuse/dev.c
+@@ -281,7 +281,8 @@ static void request_end(struct fuse_conn
+                       fc->blocked = 0;
+                       wake_up_all(&fc->blocked_waitq);
+               }
+-              if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
++              if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
++                  fc->connected) {
+                       clear_bdi_congested(&fc->bdi, READ);
+                       clear_bdi_congested(&fc->bdi, WRITE);
+               }
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -292,6 +292,7 @@ static void fuse_put_super(struct super_
+       list_del(&fc->entry);
+       fuse_ctl_remove_conn(fc);
+       mutex_unlock(&fuse_mutex);
++      bdi_destroy(&fc->bdi);
+       fuse_conn_put(fc);
+ }
+@@ -531,7 +532,6 @@ void fuse_conn_put(struct fuse_conn *fc)
+               if (fc->destroy_req)
+                       fuse_request_free(fc->destroy_req);
+               mutex_destroy(&fc->inst_mutex);
+-              bdi_destroy(&fc->bdi);
+               kfree(fc);
+       }
+ }
diff --git a/queue-2.6.27/fuse-fix-missing-fput-on-error.patch b/queue-2.6.27/fuse-fix-missing-fput-on-error.patch
new file mode 100644 (file)
index 0000000..bbf8d2a
--- /dev/null
@@ -0,0 +1,40 @@
+From 3ddf1e7f57237ac7c5d5bfb7058f1ea4f970b661 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Mon, 26 Jan 2009 15:00:58 +0100
+Subject: fuse: fix missing fput on error
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 3ddf1e7f57237ac7c5d5bfb7058f1ea4f970b661 upstream.
+
+Fix the leaking file reference if allocation or initialization of
+fuse_conn failed.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fuse/inode.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -832,12 +832,16 @@ static int fuse_fill_super(struct super_
+       if (!file)
+               return -EINVAL;
+-      if (file->f_op != &fuse_dev_operations)
++      if (file->f_op != &fuse_dev_operations) {
++              fput(file);
+               return -EINVAL;
++      }
+       fc = new_conn(sb);
+-      if (!fc)
++      if (!fc) {
++              fput(file);
+               return -ENOMEM;
++      }
+       fc->flags = d.flags;
+       fc->user_id = d.user_id;
diff --git a/queue-2.6.27/fuse-fix-null-deref-in-fuse_file_alloc.patch b/queue-2.6.27/fuse-fix-null-deref-in-fuse_file_alloc.patch
new file mode 100644 (file)
index 0000000..e2fcdc1
--- /dev/null
@@ -0,0 +1,30 @@
+From bb875b38dc5e343bdb696b2eab8233e4d195e208 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <error27@gmail.com>
+Date: Mon, 26 Jan 2009 15:00:58 +0100
+Subject: fuse: fix NULL deref in fuse_file_alloc()
+
+From: Dan Carpenter <error27@gmail.com>
+
+commit bb875b38dc5e343bdb696b2eab8233e4d195e208 upstream.
+
+ff is set to NULL and then dereferenced on line 65.  Compile tested only.
+
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/fuse/file.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -54,7 +54,7 @@ struct fuse_file *fuse_file_alloc(void)
+               ff->reserved_req = fuse_request_alloc();
+               if (!ff->reserved_req) {
+                       kfree(ff);
+-                      ff = NULL;
++                      return NULL;
+               } else {
+                       INIT_LIST_HEAD(&ff->write_entry);
+                       atomic_set(&ff->count, 0);
diff --git a/queue-2.6.27/inotify-clean-up-inotify_read-and-fix-locking-problems.patch b/queue-2.6.27/inotify-clean-up-inotify_read-and-fix-locking-problems.patch
new file mode 100644 (file)
index 0000000..d68d11e
--- /dev/null
@@ -0,0 +1,225 @@
+From 3632dee2f8b8a9720329f29eeaa4ec4669a3aff8 Mon Sep 17 00:00:00 2001
+From: Vegard Nossum <vegard.nossum@gmail.com>
+Date: Thu, 22 Jan 2009 15:29:45 +0100
+Subject: inotify: clean up inotify_read and fix locking problems
+
+From: Vegard Nossum <vegard.nossum@gmail.com>
+
+commit 3632dee2f8b8a9720329f29eeaa4ec4669a3aff8 upstream.
+
+If userspace supplies an invalid pointer to a read() of an inotify
+instance, the inotify device's event list mutex is unlocked twice.
+This causes an unbalance which effectively leaves the data structure
+unprotected, and we can trigger oopses by accessing the inotify
+instance from different tasks concurrently.
+
+The best fix (contributed largely by Linus) is a total rewrite
+of the function in question:
+
+On Thu, Jan 22, 2009 at 7:05 AM, Linus Torvalds wrote:
+> The thing to notice is that:
+>
+>  - locking is done in just one place, and there is no question about it
+>   not having an unlock.
+>
+>  - that whole double-while(1)-loop thing is gone.
+>
+>  - use multiple functions to make nesting and error handling sane
+>
+>  - do error testing after doing the things you always need to do, ie do
+>   this:
+>
+>        mutex_lock(..)
+>        ret = function_call();
+>        mutex_unlock(..)
+>
+>        .. test ret here ..
+>
+>   instead of doing conditional exits with unlocking or freeing.
+>
+> So if the code is written in this way, it may still be buggy, but at least
+> it's not buggy because of subtle "forgot to unlock" or "forgot to free"
+> issues.
+>
+> This _always_ unlocks if it locked, and it always frees if it got a
+> non-error kevent.
+
+Cc: John McCutchan <ttb@tentacle.dhs.org>
+Cc: Robert Love <rlove@google.com>
+Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/inotify_user.c |  135 +++++++++++++++++++++++++++++-------------------------
+ 1 file changed, 74 insertions(+), 61 deletions(-)
+
+--- a/fs/inotify_user.c
++++ b/fs/inotify_user.c
+@@ -427,10 +427,61 @@ static unsigned int inotify_poll(struct 
+       return ret;
+ }
++/*
++ * Get an inotify_kernel_event if one exists and is small
++ * enough to fit in "count". Return an error pointer if
++ * not large enough.
++ *
++ * Called with the device ev_mutex held.
++ */
++static struct inotify_kernel_event *get_one_event(struct inotify_device *dev,
++                                                size_t count)
++{
++      size_t event_size = sizeof(struct inotify_event);
++      struct inotify_kernel_event *kevent;
++
++      if (list_empty(&dev->events))
++              return NULL;
++
++      kevent = inotify_dev_get_event(dev);
++      if (kevent->name)
++              event_size += kevent->event.len;
++
++      if (event_size > count)
++              return ERR_PTR(-EINVAL);
++
++      remove_kevent(dev, kevent);
++      return kevent;
++}
++
++/*
++ * Copy an event to user space, returning how much we copied.
++ *
++ * We already checked that the event size is smaller than the
++ * buffer we had in "get_one_event()" above.
++ */
++static ssize_t copy_event_to_user(struct inotify_kernel_event *kevent,
++                                char __user *buf)
++{
++      size_t event_size = sizeof(struct inotify_event);
++
++      if (copy_to_user(buf, &kevent->event, event_size))
++              return -EFAULT;
++
++      if (kevent->name) {
++              buf += event_size;
++
++              if (copy_to_user(buf, kevent->name, kevent->event.len))
++                      return -EFAULT;
++
++              event_size += kevent->event.len;
++      }
++      return event_size;
++}
++
+ static ssize_t inotify_read(struct file *file, char __user *buf,
+                           size_t count, loff_t *pos)
+ {
+-      size_t event_size = sizeof (struct inotify_event);
+       struct inotify_device *dev;
+       char __user *start;
+       int ret;
+@@ -440,81 +491,43 @@ static ssize_t inotify_read(struct file 
+       dev = file->private_data;
+       while (1) {
++              struct inotify_kernel_event *kevent;
+               prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
+               mutex_lock(&dev->ev_mutex);
+-              if (!list_empty(&dev->events)) {
+-                      ret = 0;
+-                      break;
+-              }
++              kevent = get_one_event(dev, count);
+               mutex_unlock(&dev->ev_mutex);
+-              if (file->f_flags & O_NONBLOCK) {
+-                      ret = -EAGAIN;
+-                      break;
+-              }
+-
+-              if (signal_pending(current)) {
+-                      ret = -EINTR;
+-                      break;
++              if (kevent) {
++                      ret = PTR_ERR(kevent);
++                      if (IS_ERR(kevent))
++                              break;
++                      ret = copy_event_to_user(kevent, buf);
++                      free_kevent(kevent);
++                      if (ret < 0)
++                              break;
++                      buf += ret;
++                      count -= ret;
++                      continue;
+               }
+-              schedule();
+-      }
+-
+-      finish_wait(&dev->wq, &wait);
+-      if (ret)
+-              return ret;
+-
+-      while (1) {
+-              struct inotify_kernel_event *kevent;
+-
+-              ret = buf - start;
+-              if (list_empty(&dev->events))
++              ret = -EAGAIN;
++              if (file->f_flags & O_NONBLOCK)
+                       break;
+-
+-              kevent = inotify_dev_get_event(dev);
+-              if (event_size + kevent->event.len > count) {
+-                      if (ret == 0 && count > 0) {
+-                              /*
+-                               * could not get a single event because we
+-                               * didn't have enough buffer space.
+-                               */
+-                              ret = -EINVAL;
+-                      }
++              ret = -EINTR;
++              if (signal_pending(current))
+                       break;
+-              }
+-              remove_kevent(dev, kevent);
+-              /*
+-               * Must perform the copy_to_user outside the mutex in order
+-               * to avoid a lock order reversal with mmap_sem.
+-               */
+-              mutex_unlock(&dev->ev_mutex);
+-
+-              if (copy_to_user(buf, &kevent->event, event_size)) {
+-                      ret = -EFAULT;
++              if (start != buf)
+                       break;
+-              }
+-              buf += event_size;
+-              count -= event_size;
+-
+-              if (kevent->name) {
+-                      if (copy_to_user(buf, kevent->name, kevent->event.len)){
+-                              ret = -EFAULT;
+-                              break;
+-                      }
+-                      buf += kevent->event.len;
+-                      count -= kevent->event.len;
+-              }
+-              free_kevent(kevent);
+-
+-              mutex_lock(&dev->ev_mutex);
++              schedule();
+       }
+-      mutex_unlock(&dev->ev_mutex);
++      finish_wait(&dev->wq, &wait);
++      if (start != buf && ret != -EFAULT)
++              ret = buf - start;
+       return ret;
+ }
diff --git a/queue-2.6.27/mac80211-decrement-ref-count-to-netdev-after-launching-mesh-discovery.patch b/queue-2.6.27/mac80211-decrement-ref-count-to-netdev-after-launching-mesh-discovery.patch
new file mode 100644 (file)
index 0000000..26b815d
--- /dev/null
@@ -0,0 +1,36 @@
+From 5dc306f3bd1d4cfdf79df39221b3036eab1ddcf3 Mon Sep 17 00:00:00 2001
+From: Brian Cavagnolo <brian@cozybit.com>
+Date: Fri, 16 Jan 2009 19:04:49 -0800
+Subject: mac80211: decrement ref count to netdev after launching mesh discovery
+
+From: Brian Cavagnolo <brian@cozybit.com>
+
+commit 5dc306f3bd1d4cfdf79df39221b3036eab1ddcf3 upstream.
+
+After launching mesh discovery in tx path, reference count was not being
+decremented.  This was preventing module unload.
+
+Signed-off-by: Brian Cavagnolo <brian@cozybit.com>
+Signed-off-by: Andrey Yurovsky <andrey@cozybit.com>
+Acked-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/mac80211/tx.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1335,8 +1335,10 @@ int ieee80211_master_start_xmit(struct s
+                       if (is_multicast_ether_addr(hdr->addr3))
+                               memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
+                       else
+-                              if (mesh_nexthop_lookup(skb, odev))
++                              if (mesh_nexthop_lookup(skb, odev)) {
++                                      dev_put(odev);
+                                       return  0;
++                              }
+                       if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
+                               IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta,
+                                                            fwded_frames);
diff --git a/queue-2.6.27/series b/queue-2.6.27/series
new file mode 100644 (file)
index 0000000..fa9c66b
--- /dev/null
@@ -0,0 +1,7 @@
+fuse-destroy-bdi-on-umount.patch
+fuse-fix-missing-fput-on-error.patch
+fuse-fix-null-deref-in-fuse_file_alloc.patch
+inotify-clean-up-inotify_read-and-fix-locking-problems.patch
+mac80211-decrement-ref-count-to-netdev-after-launching-mesh-discovery.patch
+sysfs-fix-problems-with-binary-files.patch
+x86-mm-fix-pte_free.patch
diff --git a/queue-2.6.27/sysfs-fix-problems-with-binary-files.patch b/queue-2.6.27/sysfs-fix-problems-with-binary-files.patch
new file mode 100644 (file)
index 0000000..bc60586
--- /dev/null
@@ -0,0 +1,44 @@
+From 4503efd0891c40e30928afb4b23dc3f99c62a6b2 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Tue, 20 Jan 2009 15:51:16 -0800
+Subject: sysfs: fix problems with binary files
+
+From: Greg Kroah-Hartman <gregkh@suse.de>
+
+commit 4503efd0891c40e30928afb4b23dc3f99c62a6b2 upstream.
+
+Some sysfs binary files don't like having 0 passed to them as a size.
+Fix this up at the root by just returning to the vfs if userspace asks
+us for a zero sized buffer.
+
+Thanks to Pavel Roskin for pointing this out.
+
+Reported-by: Pavel Roskin <proski@gnu.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/sysfs/bin.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/sysfs/bin.c
++++ b/fs/sysfs/bin.c
+@@ -62,6 +62,9 @@ read(struct file *file, char __user *use
+       loff_t offs = *off;
+       int count = min_t(size_t, bytes, PAGE_SIZE);
++      if (!bytes)
++              return 0;
++
+       if (size) {
+               if (offs > size)
+                       return 0;
+@@ -119,6 +122,9 @@ static ssize_t write(struct file *file, 
+       loff_t offs = *off;
+       int count = min_t(size_t, bytes, PAGE_SIZE);
++      if (!bytes)
++              return 0;
++
+       if (size) {
+               if (offs > size)
+                       return 0;
diff --git a/queue-2.6.27/x86-mm-fix-pte_free.patch b/queue-2.6.27/x86-mm-fix-pte_free.patch
new file mode 100644 (file)
index 0000000..e5649d4
--- /dev/null
@@ -0,0 +1,74 @@
+From 42ef73fe134732b2e91c0326df5fd568da17c4b2 Mon Sep 17 00:00:00 2001
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Fri, 23 Jan 2009 17:37:49 +0100
+Subject: x86, mm: fix pte_free()
+
+From: Peter Zijlstra <peterz@infradead.org>
+
+commit 42ef73fe134732b2e91c0326df5fd568da17c4b2 upstream.
+
+On -rt we were seeing spurious bad page states like:
+
+Bad page state in process 'firefox'
+page:c1bc2380 flags:0x40000000 mapping:c1bc2390 mapcount:0 count:0
+Trying to fix it up, but a reboot is needed
+Backtrace:
+Pid: 503, comm: firefox Not tainted 2.6.26.8-rt13 #3
+[<c043d0f3>] ? printk+0x14/0x19
+[<c0272d4e>] bad_page+0x4e/0x79
+[<c0273831>] free_hot_cold_page+0x5b/0x1d3
+[<c02739f6>] free_hot_page+0xf/0x11
+[<c0273a18>] __free_pages+0x20/0x2b
+[<c027d170>] __pte_alloc+0x87/0x91
+[<c027d25e>] handle_mm_fault+0xe4/0x733
+[<c043f680>] ? rt_mutex_down_read_trylock+0x57/0x63
+[<c043f680>] ? rt_mutex_down_read_trylock+0x57/0x63
+[<c0218875>] do_page_fault+0x36f/0x88a
+
+This is the case where a concurrent fault already installed the PTE and
+we get to free the newly allocated one.
+
+This is due to pgtable_page_ctor() doing the spin_lock_init(&page->ptl)
+which is overlaid with the {private, mapping} struct.
+
+union {
+    struct {
+        unsigned long private;
+        struct address_space *mapping;
+    };
+    spinlock_t ptl;
+    struct kmem_cache *slab;
+    struct page *first_page;
+};
+
+Normally the spinlock is small enough to not stomp on page->mapping, but
+PREEMPT_RT=y has huge 'spin'locks.
+
+But lockdep kernels should also be able to trigger this splat, as the
+lock tracking code grows the spinlock to cover page->mapping.
+
+The obvious fix is calling pgtable_page_dtor() like the regular pte free
+path __pte_free_tlb() does.
+
+It seems all architectures except x86 and nm10300 already do this, and
+nm10300 doesn't seem to use pgtable_page_ctor(), which suggests it
+doesn't do SMP or simply doesnt do MMU at all or something.
+
+Signed-off-by: Peter Zijlstra <a.p.zijlsta@chello.nl>
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/asm-x86/pgalloc.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/asm-x86/pgalloc.h
++++ b/include/asm-x86/pgalloc.h
+@@ -42,6 +42,7 @@ static inline void pte_free_kernel(struc
+ static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
++      pgtable_page_dtor(pte);
+       __free_page(pte);
+ }