]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more .32 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Fri, 29 Jan 2010 19:37:47 +0000 (11:37 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 29 Jan 2010 19:37:47 +0000 (11:37 -0800)
20 files changed:
queue-2.6.32/drm-i915-add-acpi-opregion-support-for-ironlake.patch [new file with mode: 0644]
queue-2.6.32/drm-i915-add-display-hotplug-event-on-ironlake.patch [new file with mode: 0644]
queue-2.6.32/drm-i915-reload-hangcheck-timer-too-for-ironlake.patch [new file with mode: 0644]
queue-2.6.32/e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch [new file with mode: 0644]
queue-2.6.32/e1000-enhance-frame-fragment-detection.patch [new file with mode: 0644]
queue-2.6.32/e1000e-enhance-frame-fragment-detection.patch [new file with mode: 0644]
queue-2.6.32/fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch [new file with mode: 0644]
queue-2.6.32/fix-a-leak-in-affs_fill_super.patch [new file with mode: 0644]
queue-2.6.32/fix-affs-parse_options.patch [new file with mode: 0644]
queue-2.6.32/fix-failure-exit-in-ipathfs.patch [new file with mode: 0644]
queue-2.6.32/fix-failure-exits-in-bfs_fill_super.patch [new file with mode: 0644]
queue-2.6.32/fix-leak-in-romfs_fill_super.patch [new file with mode: 0644]
queue-2.6.32/fix-oops-in-fs-9p-late-mount-failure.patch [new file with mode: 0644]
queue-2.6.32/fix-remount-races-with-symlink-handling-in-affs.patch [new file with mode: 0644]
queue-2.6.32/input-winbond-cir-remove-dmesg-spam.patch [new file with mode: 0644]
queue-2.6.32/mm-fix-migratetype-bug-which-slowed-swapping.patch [new file with mode: 0644]
queue-2.6.32/series
queue-2.6.32/sparc-tif_abi_pending-bit-removal.patch [new file with mode: 0644]
queue-2.6.32/split-flush_old_exec-into-two-functions.patch [new file with mode: 0644]
queue-2.6.32/x86-get-rid-of-the-insane-tif_abi_pending-bit.patch [new file with mode: 0644]

diff --git a/queue-2.6.32/drm-i915-add-acpi-opregion-support-for-ironlake.patch b/queue-2.6.32/drm-i915-add-acpi-opregion-support-for-ironlake.patch
new file mode 100644 (file)
index 0000000..2f059a4
--- /dev/null
@@ -0,0 +1,213 @@
+From sconklin@canonical.com  Fri Jan 29 11:11:00 2010
+From: Steve Conklin <sconklin@canonical.com>
+Date: Fri, 29 Jan 2010 12:55:46 -0600
+Subject: drm/i915: Add ACPI OpRegion support for Ironlake
+To: stable@kernel.org
+Cc: Zhao Yakui <yakui.zhao@intel.com>, Eric Anholt <eric@anholt.net>, Steve Conklin <sconklin@canonical.com>, Zhenyu Wang <zhenyuw@linux.intel.com>
+Message-ID: <1264791346-8113-1-git-send-email-sconklin@canonical.com>
+
+
+commit 01c66889c14aa163c49355b3be2ccfb214500599 upstream
+
+Add the support of ACPI opregion on Ironlake so that the backlight
+brightness can be adjusted by using ACPI interface
+   >/sys/class/backlight/acpi_video0/brightness
+
+Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Steve Conklin <sconklin@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/gpu/drm/i915/i915_dma.c      |    7 ---
+ drivers/gpu/drm/i915/i915_drv.h      |    3 +
+ drivers/gpu/drm/i915/i915_irq.c      |   19 ++++++++
+ drivers/gpu/drm/i915/i915_opregion.c |   74 ++++++++++++++++++++++++++++++++++-
+ 4 files changed, 95 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_dma.c
++++ b/drivers/gpu/drm/i915/i915_dma.c
+@@ -1490,9 +1490,7 @@ int i915_driver_load(struct drm_device *
+       }
+       /* Must be done after probing outputs */
+-      /* FIXME: verify on IGDNG */
+-      if (!IS_IGDNG(dev))
+-              intel_opregion_init(dev, 0);
++      intel_opregion_init(dev, 0);
+       setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
+                   (unsigned long) dev);
+@@ -1536,8 +1534,7 @@ int i915_driver_unload(struct drm_device
+       if (dev_priv->regs != NULL)
+               iounmap(dev_priv->regs);
+-      if (!IS_IGDNG(dev))
+-              intel_opregion_free(dev, 0);
++      intel_opregion_free(dev, 0);
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               intel_modeset_cleanup(dev);
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -739,6 +739,7 @@ i915_enable_pipestat(drm_i915_private_t 
+ void
+ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
++void intel_enable_asle (struct drm_device *dev);
+ /* i915_mem.c */
+ extern int i915_mem_alloc(struct drm_device *dev, void *data,
+@@ -864,11 +865,13 @@ extern int i915_restore_state(struct drm
+ extern int intel_opregion_init(struct drm_device *dev, int resume);
+ extern void intel_opregion_free(struct drm_device *dev, int suspend);
+ extern void opregion_asle_intr(struct drm_device *dev);
++extern void ironlake_opregion_gse_intr(struct drm_device *dev);
+ extern void opregion_enable_asle(struct drm_device *dev);
+ #else
+ static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
+ static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
+ static inline void opregion_asle_intr(struct drm_device *dev) { return; }
++static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
+ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
+ #endif
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -157,6 +157,20 @@ i915_disable_pipestat(drm_i915_private_t
+ }
+ /**
++ * intel_enable_asle - enable ASLE interrupt for OpRegion
++ */
++void intel_enable_asle (struct drm_device *dev)
++{
++      drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
++
++      if (IS_IGDNG(dev))
++              igdng_enable_display_irq(dev_priv, DE_GSE);
++      else
++              i915_enable_pipestat(dev_priv, 1,
++                                   I915_LEGACY_BLC_EVENT_ENABLE);
++}
++
++/**
+  * i915_pipe_enabled - check if a pipe is enabled
+  * @dev: DRM device
+  * @pipe: pipe to check
+@@ -286,6 +300,9 @@ irqreturn_t igdng_irq_handler(struct drm
+               mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
+       }
++      if (de_iir & DE_GSE)
++              ironlake_opregion_gse_intr(dev);
++
+       I915_WRITE(GTIIR, gt_iir);
+       I915_WRITE(DEIIR, de_iir);
+@@ -993,7 +1010,7 @@ static int igdng_irq_postinstall(struct 
+ {
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       /* enable kind of interrupts always enabled */
+-      u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
++      u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
+       u32 render_mask = GT_USER_INTERRUPT;
+       dev_priv->irq_mask_reg = ~display_mask;
+--- a/drivers/gpu/drm/i915/i915_opregion.c
++++ b/drivers/gpu/drm/i915/i915_opregion.c
+@@ -118,6 +118,10 @@ struct opregion_asle {
+ #define ASLE_BACKLIGHT_FAIL    (2<<12)
+ #define ASLE_PFIT_FAIL         (2<<14)
+ #define ASLE_PWM_FREQ_FAIL     (2<<16)
++#define ASLE_ALS_ILLUM_FAILED (1<<10)
++#define ASLE_BACKLIGHT_FAILED (1<<12)
++#define ASLE_PFIT_FAILED      (1<<14)
++#define ASLE_PWM_FREQ_FAILED  (1<<16)
+ /* ASLE backlight brightness to set */
+ #define ASLE_BCLP_VALID                (1<<31)
+@@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_devic
+       asle->aslc = asle_stat;
+ }
++static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
++      struct opregion_asle *asle = dev_priv->opregion.asle;
++      u32 cpu_pwm_ctl, pch_pwm_ctl2;
++      u32 max_backlight, level;
++
++      if (!(bclp & ASLE_BCLP_VALID))
++              return ASLE_BACKLIGHT_FAILED;
++
++      bclp &= ASLE_BCLP_MSK;
++      if (bclp < 0 || bclp > 255)
++              return ASLE_BACKLIGHT_FAILED;
++
++      cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
++      pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
++      /* get the max PWM frequency */
++      max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
++      /* calculate the expected PMW frequency */
++      level = (bclp * max_backlight) / 255;
++      /* reserve the high 16 bits */
++      cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
++      /* write the updated PWM frequency */
++      I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);
++
++      asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;
++
++      return 0;
++}
++
++void ironlake_opregion_gse_intr(struct drm_device *dev)
++{
++      struct drm_i915_private *dev_priv = dev->dev_private;
++      struct opregion_asle *asle = dev_priv->opregion.asle;
++      u32 asle_stat = 0;
++      u32 asle_req;
++
++      if (!asle)
++              return;
++
++      asle_req = asle->aslc & ASLE_REQ_MSK;
++
++      if (!asle_req) {
++              DRM_DEBUG_DRIVER("non asle set request??\n");
++              return;
++      }
++
++      if (asle_req & ASLE_SET_ALS_ILLUM) {
++              DRM_DEBUG_DRIVER("Illum is not supported\n");
++              asle_stat |= ASLE_ALS_ILLUM_FAILED;
++      }
++
++      if (asle_req & ASLE_SET_BACKLIGHT)
++              asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);
++
++      if (asle_req & ASLE_SET_PFIT) {
++              DRM_DEBUG_DRIVER("Pfit is not supported\n");
++              asle_stat |= ASLE_PFIT_FAILED;
++      }
++
++      if (asle_req & ASLE_SET_PWM_FREQ) {
++              DRM_DEBUG_DRIVER("PWM freq is not supported\n");
++              asle_stat |= ASLE_PWM_FREQ_FAILED;
++      }
++
++      asle->aslc = asle_stat;
++}
+ #define ASLE_ALS_EN    (1<<0)
+ #define ASLE_BLC_EN    (1<<1)
+ #define ASLE_PFIT_EN   (1<<2)
+@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_dev
+                       unsigned long irqflags;
+                       spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
+-                      i915_enable_pipestat(dev_priv, 1,
+-                                           I915_LEGACY_BLC_EVENT_ENABLE);
++                      intel_enable_asle(dev);
+                       spin_unlock_irqrestore(&dev_priv->user_irq_lock,
+                                              irqflags);
+               }
diff --git a/queue-2.6.32/drm-i915-add-display-hotplug-event-on-ironlake.patch b/queue-2.6.32/drm-i915-add-display-hotplug-event-on-ironlake.patch
new file mode 100644 (file)
index 0000000..369ea99
--- /dev/null
@@ -0,0 +1,120 @@
+From sconklin@canonical.com  Fri Jan 29 11:32:08 2010
+From: Steve Conklin <sconklin@canonical.com>
+Date: Fri, 29 Jan 2010 12:56:45 -0600
+Subject: drm/i915: Add display hotplug event on Ironlake
+To: stable@kernel.org
+Cc: Steve Conklin <sconklin@canonical.com>, Eric Anholt <eric@anholt.net>, Zhenyu Wang <zhenyuw@linux.intel.com>
+Message-ID: <1264791405-8169-1-git-send-email-sconklin@canonical.com>
+
+
+commit c650156af34bffa3d3a62c9fe26eee595aab3fd1 upstream
+
+Enable display hotplug irqs from Ibex Peak (PCH).
+
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Steve Conklin <sconklin@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_drv.h |    2 ++
+ drivers/gpu/drm/i915/i915_irq.c |   30 +++++++++++++++++++++++++++---
+ drivers/gpu/drm/i915/i915_reg.h |    1 +
+ 3 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -211,6 +211,8 @@ typedef struct drm_i915_private {
+       u32 gt_irq_mask_reg;
+       u32 gt_irq_enable_reg;
+       u32 de_irq_enable_reg;
++      u32 pch_irq_mask_reg;
++      u32 pch_irq_enable_reg;
+       u32 hotplug_supported_mask;
+       struct work_struct hotplug_work;
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -268,7 +268,7 @@ irqreturn_t igdng_irq_handler(struct drm
+ {
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       int ret = IRQ_NONE;
+-      u32 de_iir, gt_iir, de_ier;
++      u32 de_iir, gt_iir, de_ier, pch_iir;
+       struct drm_i915_master_private *master_priv;
+       /* disable master interrupt before clearing iir  */
+@@ -278,8 +278,9 @@ irqreturn_t igdng_irq_handler(struct drm
+       de_iir = I915_READ(DEIIR);
+       gt_iir = I915_READ(GTIIR);
++      pch_iir = I915_READ(SDEIIR);
+-      if (de_iir == 0 && gt_iir == 0)
++      if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
+               goto done;
+       ret = IRQ_HANDLED;
+@@ -303,6 +304,14 @@ irqreturn_t igdng_irq_handler(struct drm
+       if (de_iir & DE_GSE)
+               ironlake_opregion_gse_intr(dev);
++      /* check event from PCH */
++      if ((de_iir & DE_PCH_EVENT) &&
++          (pch_iir & SDE_HOTPLUG_MASK)) {
++              queue_work(dev_priv->wq, &dev_priv->hotplug_work);
++      }
++
++      /* should clear PCH hotplug event before clear CPU irq */
++      I915_WRITE(SDEIIR, pch_iir);
+       I915_WRITE(GTIIR, gt_iir);
+       I915_WRITE(DEIIR, de_iir);
+@@ -1004,14 +1013,21 @@ static void igdng_irq_preinstall(struct 
+       I915_WRITE(GTIMR, 0xffffffff);
+       I915_WRITE(GTIER, 0x0);
+       (void) I915_READ(GTIER);
++
++      /* south display irq */
++      I915_WRITE(SDEIMR, 0xffffffff);
++      I915_WRITE(SDEIER, 0x0);
++      (void) I915_READ(SDEIER);
+ }
+ static int igdng_irq_postinstall(struct drm_device *dev)
+ {
+       drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+       /* enable kind of interrupts always enabled */
+-      u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
++      u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
+       u32 render_mask = GT_USER_INTERRUPT;
++      u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
++                         SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
+       dev_priv->irq_mask_reg = ~display_mask;
+       dev_priv->de_irq_enable_reg = display_mask;
+@@ -1031,6 +1047,14 @@ static int igdng_irq_postinstall(struct 
+       I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
+       (void) I915_READ(GTIER);
++      dev_priv->pch_irq_mask_reg = ~hotplug_mask;
++      dev_priv->pch_irq_enable_reg = hotplug_mask;
++
++      I915_WRITE(SDEIIR, I915_READ(SDEIIR));
++      I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
++      I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
++      (void) I915_READ(SDEIER);
++
+       return 0;
+ }
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -2121,6 +2121,7 @@
+ #define SDE_PORTC_HOTPLUG       (1 << 9)
+ #define SDE_PORTB_HOTPLUG       (1 << 8)
+ #define SDE_SDVOB_HOTPLUG       (1 << 6)
++#define SDE_HOTPLUG_MASK      (0xf << 8)
+ #define SDEISR  0xc4000
+ #define SDEIMR  0xc4004
diff --git a/queue-2.6.32/drm-i915-reload-hangcheck-timer-too-for-ironlake.patch b/queue-2.6.32/drm-i915-reload-hangcheck-timer-too-for-ironlake.patch
new file mode 100644 (file)
index 0000000..d574783
--- /dev/null
@@ -0,0 +1,30 @@
+From c566ec49159b806db95a90fd8f37448376cd0ad2 Mon Sep 17 00:00:00 2001
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+Date: Thu, 17 Dec 2009 16:12:56 +0800
+Subject: drm/i915: Reload hangcheck timer too for Ironlake
+
+From: Zhenyu Wang <zhenyuw@linux.intel.com>
+
+commit c566ec49159b806db95a90fd8f37448376cd0ad2 upstream.
+
+Make sure hangcheck timer won't beat us unexpectedly on Ironlake.
+
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_irq.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -282,6 +282,8 @@ irqreturn_t igdng_irq_handler(struct drm
+               dev_priv->mm.irq_gem_seqno = seqno;
+               trace_i915_gem_request_complete(dev, seqno);
+               DRM_WAKEUP(&dev_priv->irq_queue);
++              dev_priv->hangcheck_count = 0;
++              mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
+       }
+       I915_WRITE(GTIIR, gt_iir);
diff --git a/queue-2.6.32/e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch b/queue-2.6.32/e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch
new file mode 100644 (file)
index 0000000..d105889
--- /dev/null
@@ -0,0 +1,111 @@
+From 9926146b15fd96d78a4f7c32e7a26d50639369f4 Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Fri, 22 Jan 2010 22:56:16 +0000
+Subject: e1000/e1000e: don't use small hardware rx buffers
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit 9926146b15fd96d78a4f7c32e7a26d50639369f4 upstream.
+
+When testing the "e1000: enhance frame fragment detection" (and e1000e)
+patches we found some bugs with reducing the MTU size.  The 1024 byte
+descriptor used with the 1000 mtu test also (re) introduced the
+(originally) reported bug, and causes us to need the e1000_clean_tx_irq
+"enhance frame fragment detection" fix.
+
+So what has occured here is that 2.6.32 is only vulnerable for mtu <
+1500 due to the jumbo specific routines in both e1000 and e1000e.
+So, 2.6.32 needs the 2kB buffer len fix for those smaller MTUs, but
+is not vulnerable to the original issue reported.  It has been pointed
+out that this vulnerability needs to be patched in older kernels that
+don't have the e1000 jumbo routine.  Without the jumbo routines, we
+need the "enhance frame fragment detection" fix the e1000, old
+e1000e is only vulnerable for < 1500 mtu, and needs a similar
+fix.  We split the patches up to provide easy backport paths.
+
+There is only a slight bit of extra code when this fix and the
+original "enhance frame fragment detection" fixes are applied, so
+please apply both, even though it is a bit of overkill.
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000/e1000_main.c |   20 +-------------------
+ drivers/net/e1000e/netdev.c    |   20 +-------------------
+ 2 files changed, 2 insertions(+), 38 deletions(-)
+
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -1698,18 +1698,6 @@ static void e1000_setup_rctl(struct e100
+       rctl &= ~E1000_RCTL_SZ_4096;
+       rctl |= E1000_RCTL_BSEX;
+       switch (adapter->rx_buffer_len) {
+-              case E1000_RXBUFFER_256:
+-                      rctl |= E1000_RCTL_SZ_256;
+-                      rctl &= ~E1000_RCTL_BSEX;
+-                      break;
+-              case E1000_RXBUFFER_512:
+-                      rctl |= E1000_RCTL_SZ_512;
+-                      rctl &= ~E1000_RCTL_BSEX;
+-                      break;
+-              case E1000_RXBUFFER_1024:
+-                      rctl |= E1000_RCTL_SZ_1024;
+-                      rctl &= ~E1000_RCTL_BSEX;
+-                      break;
+               case E1000_RXBUFFER_2048:
+               default:
+                       rctl |= E1000_RCTL_SZ_2048;
+@@ -3154,13 +3142,7 @@ static int e1000_change_mtu(struct net_d
+        *  however with the new *_jumbo_rx* routines, jumbo receives will use
+        *  fragmented skbs */
+-      if (max_frame <= E1000_RXBUFFER_256)
+-              adapter->rx_buffer_len = E1000_RXBUFFER_256;
+-      else if (max_frame <= E1000_RXBUFFER_512)
+-              adapter->rx_buffer_len = E1000_RXBUFFER_512;
+-      else if (max_frame <= E1000_RXBUFFER_1024)
+-              adapter->rx_buffer_len = E1000_RXBUFFER_1024;
+-      else if (max_frame <= E1000_RXBUFFER_2048)
++      if (max_frame <= E1000_RXBUFFER_2048)
+               adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+       else
+ #if (PAGE_SIZE >= E1000_RXBUFFER_16384)
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -2347,18 +2347,6 @@ static void e1000_setup_rctl(struct e100
+       rctl &= ~E1000_RCTL_SZ_4096;
+       rctl |= E1000_RCTL_BSEX;
+       switch (adapter->rx_buffer_len) {
+-      case 256:
+-              rctl |= E1000_RCTL_SZ_256;
+-              rctl &= ~E1000_RCTL_BSEX;
+-              break;
+-      case 512:
+-              rctl |= E1000_RCTL_SZ_512;
+-              rctl &= ~E1000_RCTL_BSEX;
+-              break;
+-      case 1024:
+-              rctl |= E1000_RCTL_SZ_1024;
+-              rctl &= ~E1000_RCTL_BSEX;
+-              break;
+       case 2048:
+       default:
+               rctl |= E1000_RCTL_SZ_2048;
+@@ -4338,13 +4326,7 @@ static int e1000_change_mtu(struct net_d
+        * fragmented skbs
+        */
+-      if (max_frame <= 256)
+-              adapter->rx_buffer_len = 256;
+-      else if (max_frame <= 512)
+-              adapter->rx_buffer_len = 512;
+-      else if (max_frame <= 1024)
+-              adapter->rx_buffer_len = 1024;
+-      else if (max_frame <= 2048)
++      if (max_frame <= 2048)
+               adapter->rx_buffer_len = 2048;
+       else
+               adapter->rx_buffer_len = 4096;
diff --git a/queue-2.6.32/e1000-enhance-frame-fragment-detection.patch b/queue-2.6.32/e1000-enhance-frame-fragment-detection.patch
new file mode 100644 (file)
index 0000000..2e46351
--- /dev/null
@@ -0,0 +1,76 @@
+From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Tue, 19 Jan 2010 14:15:38 +0000
+Subject: e1000: enhance frame fragment detection
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit 40a14deaf411592b57cb0720f0e8004293ab9865 upstream.
+
+Originally From: Neil Horman <nhorman@tuxdriver.com>
+Modified by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+Hey all-
+       A security discussion was recently given:
+http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html
+And a patch that I submitted awhile back was brought up.  Apparently some of
+their testing revealed that they were able to force a buffer fragment in e1000
+in which the trailing fragment was greater than 4 bytes.  As a result the
+fragment check I introduced failed to detect the fragement and a partial
+invalid frame was passed up into the network stack.  I've written this patch
+to correct it.  I'm in the process of testing it now, but it makes good
+logical sense to me.  Effectively it maintains a per-adapter state variable
+which detects a non-EOP frame, and discards it and subsequent non-EOP frames
+leading up to _and_ _including_ the next positive-EOP frame (as it is by
+definition the last fragment).  This should prevent any and all partial frames
+from entering the network stack from e1000.
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000/e1000.h      |    2 ++
+ drivers/net/e1000/e1000_main.c |   13 +++++++++++--
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/e1000/e1000.h
++++ b/drivers/net/e1000/e1000.h
+@@ -326,6 +326,8 @@ struct e1000_adapter {
+       /* for ioport free */
+       int bars;
+       int need_ioport;
++
++      bool discarding;
+ };
+ enum e1000_state_t {
+--- a/drivers/net/e1000/e1000_main.c
++++ b/drivers/net/e1000/e1000_main.c
+@@ -3827,13 +3827,22 @@ static bool e1000_clean_rx_irq(struct e1
+               length = le16_to_cpu(rx_desc->length);
+               /* !EOP means multiple descriptors were used to store a single
+-               * packet, also make sure the frame isn't just CRC only */
+-              if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
++               * packet, if thats the case we need to toss it.  In fact, we
++               * to toss every packet with the EOP bit clear and the next
++               * frame that _does_ have the EOP bit set, as it is by
++               * definition only a frame fragment
++               */
++              if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++                      adapter->discarding = true;
++
++              if (adapter->discarding) {
+                       /* All receives must fit into a single buffer */
+                       E1000_DBG("%s: Receive packet consumed multiple"
+                                 " buffers\n", netdev->name);
+                       /* recycle */
+                       buffer_info->skb = skb;
++                      if (status & E1000_RXD_STAT_EOP)
++                              adapter->discarding = false;
+                       goto next_desc;
+               }
diff --git a/queue-2.6.32/e1000e-enhance-frame-fragment-detection.patch b/queue-2.6.32/e1000e-enhance-frame-fragment-detection.patch
new file mode 100644 (file)
index 0000000..2f4c4f9
--- /dev/null
@@ -0,0 +1,94 @@
+From b94b50289622e816adc9f94111cfc2679c80177c Mon Sep 17 00:00:00 2001
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Date: Tue, 19 Jan 2010 14:15:59 +0000
+Subject: e1000e: enhance frame fragment detection
+
+From: Jesse Brandeburg <jesse.brandeburg@intel.com>
+
+commit b94b50289622e816adc9f94111cfc2679c80177c upstream.
+
+Originally patched by Neil Horman <nhorman@tuxdriver.com>
+
+e1000e could with a jumbo frame enabled interface, and packet split disabled,
+receive a packet that would overflow a single rx buffer.  While in practice
+very hard to craft a packet that could abuse this, it is possible.
+
+this is related to CVE-2009-4538
+
+Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+CC: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/e1000e/e1000.h  |    1 +
+ drivers/net/e1000e/netdev.c |   25 +++++++++++++++++++++----
+ 2 files changed, 22 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -417,6 +417,7 @@ struct e1000_info {
+ /* CRC Stripping defines */
+ #define FLAG2_CRC_STRIPPING               (1 << 0)
+ #define FLAG2_HAS_PHY_WAKEUP              (1 << 1)
++#define FLAG2_IS_DISCARDING               (1 << 2)
+ #define E1000_RX_DESC_PS(R, i)            \
+       (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -482,14 +482,24 @@ static bool e1000_clean_rx_irq(struct e1
+               length = le16_to_cpu(rx_desc->length);
+-              /* !EOP means multiple descriptors were used to store a single
+-               * packet, also make sure the frame isn't just CRC only */
+-              if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
++              /*
++               * !EOP means multiple descriptors were used to store a single
++               * packet, if that's the case we need to toss it.  In fact, we
++               * need to toss every packet with the EOP bit clear and the
++               * next frame that _does_ have the EOP bit set, as it is by
++               * definition only a frame fragment
++               */
++              if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++                      adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++              if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+                       /* All receives must fit into a single buffer */
+                       e_dbg("%s: Receive packet consumed multiple buffers\n",
+                             netdev->name);
+                       /* recycle */
+                       buffer_info->skb = skb;
++                      if (status & E1000_RXD_STAT_EOP)
++                              adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+                       goto next_desc;
+               }
+@@ -747,10 +757,16 @@ static bool e1000_clean_rx_irq_ps(struct
+                                PCI_DMA_FROMDEVICE);
+               buffer_info->dma = 0;
+-              if (!(staterr & E1000_RXD_STAT_EOP)) {
++              /* see !EOP comment in other rx routine */
++              if (!(staterr & E1000_RXD_STAT_EOP))
++                      adapter->flags2 |= FLAG2_IS_DISCARDING;
++
++              if (adapter->flags2 & FLAG2_IS_DISCARDING) {
+                       e_dbg("%s: Packet Split buffers didn't pick up the "
+                             "full packet\n", netdev->name);
+                       dev_kfree_skb_irq(skb);
++                      if (staterr & E1000_RXD_STAT_EOP)
++                              adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+                       goto next_desc;
+               }
+@@ -1120,6 +1136,7 @@ static void e1000_clean_rx_ring(struct e
+       rx_ring->next_to_clean = 0;
+       rx_ring->next_to_use = 0;
++      adapter->flags2 &= ~FLAG2_IS_DISCARDING;
+       writel(0, adapter->hw.hw_addr + rx_ring->head);
+       writel(0, adapter->hw.hw_addr + rx_ring->tail);
diff --git a/queue-2.6.32/fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch b/queue-2.6.32/fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch
new file mode 100644 (file)
index 0000000..ba5e884
--- /dev/null
@@ -0,0 +1,105 @@
+From 04e4f2b18c8de1389d1e00fef0f42a8099910daf Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Wed, 6 Jan 2010 17:23:17 +0000
+Subject: FDPIC: Respect PT_GNU_STACK exec protection markings when creating NOMMU stack
+
+From: Mike Frysinger <vapier@gentoo.org>
+
+commit 04e4f2b18c8de1389d1e00fef0f42a8099910daf upstream.
+
+The current code will load the stack size and protection markings, but
+then only use the markings in the MMU code path.  The NOMMU code path
+always passes PROT_EXEC to the mmap() call.  While this doesn't matter
+to most people whilst the code is running, it will cause a pointless
+icache flush when starting every FDPIC application.  Typically this
+icache flush will be of a region on the order of 128KB in size, or may
+be the entire icache, depending on the facilities available on the CPU.
+
+In the case where the arch default behaviour seems to be desired
+(EXSTACK_DEFAULT), we probe VM_STACK_FLAGS for VM_EXEC to determine
+whether we should be setting PROT_EXEC or not.
+
+For arches that support an MPU (Memory Protection Unit - an MMU without
+the virtual mapping capability), setting PROT_EXEC or not will make an
+important difference.
+
+It should be noted that this change also affects the executability of
+the brk region, since ELF-FDPIC has that share with the stack.  However,
+this is probably irrelevant as NOMMU programs aren't likely to use the
+brk region, preferring instead allocation via mmap().
+
+Signed-off-by: Mike Frysinger <vapier@gentoo.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/blackfin/include/asm/page.h |    5 +++++
+ arch/frv/include/asm/page.h      |    2 --
+ fs/binfmt_elf_fdpic.c            |   13 +++++++++++--
+ 3 files changed, 16 insertions(+), 4 deletions(-)
+
+--- a/arch/blackfin/include/asm/page.h
++++ b/arch/blackfin/include/asm/page.h
+@@ -10,4 +10,9 @@
+ #include <asm-generic/page.h>
+ #define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
++#define VM_DATA_DEFAULT_FLAGS \
++      (VM_READ | VM_WRITE | \
++      ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
++               VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++
+ #endif
+--- a/arch/frv/include/asm/page.h
++++ b/arch/frv/include/asm/page.h
+@@ -63,12 +63,10 @@ extern unsigned long max_pfn;
+ #define virt_addr_valid(kaddr)        pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+-#ifdef CONFIG_MMU
+ #define VM_DATA_DEFAULT_FLAGS \
+       (VM_READ | VM_WRITE | \
+       ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
+                VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+-#endif
+ #endif /* __ASSEMBLY__ */
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -171,6 +171,9 @@ static int load_elf_fdpic_binary(struct 
+ #ifdef ELF_FDPIC_PLAT_INIT
+       unsigned long dynaddr;
+ #endif
++#ifndef CONFIG_MMU
++      unsigned long stack_prot;
++#endif
+       struct file *interpreter = NULL; /* to shut gcc up */
+       char *interpreter_name = NULL;
+       int executable_stack;
+@@ -316,6 +319,8 @@ static int load_elf_fdpic_binary(struct 
+        * defunct, deceased, etc. after this point we have to exit via
+        * error_kill */
+       set_personality(PER_LINUX_FDPIC);
++      if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
++              current->personality |= READ_IMPLIES_EXEC;
+       set_binfmt(&elf_fdpic_format);
+       current->mm->start_code = 0;
+@@ -377,9 +382,13 @@ static int load_elf_fdpic_binary(struct 
+       if (stack_size < PAGE_SIZE * 2)
+               stack_size = PAGE_SIZE * 2;
++      stack_prot = PROT_READ | PROT_WRITE;
++      if (executable_stack == EXSTACK_ENABLE_X ||
++          (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
++              stack_prot |= PROT_EXEC;
++
+       down_write(&current->mm->mmap_sem);
+-      current->mm->start_brk = do_mmap(NULL, 0, stack_size,
+-                                       PROT_READ | PROT_WRITE | PROT_EXEC,
++      current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
+                                        MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN,
+                                        0);
diff --git a/queue-2.6.32/fix-a-leak-in-affs_fill_super.patch b/queue-2.6.32/fix-a-leak-in-affs_fill_super.patch
new file mode 100644 (file)
index 0000000..1a62ba8
--- /dev/null
@@ -0,0 +1,27 @@
+From afc70ed05a07bfe171f7a5b8fdc80bdb073d314f Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 23 Jan 2010 23:38:27 -0500
+Subject: Fix a leak in affs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit afc70ed05a07bfe171f7a5b8fdc80bdb073d314f upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/super.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -316,6 +316,8 @@ static int affs_fill_super(struct super_
+                               &blocksize,&sbi->s_prefix,
+                               sbi->s_volume, &mount_flags)) {
+               printk(KERN_ERR "AFFS: Error parsing options\n");
++              kfree(sbi->s_prefix);
++              kfree(sbi);
+               return -EINVAL;
+       }
+       /* N.B. after this point s_prefix must be released */
diff --git a/queue-2.6.32/fix-affs-parse_options.patch b/queue-2.6.32/fix-affs-parse_options.patch
new file mode 100644 (file)
index 0000000..87b4967
--- /dev/null
@@ -0,0 +1,68 @@
+From 217686e98321a4ff4c1a6cc535e511e37c5d2dbf Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:06:22 -0500
+Subject: fix affs parse_options()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 217686e98321a4ff4c1a6cc535e511e37c5d2dbf upstream.
+
+Error handling in that sucker got broken back in 2003.  If function
+returns 0 on failure, it's not nice to add return -EINVAL into it.
+Adding return 1 on other failure exits is also not a good thing (and
+yes, original success exits with 1 and some of failure exits with 0
+are still there; so's the original logics in callers).
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/super.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -203,7 +203,7 @@ parse_options(char *options, uid_t *uid,
+               switch (token) {
+               case Opt_bs:
+                       if (match_int(&args[0], &n))
+-                              return -EINVAL;
++                              return 0;
+                       if (n != 512 && n != 1024 && n != 2048
+                           && n != 4096) {
+                               printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
+@@ -213,7 +213,7 @@ parse_options(char *options, uid_t *uid,
+                       break;
+               case Opt_mode:
+                       if (match_octal(&args[0], &option))
+-                              return 1;
++                              return 0;
+                       *mode = option & 0777;
+                       *mount_opts |= SF_SETMODE;
+                       break;
+@@ -231,21 +231,21 @@ parse_options(char *options, uid_t *uid,
+                       break;
+               case Opt_reserved:
+                       if (match_int(&args[0], reserved))
+-                              return 1;
++                              return 0;
+                       break;
+               case Opt_root:
+                       if (match_int(&args[0], root))
+-                              return 1;
++                              return 0;
+                       break;
+               case Opt_setgid:
+                       if (match_int(&args[0], &option))
+-                              return 1;
++                              return 0;
+                       *gid = option;
+                       *mount_opts |= SF_SETGID;
+                       break;
+               case Opt_setuid:
+                       if (match_int(&args[0], &option))
+-                              return -EINVAL;
++                              return 0;
+                       *uid = option;
+                       *mount_opts |= SF_SETUID;
+                       break;
diff --git a/queue-2.6.32/fix-failure-exit-in-ipathfs.patch b/queue-2.6.32/fix-failure-exit-in-ipathfs.patch
new file mode 100644 (file)
index 0000000..50fa443
--- /dev/null
@@ -0,0 +1,33 @@
+From 12e9a45609054fb83d4a8b716a5265cc1a393e10 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 18:44:58 -0500
+Subject: Fix failure exit in ipathfs
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 12e9a45609054fb83d4a8b716a5265cc1a393e10 upstream.
+
+deactivate_locked_super() will be done by caller of fill_super, doing
+it there as well is b0rken.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/infiniband/hw/ipath/ipath_fs.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -346,10 +346,8 @@ static int ipathfs_fill_super(struct sup
+       list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) {
+               spin_unlock_irqrestore(&ipath_devs_lock, flags);
+               ret = create_device_files(sb, dd);
+-              if (ret) {
+-                      deactivate_locked_super(sb);
++              if (ret)
+                       goto bail;
+-              }
+               spin_lock_irqsave(&ipath_devs_lock, flags);
+       }
diff --git a/queue-2.6.32/fix-failure-exits-in-bfs_fill_super.patch b/queue-2.6.32/fix-failure-exits-in-bfs_fill_super.patch
new file mode 100644 (file)
index 0000000..7eccbb5
--- /dev/null
@@ -0,0 +1,136 @@
+From 5998649f779b7148a8a0c10c46cfa99e27d34dfe Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:52:22 -0500
+Subject: Fix failure exits in bfs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 5998649f779b7148a8a0c10c46cfa99e27d34dfe upstream.
+
+double iput(), leaks...
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/bfs/inode.c |   43 +++++++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 22 deletions(-)
+
+--- a/fs/bfs/inode.c
++++ b/fs/bfs/inode.c
+@@ -353,35 +353,35 @@ static int bfs_fill_super(struct super_b
+       struct inode *inode;
+       unsigned i, imap_len;
+       struct bfs_sb_info *info;
+-      long ret = -EINVAL;
++      int ret = -EINVAL;
+       unsigned long i_sblock, i_eblock, i_eoff, s_size;
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
++      mutex_init(&info->bfs_lock);
+       s->s_fs_info = info;
+       sb_set_blocksize(s, BFS_BSIZE);
+-      bh = sb_bread(s, 0);
+-      if(!bh)
++      info->si_sbh = sb_bread(s, 0);
++      if (!info->si_sbh)
+               goto out;
+-      bfs_sb = (struct bfs_super_block *)bh->b_data;
++      bfs_sb = (struct bfs_super_block *)info->si_sbh->b_data;
+       if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
+               if (!silent)
+                       printf("No BFS filesystem on %s (magic=%08x)\n", 
+                               s->s_id,  le32_to_cpu(bfs_sb->s_magic));
+-              goto out;
++              goto out1;
+       }
+       if (BFS_UNCLEAN(bfs_sb, s) && !silent)
+               printf("%s is unclean, continuing\n", s->s_id);
+       s->s_magic = BFS_MAGIC;
+-      info->si_sbh = bh;
+       if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) {
+               printf("Superblock is corrupted\n");
+-              goto out;
++              goto out1;
+       }
+       info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
+@@ -390,7 +390,7 @@ static int bfs_fill_super(struct super_b
+       imap_len = (info->si_lasti / 8) + 1;
+       info->si_imap = kzalloc(imap_len, GFP_KERNEL);
+       if (!info->si_imap)
+-              goto out;
++              goto out1;
+       for (i = 0; i < BFS_ROOT_INO; i++)
+               set_bit(i, info->si_imap);
+@@ -398,15 +398,13 @@ static int bfs_fill_super(struct super_b
+       inode = bfs_iget(s, BFS_ROOT_INO);
+       if (IS_ERR(inode)) {
+               ret = PTR_ERR(inode);
+-              kfree(info->si_imap);
+-              goto out;
++              goto out2;
+       }
+       s->s_root = d_alloc_root(inode);
+       if (!s->s_root) {
+               iput(inode);
+               ret = -ENOMEM;
+-              kfree(info->si_imap);
+-              goto out;
++              goto out2;
+       }
+       info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
+@@ -419,10 +417,8 @@ static int bfs_fill_super(struct super_b
+       bh = sb_bread(s, info->si_blocks - 1);
+       if (!bh) {
+               printf("Last block not available: %lu\n", info->si_blocks - 1);
+-              iput(inode);
+               ret = -EIO;
+-              kfree(info->si_imap);
+-              goto out;
++              goto out3;
+       }
+       brelse(bh);
+@@ -459,11 +455,8 @@ static int bfs_fill_super(struct super_b
+                       printf("Inode 0x%08x corrupted\n", i);
+                       brelse(bh);
+-                      s->s_root = NULL;
+-                      kfree(info->si_imap);
+-                      kfree(info);
+-                      s->s_fs_info = NULL;
+-                      return -EIO;
++                      ret = -EIO;
++                      goto out3;
+               }
+               if (!di->i_ino) {
+@@ -483,11 +476,17 @@ static int bfs_fill_super(struct super_b
+               s->s_dirt = 1;
+       } 
+       dump_imap("read_super", s);
+-      mutex_init(&info->bfs_lock);
+       return 0;
++out3:
++      dput(s->s_root);
++      s->s_root = NULL;
++out2:
++      kfree(info->si_imap);
++out1:
++      brelse(info->si_sbh);
+ out:
+-      brelse(bh);
++      mutex_destroy(&info->bfs_lock);
+       kfree(info);
+       s->s_fs_info = NULL;
+       return ret;
diff --git a/queue-2.6.32/fix-leak-in-romfs_fill_super.patch b/queue-2.6.32/fix-leak-in-romfs_fill_super.patch
new file mode 100644 (file)
index 0000000..8e9a987
--- /dev/null
@@ -0,0 +1,26 @@
+From 7e32b7bb734047c5e3cecf2e896b9cf8fc35d1e8 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 06:05:54 -0500
+Subject: fix leak in romfs_fill_super()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 7e32b7bb734047c5e3cecf2e896b9cf8fc35d1e8 upstream.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/romfs/super.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/romfs/super.c
++++ b/fs/romfs/super.c
+@@ -544,6 +544,7 @@ error:
+ error_rsb_inval:
+       ret = -EINVAL;
+ error_rsb:
++      kfree(rsb);
+       return ret;
+ }
diff --git a/queue-2.6.32/fix-oops-in-fs-9p-late-mount-failure.patch b/queue-2.6.32/fix-oops-in-fs-9p-late-mount-failure.patch
new file mode 100644 (file)
index 0000000..afb9972
--- /dev/null
@@ -0,0 +1,31 @@
+From 083c73c253c23c20359a344dfe1198ea628e6259 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Mon, 25 Jan 2010 06:16:19 -0500
+Subject: fix oops in fs/9p late mount failure
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 083c73c253c23c20359a344dfe1198ea628e6259 upstream.
+
+if 9P ->get_sb() fails late (at root inode or root dentry
+allocation), we'll hit its ->kill_sb() with NULL ->s_root
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/9p/vfs_super.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -188,7 +188,8 @@ static void v9fs_kill_super(struct super
+       P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
+-      v9fs_dentry_release(s->s_root); /* clunk root */
++      if (s->s_root)
++              v9fs_dentry_release(s->s_root); /* clunk root */
+       kill_anon_super(s);
diff --git a/queue-2.6.32/fix-remount-races-with-symlink-handling-in-affs.patch b/queue-2.6.32/fix-remount-races-with-symlink-handling-in-affs.patch
new file mode 100644 (file)
index 0000000..636da0f
--- /dev/null
@@ -0,0 +1,134 @@
+From 29333920a5a46edcc9b728e2cf0134d5a9b516ee Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 24 Jan 2010 00:04:07 -0500
+Subject: Fix remount races with symlink handling in affs
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 29333920a5a46edcc9b728e2cf0134d5a9b516ee upstream.
+
+A couple of fields in affs_sb_info is used in follow_link() and
+symlink() for handling AFFS "absolute" symlinks.  Need locking
+against affs_remount() updates.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/affs/affs.h    |    2 +-
+ fs/affs/namei.c   |    7 +++++--
+ fs/affs/super.c   |   17 ++++++++++++++---
+ fs/affs/symlink.c |    7 +++++--
+ 4 files changed, 25 insertions(+), 8 deletions(-)
+
+--- a/fs/affs/affs.h
++++ b/fs/affs/affs.h
+@@ -106,8 +106,8 @@ struct affs_sb_info {
+       u32 s_last_bmap;
+       struct buffer_head *s_bmap_bh;
+       char *s_prefix;                 /* Prefix for volumes and assigns. */
+-      int s_prefix_len;               /* Length of prefix. */
+       char s_volume[32];              /* Volume prefix for absolute symlinks. */
++      spinlock_t symlink_lock;        /* protects the previous two */
+ };
+ #define SF_INTL               0x0001          /* International filesystem. */
+--- a/fs/affs/namei.c
++++ b/fs/affs/namei.c
+@@ -341,10 +341,13 @@ affs_symlink(struct inode *dir, struct d
+       p  = (char *)AFFS_HEAD(bh)->table;
+       lc = '/';
+       if (*symname == '/') {
++              struct affs_sb_info *sbi = AFFS_SB(sb);
+               while (*symname == '/')
+                       symname++;
+-              while (AFFS_SB(sb)->s_volume[i])        /* Cannot overflow */
+-                      *p++ = AFFS_SB(sb)->s_volume[i++];
++              spin_lock(&sbi->symlink_lock);
++              while (sbi->s_volume[i])        /* Cannot overflow */
++                      *p++ = sbi->s_volume[i++];
++              spin_unlock(&sbi->symlink_lock);
+       }
+       while (i < maxlen && (c = *symname++)) {
+               if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
+--- a/fs/affs/super.c
++++ b/fs/affs/super.c
+@@ -221,8 +221,6 @@ parse_options(char *options, uid_t *uid,
+                       *mount_opts |= SF_MUFS;
+                       break;
+               case Opt_prefix:
+-                      /* Free any previous prefix */
+-                      kfree(*prefix);
+                       *prefix = match_strdup(&args[0]);
+                       if (!*prefix)
+                               return 0;
+@@ -311,6 +309,7 @@ static int affs_fill_super(struct super_
+               return -ENOMEM;
+       sb->s_fs_info = sbi;
+       mutex_init(&sbi->s_bmlock);
++      spin_lock_init(&sbi->symlink_lock);
+       if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
+                               &blocksize,&sbi->s_prefix,
+@@ -518,14 +517,18 @@ affs_remount(struct super_block *sb, int
+       unsigned long            mount_flags;
+       int                      res = 0;
+       char                    *new_opts = kstrdup(data, GFP_KERNEL);
++      char                     volume[32];
++      char                    *prefix = NULL;
+       pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
+       *flags |= MS_NODIRATIME;
++      memcpy(volume, sbi->s_volume, 32);
+       if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
+-                         &blocksize, &sbi->s_prefix, sbi->s_volume,
++                         &blocksize, &prefix, volume,
+                          &mount_flags)) {
++              kfree(prefix);
+               kfree(new_opts);
+               return -EINVAL;
+       }
+@@ -536,6 +539,14 @@ affs_remount(struct super_block *sb, int
+       sbi->s_mode  = mode;
+       sbi->s_uid   = uid;
+       sbi->s_gid   = gid;
++      /* protect against readers */
++      spin_lock(&sbi->symlink_lock);
++      if (prefix) {
++              kfree(sbi->s_prefix);
++              sbi->s_prefix = prefix;
++      }
++      memcpy(sbi->s_volume, volume, 32);
++      spin_unlock(&sbi->symlink_lock);
+       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
+               unlock_kernel();
+--- a/fs/affs/symlink.c
++++ b/fs/affs/symlink.c
+@@ -20,7 +20,6 @@ static int affs_symlink_readpage(struct 
+       int                      i, j;
+       char                     c;
+       char                     lc;
+-      char                    *pf;
+       pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
+@@ -32,11 +31,15 @@ static int affs_symlink_readpage(struct 
+       j  = 0;
+       lf = (struct slink_front *)bh->b_data;
+       lc = 0;
+-      pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
+       if (strchr(lf->symname,':')) {  /* Handle assign or volume name */
++              struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
++              char *pf;
++              spin_lock(&sbi->symlink_lock);
++              pf = sbi->s_prefix ? sbi->s_prefix : "/";
+               while (i < 1023 && (c = pf[i]))
+                       link[i++] = c;
++              spin_unlock(&sbi->symlink_lock);
+               while (i < 1023 && lf->symname[j] != ':')
+                       link[i++] = lf->symname[j++];
+               if (i < 1023)
diff --git a/queue-2.6.32/input-winbond-cir-remove-dmesg-spam.patch b/queue-2.6.32/input-winbond-cir-remove-dmesg-spam.patch
new file mode 100644 (file)
index 0000000..3fa2d48
--- /dev/null
@@ -0,0 +1,32 @@
+From 93fb84b50fe03aabca8d9dea5d3ba521a07e8571 Mon Sep 17 00:00:00 2001
+From: David Härdeman <david@hardeman.nu>
+Date: Thu, 28 Jan 2010 22:28:27 -0800
+Subject: Input: winbond-cir - remove dmesg spam
+
+From: David Härdeman <david@hardeman.nu>
+
+commit 93fb84b50fe03aabca8d9dea5d3ba521a07e8571 upstream.
+
+I missed converting one dev_info call to deb_dbg before submitting the driver.
+Without this change, a message will be printed to dmesg for each button press
+if a RC6 remote is used.
+
+Signed-off-by: David Härdeman <david@hardeman.nu>
+Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/input/misc/winbond-cir.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/input/misc/winbond-cir.c
++++ b/drivers/input/misc/winbond-cir.c
+@@ -768,7 +768,7 @@ wbcir_parse_rc6(struct device *dev, stru
+               return;
+       }
+-      dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
++      dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X "
+               "toggle %u mode %u scan 0x%08X\n",
+               address,
+               command,
diff --git a/queue-2.6.32/mm-fix-migratetype-bug-which-slowed-swapping.patch b/queue-2.6.32/mm-fix-migratetype-bug-which-slowed-swapping.patch
new file mode 100644 (file)
index 0000000..6b8290a
--- /dev/null
@@ -0,0 +1,55 @@
+From a7016235a61d520e6806f38129001d935c4b6661 Mon Sep 17 00:00:00 2001
+From: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+Date: Fri, 29 Jan 2010 17:46:34 +0000
+Subject: mm: fix migratetype bug which slowed swapping
+
+From: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+
+commit a7016235a61d520e6806f38129001d935c4b6661 upstream.
+
+After memory pressure has forced it to dip into the reserves, 2.6.32's
+5f8dcc21211a3d4e3a7a5ca366b469fb88117f61 "page-allocator: split per-cpu
+list into one-list-per-migrate-type" has been returning MIGRATE_RESERVE
+pages to the MIGRATE_MOVABLE free_list: in some sense depleting reserves.
+
+Fix that in the most straightforward way (which, considering the overheads
+of alternative approaches, is Mel's preference): the right migratetype is
+already in page_private(page), but free_pcppages_bulk() wasn't using it.
+
+How did this bug show up?  As a 20% slowdown in my tmpfs loop kbuild
+swapping tests, on PowerMac G5 with SLUB allocator.  Bisecting to that
+commit was easy, but explaining the magnitude of the slowdown not easy.
+
+The same effect appears, but much less markedly, with SLAB, and even
+less markedly on other machines (the PowerMac divides into fewer zones
+than x86, I think that may be a factor).  We guess that lumpy reclaim
+of short-lived high-order pages is implicated in some way, and probably
+this bug has been tickling a poor decision somewhere in page reclaim.
+
+But instrumentation hasn't told me much, I've run out of time and
+imagination to determine exactly what's going on, and shouldn't hold up
+the fix any longer: it's valid, and might even fix other misbehaviours.
+
+Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
+Acked-by: Mel Gorman <mel@csn.ul.ie>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/page_alloc.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -559,8 +559,9 @@ static void free_pcppages_bulk(struct zo
+                       page = list_entry(list->prev, struct page, lru);
+                       /* must delete as __free_one_page list manipulates */
+                       list_del(&page->lru);
+-                      __free_one_page(page, zone, 0, migratetype);
+-                      trace_mm_page_pcpu_drain(page, 0, migratetype);
++                      /* MIGRATE_MOVABLE list may include MIGRATE_RESERVEs */
++                      __free_one_page(page, zone, 0, page_private(page));
++                      trace_mm_page_pcpu_drain(page, 0, page_private(page));
+               } while (--count && --batch_free && !list_empty(list));
+       }
+       spin_unlock(&zone->lock);
index 43258a15fe6e8309c6db07579b26239eed258d63..54501972a85ac8d1ad1ca23acdc3e45ab042cf44 100644 (file)
@@ -14,3 +14,22 @@ acpi-add-platform-wide-_osc-support.patch
 acpi-fix-osc-regression-that-caused-aer-and-pciehp-not-to-load.patch
 acpi-advertise-to-bios-in-_osc-_ost-on-_ppc-changes.patch
 ubi-fix-volume-creation-input-checking.patch
+e1000-enhance-frame-fragment-detection.patch
+e1000e-enhance-frame-fragment-detection.patch
+e1000-e1000e-don-t-use-small-hardware-rx-buffers.patch
+drm-i915-reload-hangcheck-timer-too-for-ironlake.patch
+drm-i915-add-acpi-opregion-support-for-ironlake.patch
+fix-a-leak-in-affs_fill_super.patch
+fix-failure-exits-in-bfs_fill_super.patch
+fix-oops-in-fs-9p-late-mount-failure.patch
+fix-leak-in-romfs_fill_super.patch
+fix-remount-races-with-symlink-handling-in-affs.patch
+fix-affs-parse_options.patch
+fix-failure-exit-in-ipathfs.patch
+mm-fix-migratetype-bug-which-slowed-swapping.patch
+fdpic-respect-pt_gnu_stack-exec-protection-markings-when-creating-nommu-stack.patch
+split-flush_old_exec-into-two-functions.patch
+sparc-tif_abi_pending-bit-removal.patch
+x86-get-rid-of-the-insane-tif_abi_pending-bit.patch
+drm-i915-add-display-hotplug-event-on-ironlake.patch
+input-winbond-cir-remove-dmesg-spam.patch
diff --git a/queue-2.6.32/sparc-tif_abi_pending-bit-removal.patch b/queue-2.6.32/sparc-tif_abi_pending-bit-removal.patch
new file mode 100644 (file)
index 0000000..a3e6dc3
--- /dev/null
@@ -0,0 +1,86 @@
+From 94673e968cbcce07fa78dac4b0ae05d24b5816e1 Mon Sep 17 00:00:00 2001
+From: David Miller <davem@davemloft.net>
+Date: Thu, 28 Jan 2010 21:42:02 -0800
+Subject: sparc: TIF_ABI_PENDING bit removal
+
+From: David Miller <davem@davemloft.net>
+
+commit 94673e968cbcce07fa78dac4b0ae05d24b5816e1 upstream.
+
+Here are the sparc bits to remove TIF_ABI_PENDING now that
+set_personality() is called at the appropriate place in exec.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sparc/include/asm/elf_64.h         |   13 +++----------
+ arch/sparc/include/asm/thread_info_64.h |    4 +---
+ arch/sparc/kernel/process_64.c          |    8 --------
+ 3 files changed, 4 insertions(+), 21 deletions(-)
+
+--- a/arch/sparc/include/asm/elf_64.h
++++ b/arch/sparc/include/asm/elf_64.h
+@@ -196,17 +196,10 @@ static inline unsigned int sparc64_elf_h
+ #define ELF_PLATFORM  (NULL)
+ #define SET_PERSONALITY(ex)                           \
+-do {  unsigned long new_flags = current_thread_info()->flags; \
+-      new_flags &= _TIF_32BIT;                        \
+-      if ((ex).e_ident[EI_CLASS] == ELFCLASS32)       \
+-              new_flags |= _TIF_32BIT;                \
++do {  if ((ex).e_ident[EI_CLASS] == ELFCLASS32)       \
++              set_thread_flag(TIF_32BIT);             \
+       else                                            \
+-              new_flags &= ~_TIF_32BIT;               \
+-      if ((current_thread_info()->flags & _TIF_32BIT) \
+-          != new_flags)                               \
+-              set_thread_flag(TIF_ABI_PENDING);       \
+-      else                                            \
+-              clear_thread_flag(TIF_ABI_PENDING);     \
++              clear_thread_flag(TIF_32BIT);           \
+       /* flush_thread will update pgd cache */        \
+       if (personality(current->personality) != PER_LINUX32)   \
+               set_personality(PER_LINUX |             \
+--- a/arch/sparc/include/asm/thread_info_64.h
++++ b/arch/sparc/include/asm/thread_info_64.h
+@@ -227,12 +227,11 @@ register struct thread_info *current_thr
+ /* flag bit 8 is available */
+ #define TIF_SECCOMP           9       /* secure computing */
+ #define TIF_SYSCALL_AUDIT     10      /* syscall auditing active */
+-/* flag bit 11 is available */
+ /* NOTE: Thread flags >= 12 should be ones we have no interest
+  *       in using in assembly, else we can't use the mask as
+  *       an immediate value in instructions such as andcc.
+  */
+-#define TIF_ABI_PENDING               12
++/* flag bit 12 is available */
+ #define TIF_MEMDIE            13
+ #define TIF_POLLING_NRFLAG    14
+ #define TIF_FREEZE            15      /* is freezing for suspend */
+@@ -246,7 +245,6 @@ register struct thread_info *current_thr
+ #define _TIF_32BIT            (1<<TIF_32BIT)
+ #define _TIF_SECCOMP          (1<<TIF_SECCOMP)
+ #define _TIF_SYSCALL_AUDIT    (1<<TIF_SYSCALL_AUDIT)
+-#define _TIF_ABI_PENDING      (1<<TIF_ABI_PENDING)
+ #define _TIF_POLLING_NRFLAG   (1<<TIF_POLLING_NRFLAG)
+ #define _TIF_FREEZE           (1<<TIF_FREEZE)
+--- a/arch/sparc/kernel/process_64.c
++++ b/arch/sparc/kernel/process_64.c
+@@ -365,14 +365,6 @@ void flush_thread(void)
+       struct thread_info *t = current_thread_info();
+       struct mm_struct *mm;
+-      if (test_ti_thread_flag(t, TIF_ABI_PENDING)) {
+-              clear_ti_thread_flag(t, TIF_ABI_PENDING);
+-              if (test_ti_thread_flag(t, TIF_32BIT))
+-                      clear_ti_thread_flag(t, TIF_32BIT);
+-              else
+-                      set_ti_thread_flag(t, TIF_32BIT);
+-      }
+-
+       mm = t->task->mm;
+       if (mm)
+               tsb_context_switch(mm);
diff --git a/queue-2.6.32/split-flush_old_exec-into-two-functions.patch b/queue-2.6.32/split-flush_old_exec-into-two-functions.patch
new file mode 100644 (file)
index 0000000..8794a49
--- /dev/null
@@ -0,0 +1,245 @@
+From 221af7f87b97431e3ee21ce4b0e77d5411cf1549 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 28 Jan 2010 22:14:42 -0800
+Subject: Split 'flush_old_exec' into two functions
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 221af7f87b97431e3ee21ce4b0e77d5411cf1549 upstream.
+
+'flush_old_exec()' is the point of no return when doing an execve(), and
+it is pretty badly misnamed.  It doesn't just flush the old executable
+environment, it also starts up the new one.
+
+Which is very inconvenient for things like setting up the new
+personality, because we want the new personality to affect the starting
+of the new environment, but at the same time we do _not_ want the new
+personality to take effect if flushing the old one fails.
+
+As a result, the x86-64 '32-bit' personality is actually done using this
+insane "I'm going to change the ABI, but I haven't done it yet" bit
+(TIF_ABI_PENDING), with SET_PERSONALITY() not actually setting the
+personality, but just the "pending" bit, so that "flush_thread()" can do
+the actual personality magic.
+
+This patch in no way changes any of that insanity, but it does split the
+'flush_old_exec()' function up into a preparatory part that can fail
+(still called flush_old_exec()), and a new part that will actually set
+up the new exec environment (setup_new_exec()).  All callers are changed
+to trivially comply with the new world order.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/sh/kernel/process_64.c |    2 +-
+ arch/x86/ia32/ia32_aout.c   |   10 ++++++----
+ fs/binfmt_aout.c            |    1 +
+ fs/binfmt_elf.c             |   27 ++-------------------------
+ fs/binfmt_elf_fdpic.c       |    3 +++
+ fs/binfmt_flat.c            |    1 +
+ fs/binfmt_som.c             |    1 +
+ fs/exec.c                   |   26 ++++++++++++++++----------
+ include/linux/binfmts.h     |    1 +
+ include/linux/sched.h       |    2 +-
+ 10 files changed, 33 insertions(+), 41 deletions(-)
+
+--- a/arch/sh/kernel/process_64.c
++++ b/arch/sh/kernel/process_64.c
+@@ -367,7 +367,7 @@ void exit_thread(void)
+ void flush_thread(void)
+ {
+-      /* Called by fs/exec.c (flush_old_exec) to remove traces of a
++      /* Called by fs/exec.c (setup_new_exec) to remove traces of a
+        * previously running executable. */
+ #ifdef CONFIG_SH_FPU
+       if (last_task_used_math == current) {
+--- a/arch/x86/ia32/ia32_aout.c
++++ b/arch/x86/ia32/ia32_aout.c
+@@ -308,15 +308,17 @@ static int load_aout_binary(struct linux
+       if (retval)
+               return retval;
+-      regs->cs = __USER32_CS;
+-      regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
+-              regs->r13 = regs->r14 = regs->r15 = 0;
+-
+       /* OK, This is the point of no return */
+       set_personality(PER_LINUX);
+       set_thread_flag(TIF_IA32);
+       clear_thread_flag(TIF_ABI_PENDING);
++      setup_new_exec(bprm);
++
++      regs->cs = __USER32_CS;
++      regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
++              regs->r13 = regs->r14 = regs->r15 = 0;
++
+       current->mm->end_code = ex.a_text +
+               (current->mm->start_code = N_TXTADDR(ex));
+       current->mm->end_data = ex.a_data +
+--- a/fs/binfmt_aout.c
++++ b/fs/binfmt_aout.c
+@@ -263,6 +263,7 @@ static int load_aout_binary(struct linux
+ #else
+       set_personality(PER_LINUX);
+ #endif
++      setup_new_exec(bprm);
+       current->mm->end_code = ex.a_text +
+               (current->mm->start_code = N_TXTADDR(ex));
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -662,27 +662,6 @@ static int load_elf_binary(struct linux_
+                       if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0')
+                               goto out_free_interp;
+-                      /*
+-                       * The early SET_PERSONALITY here is so that the lookup
+-                       * for the interpreter happens in the namespace of the 
+-                       * to-be-execed image.  SET_PERSONALITY can select an
+-                       * alternate root.
+-                       *
+-                       * However, SET_PERSONALITY is NOT allowed to switch
+-                       * this task into the new images's memory mapping
+-                       * policy - that is, TASK_SIZE must still evaluate to
+-                       * that which is appropriate to the execing application.
+-                       * This is because exit_mmap() needs to have TASK_SIZE
+-                       * evaluate to the size of the old image.
+-                       *
+-                       * So if (say) a 64-bit application is execing a 32-bit
+-                       * application it is the architecture's responsibility
+-                       * to defer changing the value of TASK_SIZE until the
+-                       * switch really is going to happen - do this in
+-                       * flush_thread().      - akpm
+-                       */
+-                      SET_PERSONALITY(loc->elf_ex);
+-
+                       interpreter = open_exec(elf_interpreter);
+                       retval = PTR_ERR(interpreter);
+                       if (IS_ERR(interpreter))
+@@ -730,9 +709,6 @@ static int load_elf_binary(struct linux_
+               /* Verify the interpreter has a valid arch */
+               if (!elf_check_arch(&loc->interp_elf_ex))
+                       goto out_free_dentry;
+-      } else {
+-              /* Executables without an interpreter also need a personality  */
+-              SET_PERSONALITY(loc->elf_ex);
+       }
+       /* Flush all traces of the currently running executable */
+@@ -752,7 +728,8 @@ static int load_elf_binary(struct linux_
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+               current->flags |= PF_RANDOMIZE;
+-      arch_pick_mmap_layout(current->mm);
++
++      setup_new_exec(bprm);
+       /* Do this so that we can load the interpreter, if need be.  We will
+          change some of these later */
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -321,6 +321,9 @@ static int load_elf_fdpic_binary(struct 
+       set_personality(PER_LINUX_FDPIC);
+       if (elf_read_implies_exec(&exec_params.hdr, executable_stack))
+               current->personality |= READ_IMPLIES_EXEC;
++
++      setup_new_exec(bprm);
++
+       set_binfmt(&elf_fdpic_format);
+       current->mm->start_code = 0;
+--- a/fs/binfmt_flat.c
++++ b/fs/binfmt_flat.c
+@@ -519,6 +519,7 @@ static int load_flat_file(struct linux_b
+               /* OK, This is the point of no return */
+               set_personality(PER_LINUX_32BIT);
++              setup_new_exec(bprm);
+       }
+       /*
+--- a/fs/binfmt_som.c
++++ b/fs/binfmt_som.c
+@@ -227,6 +227,7 @@ load_som_binary(struct linux_binprm * bp
+       /* OK, This is the point of no return */
+       current->flags &= ~PF_FORKNOEXEC;
+       current->personality = PER_HPUX;
++      setup_new_exec(bprm);
+       /* Set the task size for HP-UX processes such that
+        * the gateway page is outside the address space.
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -931,9 +931,7 @@ void set_task_comm(struct task_struct *t
+ int flush_old_exec(struct linux_binprm * bprm)
+ {
+-      char * name;
+-      int i, ch, retval;
+-      char tcomm[sizeof(current->comm)];
++      int retval;
+       /*
+        * Make sure we have a private signal table and that
+@@ -953,6 +951,20 @@ int flush_old_exec(struct linux_binprm *
+               goto out;
+       bprm->mm = NULL;                /* We're using it now */
++      return 0;
++
++out:
++      return retval;
++}
++EXPORT_SYMBOL(flush_old_exec);
++
++void setup_new_exec(struct linux_binprm * bprm)
++{
++      int i, ch;
++      char * name;
++      char tcomm[sizeof(current->comm)];
++
++      arch_pick_mmap_layout(current->mm);
+       /* This is the point of no return */
+       current->sas_ss_sp = current->sas_ss_size = 0;
+@@ -1009,14 +1021,8 @@ int flush_old_exec(struct linux_binprm *
+                       
+       flush_signal_handlers(current, 0);
+       flush_old_files(current->files);
+-
+-      return 0;
+-
+-out:
+-      return retval;
+ }
+-
+-EXPORT_SYMBOL(flush_old_exec);
++EXPORT_SYMBOL(setup_new_exec);
+ /*
+  * Prepare credentials and lock ->cred_guard_mutex.
+--- a/include/linux/binfmts.h
++++ b/include/linux/binfmts.h
+@@ -101,6 +101,7 @@ extern int prepare_binprm(struct linux_b
+ extern int __must_check remove_arg_zero(struct linux_binprm *);
+ extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
+ extern int flush_old_exec(struct linux_binprm * bprm);
++extern void setup_new_exec(struct linux_binprm * bprm);
+ extern int suid_dumpable;
+ #define SUID_DUMP_DISABLE     0       /* No setuid dumping */
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1354,7 +1354,7 @@ struct task_struct {
+       char comm[TASK_COMM_LEN]; /* executable name excluding path
+                                    - access with [gs]et_task_comm (which lock
+                                      it with task_lock())
+-                                   - initialized normally by flush_old_exec */
++                                   - initialized normally by setup_new_exec */
+ /* file system info */
+       int link_count, total_link_count;
+ #ifdef CONFIG_SYSVIPC
diff --git a/queue-2.6.32/x86-get-rid-of-the-insane-tif_abi_pending-bit.patch b/queue-2.6.32/x86-get-rid-of-the-insane-tif_abi_pending-bit.patch
new file mode 100644 (file)
index 0000000..bf0a3fa
--- /dev/null
@@ -0,0 +1,117 @@
+From 05d43ed8a89c159ff641d472f970e3f1baa66318 Mon Sep 17 00:00:00 2001
+From: H. Peter Anvin <hpa@zytor.com>
+Date: Thu, 28 Jan 2010 22:14:43 -0800
+Subject: x86: get rid of the insane TIF_ABI_PENDING bit
+
+From: H. Peter Anvin <hpa@zytor.com>
+
+commit 05d43ed8a89c159ff641d472f970e3f1baa66318 upstream.
+
+Now that the previous commit made it possible to do the personality
+setting at the point of no return, we do just that for ELF binaries.
+And suddenly all the reasons for that insane TIF_ABI_PENDING bit go
+away, and we can just make SET_PERSONALITY() just do the obvious thing
+for a 32-bit compat process.
+
+Everything becomes much more straightforward this way.
+
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/ia32/ia32_aout.c          |    1 -
+ arch/x86/include/asm/elf.h         |   10 ++--------
+ arch/x86/include/asm/thread_info.h |    2 --
+ arch/x86/kernel/process.c          |   12 ------------
+ arch/x86/kernel/process_64.c       |   11 +++++++++++
+ 5 files changed, 13 insertions(+), 23 deletions(-)
+
+--- a/arch/x86/ia32/ia32_aout.c
++++ b/arch/x86/ia32/ia32_aout.c
+@@ -311,7 +311,6 @@ static int load_aout_binary(struct linux
+       /* OK, This is the point of no return */
+       set_personality(PER_LINUX);
+       set_thread_flag(TIF_IA32);
+-      clear_thread_flag(TIF_ABI_PENDING);
+       setup_new_exec(bprm);
+--- a/arch/x86/include/asm/elf.h
++++ b/arch/x86/include/asm/elf.h
+@@ -197,14 +197,8 @@ do {                                                      \
+       set_fs(USER_DS);                                \
+ } while (0)
+-#define COMPAT_SET_PERSONALITY(ex)                    \
+-do {                                                  \
+-      if (test_thread_flag(TIF_IA32))                 \
+-              clear_thread_flag(TIF_ABI_PENDING);     \
+-      else                                            \
+-              set_thread_flag(TIF_ABI_PENDING);       \
+-      current->personality |= force_personality32;    \
+-} while (0)
++void set_personality_ia32(void);
++#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32()
+ #define COMPAT_ELF_PLATFORM                   ("i686")
+--- a/arch/x86/include/asm/thread_info.h
++++ b/arch/x86/include/asm/thread_info.h
+@@ -86,7 +86,6 @@ struct thread_info {
+ #define TIF_NOTSC             16      /* TSC is not accessible in userland */
+ #define TIF_IA32              17      /* 32bit process */
+ #define TIF_FORK              18      /* ret_from_fork */
+-#define TIF_ABI_PENDING               19
+ #define TIF_MEMDIE            20
+ #define TIF_DEBUG             21      /* uses debug registers */
+ #define TIF_IO_BITMAP         22      /* uses I/O bitmap */
+@@ -110,7 +109,6 @@ struct thread_info {
+ #define _TIF_NOTSC            (1 << TIF_NOTSC)
+ #define _TIF_IA32             (1 << TIF_IA32)
+ #define _TIF_FORK             (1 << TIF_FORK)
+-#define _TIF_ABI_PENDING      (1 << TIF_ABI_PENDING)
+ #define _TIF_DEBUG            (1 << TIF_DEBUG)
+ #define _TIF_IO_BITMAP                (1 << TIF_IO_BITMAP)
+ #define _TIF_FREEZE           (1 << TIF_FREEZE)
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -540,6 +540,17 @@ sys_clone(unsigned long clone_flags, uns
+       return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+ }
++void set_personality_ia32(void)
++{
++      /* inherit personality from parent */
++
++      /* Make sure to be in 32bit mode */
++      set_thread_flag(TIF_IA32);
++
++      /* Prepare the first "return" to user space */
++      current_thread_info()->status |= TS_COMPAT;
++}
++
+ unsigned long get_wchan(struct task_struct *p)
+ {
+       unsigned long stack;
+--- a/arch/x86/kernel/process.c
++++ b/arch/x86/kernel/process.c
+@@ -91,18 +91,6 @@ void flush_thread(void)
+ {
+       struct task_struct *tsk = current;
+-#ifdef CONFIG_X86_64
+-      if (test_tsk_thread_flag(tsk, TIF_ABI_PENDING)) {
+-              clear_tsk_thread_flag(tsk, TIF_ABI_PENDING);
+-              if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+-                      clear_tsk_thread_flag(tsk, TIF_IA32);
+-              } else {
+-                      set_tsk_thread_flag(tsk, TIF_IA32);
+-                      current_thread_info()->status |= TS_COMPAT;
+-              }
+-      }
+-#endif
+-
+       clear_tsk_thread_flag(tsk, TIF_DEBUG);
+       tsk->thread.debugreg0 = 0;