From: Greg Kroah-Hartman Date: Wed, 22 Sep 2010 20:18:58 +0000 (-0700) Subject: .35 patches X-Git-Tag: v2.6.35.6~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=603a7ec454e64c960cae8621d4a78514b4b8b3a4;p=thirdparty%2Fkernel%2Fstable-queue.git .35 patches --- diff --git a/queue-2.6.35/agp-intel-fix-dma-mask-bits-on-sandybridge.patch b/queue-2.6.35/agp-intel-fix-dma-mask-bits-on-sandybridge.patch new file mode 100644 index 00000000000..ad79a6f7291 --- /dev/null +++ b/queue-2.6.35/agp-intel-fix-dma-mask-bits-on-sandybridge.patch @@ -0,0 +1,58 @@ +From zhenyuw@linux.intel.com Wed Sep 22 13:11:16 2010 +From: Zhenyu Wang +Date: Sun, 19 Sep 2010 10:28:54 +0800 +Subject: agp/intel: fix dma mask bits on sandybridge +To: stable@kernel.org +Cc: tiwai@suse.de, chris@chris-wilson.co.uk +Message-ID: <1284863335-15989-4-git-send-email-zhenyuw@linux.intel.com> + +From: Zhenyu Wang + +[This is backport patch from upstream 877fdacf.] + +Signed-off-by: Zhenyu Wang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/agp/intel-agp.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/char/agp/intel-agp.c ++++ b/drivers/char/agp/intel-agp.c +@@ -835,7 +835,7 @@ static const struct intel_driver_descrip + static int __devinit intel_gmch_probe(struct pci_dev *pdev, + struct agp_bridge_data *bridge) + { +- int i; ++ int i, mask; + bridge->driver = NULL; + + for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { +@@ -855,14 +855,19 @@ static int __devinit intel_gmch_probe(st + + dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); + +- if (bridge->driver->mask_memory == intel_i965_mask_memory) { +- if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) +- dev_err(&intel_private.pcidev->dev, +- "set gfx device dma mask 36bit failed!\n"); +- else +- pci_set_consistent_dma_mask(intel_private.pcidev, +- DMA_BIT_MASK(36)); +- } ++ if (bridge->driver->mask_memory == intel_gen6_mask_memory) ++ mask = 40; ++ else if (bridge->driver->mask_memory == intel_i965_mask_memory) ++ mask = 36; ++ else ++ mask = 32; ++ ++ if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) ++ dev_err(&intel_private.pcidev->dev, ++ "set gfx device dma mask %d-bit failed!\n", mask); ++ else ++ pci_set_consistent_dma_mask(intel_private.pcidev, ++ DMA_BIT_MASK(mask)); + + return 1; + } diff --git a/queue-2.6.35/agp-intel-fix-physical-address-mask-bits-for-sandybridge.patch b/queue-2.6.35/agp-intel-fix-physical-address-mask-bits-for-sandybridge.patch new file mode 100644 index 00000000000..954a575c125 --- /dev/null +++ b/queue-2.6.35/agp-intel-fix-physical-address-mask-bits-for-sandybridge.patch @@ -0,0 +1,47 @@ +From zhenyuw@linux.intel.com Wed Sep 22 13:11:00 2010 +From: Zhenyu Wang +Date: Sun, 19 Sep 2010 10:28:53 +0800 +Subject: agp/intel: fix physical address mask bits for sandybridge +To: stable@kernel.org +Cc: tiwai@suse.de, chris@chris-wilson.co.uk +Message-ID: <1284863335-15989-3-git-send-email-zhenyuw@linux.intel.com> + +From: Zhenyu Wang + +[This is backport patch from upstream 8dfc2b14.] + +Signed-off-by: Zhenyu Wang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/agp/intel-gtt.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/char/agp/intel-gtt.c ++++ b/drivers/char/agp/intel-gtt.c +@@ -1317,6 +1317,16 @@ static unsigned long intel_i965_mask_mem + return addr | bridge->driver->masks[type].mask; + } + ++static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, ++ dma_addr_t addr, int type) ++{ ++ /* gen6 has bit11-4 for physical addr bit39-32 */ ++ addr |= (addr >> 28) & 0xff0; ++ ++ /* Type checking must be done elsewhere */ ++ return addr | bridge->driver->masks[type].mask; ++} ++ + static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) + { + u16 snb_gmch_ctl; +@@ -1535,7 +1545,7 @@ static const struct agp_bridge_driver in + .configure = intel_i9xx_configure, + .fetch_size = intel_i9xx_fetch_size, + .cleanup = intel_i915_cleanup, +- .mask_memory = intel_i965_mask_memory, ++ .mask_memory = intel_gen6_mask_memory, + .masks = intel_i810_masks, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, diff --git a/queue-2.6.35/intel_agp-drm-i915-add-all-sandybridge-graphics-devices-support.patch b/queue-2.6.35/intel_agp-drm-i915-add-all-sandybridge-graphics-devices-support.patch new file mode 100644 index 00000000000..b29183a4d10 --- /dev/null +++ b/queue-2.6.35/intel_agp-drm-i915-add-all-sandybridge-graphics-devices-support.patch @@ -0,0 +1,166 @@ +From zhenyuw@linux.intel.com Wed Sep 22 13:10:08 2010 +From: Zhenyu Wang +Date: Sun, 19 Sep 2010 10:28:52 +0800 +Subject: intel_agp, drm/i915: Add all sandybridge graphics devices support +To: stable@kernel.org +Cc: tiwai@suse.de, chris@chris-wilson.co.uk +Message-ID: <1284863335-15989-2-git-send-email-zhenyuw@linux.intel.com> + +From: Zhenyu Wang + +New pci ids for all sandybridge graphics versions on desktop/mobile/server. + +[This is backport patch from upstream commit 4fefe435 and 85540480.] + +Signed-off-by: Zhenyu Wang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/agp/intel-agp.c | 19 +++++++++++++++---- + drivers/char/agp/intel-agp.h | 17 ++++++++++++----- + drivers/char/agp/intel-gtt.c | 37 +++++++++++++++++++++++++++++++++++-- + drivers/gpu/drm/i915/i915_drv.c | 5 +++++ + 4 files changed, 67 insertions(+), 11 deletions(-) + +--- a/drivers/char/agp/intel-agp.c ++++ b/drivers/char/agp/intel-agp.c +@@ -815,10 +815,20 @@ static const struct intel_driver_descrip + "HD Graphics", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, + "HD Graphics", NULL, &intel_i965_driver }, +- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, +- "Sandybridge", NULL, &intel_i965_driver }, +- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, +- "Sandybridge", NULL, &intel_i965_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, ++ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, ++ "Sandybridge", NULL, &intel_gen6_driver }, + { 0, 0, NULL, NULL, NULL } + }; + +@@ -1036,6 +1046,7 @@ static struct pci_device_id agp_intel_pc + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), ++ ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), + { } + }; + +--- a/drivers/char/agp/intel-agp.h ++++ b/drivers/char/agp/intel-agp.h +@@ -194,10 +194,16 @@ + #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 + #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a + #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 +-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 +-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102 +-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 +-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ ++#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A + + /* cover 915 and 945 variants */ + #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ +@@ -224,7 +230,8 @@ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) + + #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ +- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) ++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \ ++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB) + + #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ +--- a/drivers/char/agp/intel-gtt.c ++++ b/drivers/char/agp/intel-gtt.c +@@ -585,8 +585,7 @@ static void intel_i830_init_gtt_entries( + gtt_entries = 0; + break; + } +- } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || +- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) { ++ } else if (IS_SNB) { + /* + * SandyBridge has new memory control reg at 0x50.w + */ +@@ -1337,6 +1336,7 @@ static void intel_i965_get_gtt_range(int + break; + case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: + case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: ++ case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: + *gtt_offset = MB(2); + + pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); +@@ -1497,6 +1497,39 @@ static const struct agp_bridge_driver in + .owner = THIS_MODULE, + .aperture_sizes = intel_i830_sizes, + .size_type = FIXED_APER_SIZE, ++ .num_aperture_sizes = 4, ++ .needs_scratch_page = true, ++ .configure = intel_i9xx_configure, ++ .fetch_size = intel_i9xx_fetch_size, ++ .cleanup = intel_i915_cleanup, ++ .mask_memory = intel_i965_mask_memory, ++ .masks = intel_i810_masks, ++ .agp_enable = intel_i810_agp_enable, ++ .cache_flush = global_cache_flush, ++ .create_gatt_table = intel_i965_create_gatt_table, ++ .free_gatt_table = intel_i830_free_gatt_table, ++ .insert_memory = intel_i915_insert_entries, ++ .remove_memory = intel_i915_remove_entries, ++ .alloc_by_type = intel_i830_alloc_by_type, ++ .free_by_type = intel_i810_free_by_type, ++ .agp_alloc_page = agp_generic_alloc_page, ++ .agp_alloc_pages = agp_generic_alloc_pages, ++ .agp_destroy_page = agp_generic_destroy_page, ++ .agp_destroy_pages = agp_generic_destroy_pages, ++ .agp_type_to_mask_type = intel_i830_type_to_mask_type, ++ .chipset_flush = intel_i915_chipset_flush, ++#ifdef USE_PCI_DMA_API ++ .agp_map_page = intel_agp_map_page, ++ .agp_unmap_page = intel_agp_unmap_page, ++ .agp_map_memory = intel_agp_map_memory, ++ .agp_unmap_memory = intel_agp_unmap_memory, ++#endif ++}; ++ ++static const struct agp_bridge_driver intel_gen6_driver = { ++ .owner = THIS_MODULE, ++ .aperture_sizes = intel_i830_sizes, ++ .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 4, + .needs_scratch_page = true, + .configure = intel_i9xx_configure, +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -180,7 +180,12 @@ static const struct pci_device_id pciidl + INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), + INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), + INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), ++ INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info), ++ INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), ++ INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info), ++ INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info), ++ INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info), + {0, 0, 0} + }; + diff --git a/queue-2.6.35/mm-fix-swapin-race-condition.patch b/queue-2.6.35/mm-fix-swapin-race-condition.patch new file mode 100644 index 00000000000..431ef819848 --- /dev/null +++ b/queue-2.6.35/mm-fix-swapin-race-condition.patch @@ -0,0 +1,176 @@ +From 4969c1192d15afa3389e7ae3302096ff684ba655 Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli +Date: Thu, 9 Sep 2010 16:37:52 -0700 +Subject: mm: fix swapin race condition + +From: Andrea Arcangeli + +commit 4969c1192d15afa3389e7ae3302096ff684ba655 upstream. + +The pte_same check is reliable only if the swap entry remains pinned (by +the page lock on swapcache). We've also to ensure the swapcache isn't +removed before we take the lock as try_to_free_swap won't care about the +page pin. + +One of the possible impacts of this patch is that a KSM-shared page can +point to the anon_vma of another process, which could exit before the page +is freed. + +This can leave a page with a pointer to a recycled anon_vma object, or +worse, a pointer to something that is no longer an anon_vma. + +[Backport to 2.6.35.5 (anon_vma instead of anon_vma->root in ksm.h) by Hugh] + +[riel@redhat.com: changelog help] +Signed-off-by: Andrea Arcangeli +Acked-by: Hugh Dickins +Reviewed-by: Rik van Riel +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Hugh Dickins +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/ksm.h | 20 +++++++++----------- + mm/ksm.c | 3 --- + mm/memory.c | 39 ++++++++++++++++++++++++++++++++++----- + 3 files changed, 43 insertions(+), 19 deletions(-) + +--- a/include/linux/ksm.h ++++ b/include/linux/ksm.h +@@ -16,6 +16,9 @@ + struct stable_node; + struct mem_cgroup; + ++struct page *ksm_does_need_to_copy(struct page *page, ++ struct vm_area_struct *vma, unsigned long address); ++ + #ifdef CONFIG_KSM + int ksm_madvise(struct vm_area_struct *vma, unsigned long start, + unsigned long end, int advice, unsigned long *vm_flags); +@@ -70,19 +73,14 @@ static inline void set_page_stable_node( + * We'd like to make this conditional on vma->vm_flags & VM_MERGEABLE, + * but what if the vma was unmerged while the page was swapped out? + */ +-struct page *ksm_does_need_to_copy(struct page *page, +- struct vm_area_struct *vma, unsigned long address); +-static inline struct page *ksm_might_need_to_copy(struct page *page, ++static inline int ksm_might_need_to_copy(struct page *page, + struct vm_area_struct *vma, unsigned long address) + { + struct anon_vma *anon_vma = page_anon_vma(page); + +- if (!anon_vma || +- (anon_vma == vma->anon_vma && +- page->index == linear_page_index(vma, address))) +- return page; +- +- return ksm_does_need_to_copy(page, vma, address); ++ return anon_vma && ++ (anon_vma != vma->anon_vma || ++ page->index != linear_page_index(vma, address)); + } + + int page_referenced_ksm(struct page *page, +@@ -115,10 +113,10 @@ static inline int ksm_madvise(struct vm_ + return 0; + } + +-static inline struct page *ksm_might_need_to_copy(struct page *page, ++static inline int ksm_might_need_to_copy(struct page *page, + struct vm_area_struct *vma, unsigned long address) + { +- return page; ++ return 0; + } + + static inline int page_referenced_ksm(struct page *page, +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -1523,8 +1523,6 @@ struct page *ksm_does_need_to_copy(struc + { + struct page *new_page; + +- unlock_page(page); /* any racers will COW it, not modify it */ +- + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); + if (new_page) { + copy_user_highpage(new_page, page, address, vma); +@@ -1540,7 +1538,6 @@ struct page *ksm_does_need_to_copy(struc + add_page_to_unevictable_list(new_page); + } + +- page_cache_release(page); + return new_page; + } + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2626,7 +2626,7 @@ static int do_swap_page(struct mm_struct + unsigned int flags, pte_t orig_pte) + { + spinlock_t *ptl; +- struct page *page; ++ struct page *page, *swapcache = NULL; + swp_entry_t entry; + pte_t pte; + struct mem_cgroup *ptr = NULL; +@@ -2681,10 +2681,23 @@ static int do_swap_page(struct mm_struct + lock_page(page); + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); + +- page = ksm_might_need_to_copy(page, vma, address); +- if (!page) { +- ret = VM_FAULT_OOM; +- goto out; ++ /* ++ * Make sure try_to_free_swap didn't release the swapcache ++ * from under us. The page pin isn't enough to prevent that. ++ */ ++ if (unlikely(!PageSwapCache(page))) ++ goto out_page; ++ ++ if (ksm_might_need_to_copy(page, vma, address)) { ++ swapcache = page; ++ page = ksm_does_need_to_copy(page, vma, address); ++ ++ if (unlikely(!page)) { ++ ret = VM_FAULT_OOM; ++ page = swapcache; ++ swapcache = NULL; ++ goto out_page; ++ } + } + + if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { +@@ -2735,6 +2748,18 @@ static int do_swap_page(struct mm_struct + if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) + try_to_free_swap(page); + unlock_page(page); ++ if (swapcache) { ++ /* ++ * Hold the lock to avoid the swap entry to be reused ++ * until we take the PT lock for the pte_same() check ++ * (to avoid false positives from pte_same). For ++ * further safety release the lock after the swap_free ++ * so that the swap count won't change under a ++ * parallel locked swapcache. ++ */ ++ unlock_page(swapcache); ++ page_cache_release(swapcache); ++ } + + if (flags & FAULT_FLAG_WRITE) { + ret |= do_wp_page(mm, vma, address, page_table, pmd, ptl, pte); +@@ -2756,6 +2781,10 @@ out_page: + unlock_page(page); + out_release: + page_cache_release(page); ++ if (swapcache) { ++ unlock_page(swapcache); ++ page_cache_release(swapcache); ++ } + return ret; + } + diff --git a/queue-2.6.35/mm-further-fix-swapin-race-condition.patch b/queue-2.6.35/mm-further-fix-swapin-race-condition.patch new file mode 100644 index 00000000000..cad8c0a5445 --- /dev/null +++ b/queue-2.6.35/mm-further-fix-swapin-race-condition.patch @@ -0,0 +1,73 @@ +From 31c4a3d3a0f84a5847665f8aa0552d188389f791 Mon Sep 17 00:00:00 2001 +From: Hugh Dickins +Date: Sun, 19 Sep 2010 19:40:22 -0700 +Subject: mm: further fix swapin race condition + +From: Hugh Dickins + +commit 31c4a3d3a0f84a5847665f8aa0552d188389f791 upstream. + +Commit 4969c1192d15 ("mm: fix swapin race condition") is now agreed to +be incomplete. There's a race, not very much less likely than the +original race envisaged, in which it is further necessary to check that +the swapcache page's swap has not changed. + +Here's the reasoning: cast in terms of reuse_swap_page(), but probably +could be reformulated to rely on try_to_free_swap() instead, or on +swapoff+swapon. + +A, faults into do_swap_page(): does page1 = lookup_swap_cache(swap1) and +comes through the lock_page(page1). + +B, a racing thread of the same process, faults on the same address: does +page1 = lookup_swap_cache(swap1) and now waits in lock_page(page1), but +for whatever reason is unlucky not to get the lock any time soon. + +A carries on through do_swap_page(), a write fault, but cannot reuse the +swap page1 (another reference to swap1). Unlocks the page1 (but B +doesn't get it yet), does COW in do_wp_page(), page2 now in that pte. + +C, perhaps the parent of A+B, comes in and write faults the same swap +page1 into its mm, reuse_swap_page() succeeds this time, swap1 is freed. + +kswapd comes in after some time (B still unlucky) and swaps out some +pages from A+B and C: it allocates the original swap1 to page2 in A+B, +and some other swap2 to the original page1 now in C. But does not +immediately free page1 (actually it couldn't: B holds a reference), +leaving it in swap cache for now. + +B at last gets the lock on page1, hooray! Is PageSwapCache(page1)? Yes. +Is pte_same(*page_table, orig_pte)? Yes, because page2 has now been +given the swap1 which page1 used to have. So B proceeds to insert page1 +into A+B's page_table, though its content now belongs to C, quite +different from what A wrote there. + +B ought to have checked that page1's swap was still swap1. + +Signed-off-by: Hugh Dickins +Reviewed-by: Rik van Riel +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/memory.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2682,10 +2682,12 @@ static int do_swap_page(struct mm_struct + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); + + /* +- * Make sure try_to_free_swap didn't release the swapcache +- * from under us. The page pin isn't enough to prevent that. ++ * Make sure try_to_free_swap or reuse_swap_page or swapoff did not ++ * release the swapcache from under us. The page pin, and pte_same ++ * test below, are not enough to exclude that. Even if it is still ++ * swapcache, we need to check that the page's swap has not changed. + */ +- if (unlikely(!PageSwapCache(page))) ++ if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) + goto out_page; + + if (ksm_might_need_to_copy(page, vma, address)) { diff --git a/queue-2.6.35/net-llc-make-opt-unsigned-in-llc_ui_setsockopt.patch b/queue-2.6.35/net-llc-make-opt-unsigned-in-llc_ui_setsockopt.patch new file mode 100644 index 00000000000..f4c1a4bd5e1 --- /dev/null +++ b/queue-2.6.35/net-llc-make-opt-unsigned-in-llc_ui_setsockopt.patch @@ -0,0 +1,33 @@ +From 339db11b219f36cf7da61b390992d95bb6b7ba2e Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 10 Sep 2010 01:56:16 +0000 +Subject: net/llc: make opt unsigned in llc_ui_setsockopt() + +From: Dan Carpenter + +commit 339db11b219f36cf7da61b390992d95bb6b7ba2e upstream. + +The members of struct llc_sock are unsigned so if we pass a negative +value for "opt" it can cause a sign bug. Also it can cause an integer +overflow when we multiply "opt * HZ". + +Signed-off-by: Dan Carpenter +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/llc/af_llc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -1024,7 +1024,8 @@ static int llc_ui_setsockopt(struct sock + { + struct sock *sk = sock->sk; + struct llc_sock *llc = llc_sk(sk); +- int rc = -EINVAL, opt; ++ unsigned int opt; ++ int rc = -EINVAL; + + lock_sock(sk); + if (unlikely(level != SOL_LLC || optlen != sizeof(int))) diff --git a/queue-2.6.35/series b/queue-2.6.35/series index c0b1adf3b07..547ac6b7280 100644 --- a/queue-2.6.35/series +++ b/queue-2.6.35/series @@ -19,3 +19,12 @@ drivers-net-usb-hso.c-prevent-reading-uninitialized-memory.patch drivers-net-cxgb3-cxgb3_main.c-prevent-reading-uninitialized-stack-memory.patch drivers-net-eql.c-prevent-reading-uninitialized-stack-memory.patch bonding-correctly-process-non-linear-skbs.patch +staging-vt6655-fix-buffer-overflow.patch +net-llc-make-opt-unsigned-in-llc_ui_setsockopt.patch +mm-fix-swapin-race-condition.patch +mm-further-fix-swapin-race-condition.patch +virtio-console-prevent-userspace-from-submitting-null-buffers.patch +virtio-console-fix-poll-blocking-even-though-there-is-data-to-read.patch +intel_agp-drm-i915-add-all-sandybridge-graphics-devices-support.patch +agp-intel-fix-physical-address-mask-bits-for-sandybridge.patch +agp-intel-fix-dma-mask-bits-on-sandybridge.patch diff --git a/queue-2.6.35/staging-vt6655-fix-buffer-overflow.patch b/queue-2.6.35/staging-vt6655-fix-buffer-overflow.patch new file mode 100644 index 00000000000..14f738af287 --- /dev/null +++ b/queue-2.6.35/staging-vt6655-fix-buffer-overflow.patch @@ -0,0 +1,48 @@ +From dd173abfead903c7df54e977535973f3312cd307 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 6 Sep 2010 14:32:30 +0200 +Subject: Staging: vt6655: fix buffer overflow + +From: Dan Carpenter + +commit dd173abfead903c7df54e977535973f3312cd307 upstream. + +"param->u.wpa_associate.wpa_ie_len" comes from the user. We should +check it so that the copy_from_user() doesn't overflow the buffer. + +Also further down in the function, we assume that if +"param->u.wpa_associate.wpa_ie_len" is set then "abyWPAIE[0]" is +initialized. To make that work, I changed the test here to say that if +"wpa_ie_len" is set then "wpa_ie" has to be a valid pointer or we return +-EINVAL. + +Oddly, we only use the first element of the abyWPAIE[] array. So I +suspect there may be some other issues in this function. + +Signed-off-by: Dan Carpenter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6655/wpactl.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/staging/vt6655/wpactl.c ++++ b/drivers/staging/vt6655/wpactl.c +@@ -766,9 +766,14 @@ static int wpa_set_associate(PSDevice pD + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); + + +- if (param->u.wpa_associate.wpa_ie && +- copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) +- return -EINVAL; ++ if (param->u.wpa_associate.wpa_ie_len) { ++ if (!param->u.wpa_associate.wpa_ie) ++ return -EINVAL; ++ if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) ++ return -EINVAL; ++ if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) ++ return -EFAULT; ++ } + + if (param->u.wpa_associate.mode == 1) + pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; diff --git a/queue-2.6.35/virtio-console-fix-poll-blocking-even-though-there-is-data-to-read.patch b/queue-2.6.35/virtio-console-fix-poll-blocking-even-though-there-is-data-to-read.patch new file mode 100644 index 00000000000..24d2da6003f --- /dev/null +++ b/queue-2.6.35/virtio-console-fix-poll-blocking-even-though-there-is-data-to-read.patch @@ -0,0 +1,43 @@ +From 6df7aadcd9290807c464675098b5dd2dc9da5075 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 16 Sep 2010 14:43:08 +0530 +Subject: virtio: console: Fix poll blocking even though there is data to read + +From: Hans de Goede + +commit 6df7aadcd9290807c464675098b5dd2dc9da5075 upstream. + +I found this while working on a Linux agent for spice, the symptom I was +seeing was select blocking on the spice vdagent virtio serial port even +though there were messages queued up there. + +virtio_console's port_fops_poll checks port->inbuf != NULL to determine +if read won't block. However if an application reads enough bytes from +inbuf through port_fops_read, to empty the current port->inbuf, +port->inbuf will be NULL even though there may be buffers left in the +virtqueue. + +This causes poll() to block even though there is data to be read, +this patch fixes this by using will_read_block(port) instead of the +port->inbuf != NULL check. + +Signed-off-By: Hans de Goede +Signed-off-by: Amit Shah +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/virtio_console.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -646,7 +646,7 @@ static unsigned int port_fops_poll(struc + poll_wait(filp, &port->waitqueue, wait); + + ret = 0; +- if (port->inbuf) ++ if (!will_read_block(port)) + ret |= POLLIN | POLLRDNORM; + if (!will_write_block(port)) + ret |= POLLOUT; diff --git a/queue-2.6.35/virtio-console-prevent-userspace-from-submitting-null-buffers.patch b/queue-2.6.35/virtio-console-prevent-userspace-from-submitting-null-buffers.patch new file mode 100644 index 00000000000..f2de8eced7e --- /dev/null +++ b/queue-2.6.35/virtio-console-prevent-userspace-from-submitting-null-buffers.patch @@ -0,0 +1,37 @@ +From 65745422a898741ee0e7068ef06624ab06e8aefa Mon Sep 17 00:00:00 2001 +From: Amit Shah +Date: Tue, 14 Sep 2010 13:26:16 +0530 +Subject: virtio: console: Prevent userspace from submitting NULL buffers + +From: Amit Shah + +commit 65745422a898741ee0e7068ef06624ab06e8aefa upstream. + +A userspace could submit a buffer with 0 length to be written to the +host. Prevent such a situation. + +This was not needed previously, but recent changes in the way write() +works exposed this condition to trigger a virtqueue event to the host, +causing a NULL buffer to be sent across. + +Signed-off-by: Amit Shah +Signed-off-by: Rusty Russell +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/virtio_console.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -596,6 +596,10 @@ static ssize_t port_fops_write(struct fi + ssize_t ret; + bool nonblock; + ++ /* Userspace could be out to fool us */ ++ if (!count) ++ return 0; ++ + port = filp->private_data; + + nonblock = filp->f_flags & O_NONBLOCK;