diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-11-11 20:34:33 -0500 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-11-11 20:34:33 -0500 |
commit | 501871719a80080804d8d635c8d1efc469b4c282 (patch) | |
tree | 14f2681b360ac07620f72c1b81b9f01fec571905 | |
parent | 799dcbf071cffe1dfcb44bc5670e64a637b2ed4c (diff) | |
download | longterm-queue-2.6.34-501871719a80080804d8d635c8d1efc469b4c282.tar.gz |
32.51: import parallel commits made from that release
Pull in the upstream commits made to the 2.6.32.51 release.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
17 files changed, 1341 insertions, 0 deletions
diff --git a/queue/ALSA-hda-realtek-Fix-Oops-in-alc_mux_select.patch b/queue/ALSA-hda-realtek-Fix-Oops-in-alc_mux_select.patch new file mode 100644 index 0000000..7ebb63b --- /dev/null +++ b/queue/ALSA-hda-realtek-Fix-Oops-in-alc_mux_select.patch @@ -0,0 +1,35 @@ +From 210105d395a57350f441de2fb16b36d4b6655a03 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Fri, 2 Dec 2011 15:29:12 +0100 +Subject: [PATCH] ALSA: hda/realtek - Fix Oops in alc_mux_select() + +commit cce4aa378a049f4275416ee6302dd24f37b289df upstream. + +When no imux is available (e.g. a single capture source), +alc_auto_init_input_src() may trigger an Oops due to the access to -1. +Add a proper zero-check to avoid it. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[PG: in mainline, 21268961d3 rewrites and creates alc_mux_select, but the +code that needed the check still existed prior to that in alc_mux_enum_put] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + sound/pci/hda/patch_realtek.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 94f1a80..28118fd 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -444,6 +444,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, + imux = &spec->input_mux[mux_idx]; + if (!imux->num_items && mux_idx > 0) + imux = &spec->input_mux[0]; ++ if (!imux->num_items) ++ return 0; + + type = get_wcaps_type(get_wcaps(codec, nid)); + if (type == AC_WID_AUD_MIX) { +-- +1.7.12.1 + diff --git a/queue/ALSA-sis7019-give-slow-codecs-more-time-to-reset.patch b/queue/ALSA-sis7019-give-slow-codecs-more-time-to-reset.patch new file mode 100644 index 0000000..7dfbcf0 --- /dev/null +++ b/queue/ALSA-sis7019-give-slow-codecs-more-time-to-reset.patch @@ -0,0 +1,142 @@ +From da7f32b37d8e8275e8b8c2a2310f652da5095b7f Mon Sep 17 00:00:00 2001 +From: David Dillow <dave@thedillows.org> +Date: Thu, 1 Dec 2011 23:26:53 -0500 +Subject: [PATCH] ALSA: sis7019 - give slow codecs more time to reset + +commit fc084e0b930d546872ab23667052499f7daf0fed upstream. + +There are some AC97 codec and board combinations that have been observed +to take a very long time to respond after the cold reset has completed. +In one case, more than 350 ms was required. To allow users to have sound +on those platforms, we'll wait up to 500ms for the codec to become +ready. + +As a board may have multiple codecs, with some faster than others to +reset, we add a module parameter to inform the driver which codecs +should be present. + +Reported-by: KotCzarny <tjosko@yahoo.com> +Signed-off-by: David Dillow <dave@thedillows.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + sound/pci/sis7019.c | 64 ++++++++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 53 insertions(+), 11 deletions(-) + +diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c +index 9cc1b5a..7458323 100644 +--- a/sound/pci/sis7019.c ++++ b/sound/pci/sis7019.c +@@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); + static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ + static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ + static int enable = 1; ++static int codecs = 1; + + module_param(index, int, 0444); + MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); +@@ -48,6 +49,8 @@ module_param(id, charp, 0444); + MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); + module_param(enable, bool, 0444); + MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); ++module_param(codecs, int, 0444); ++MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); + + static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { + { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, +@@ -140,6 +143,9 @@ struct sis7019 { + dma_addr_t silence_dma_addr; + }; + ++/* These values are also used by the module param 'codecs' to indicate ++ * which codecs should be present. ++ */ + #define SIS_PRIMARY_CODEC_PRESENT 0x0001 + #define SIS_SECONDARY_CODEC_PRESENT 0x0002 + #define SIS_TERTIARY_CODEC_PRESENT 0x0004 +@@ -1076,6 +1082,7 @@ static int sis_chip_init(struct sis7019 *sis) + { + unsigned long io = sis->ioport; + void __iomem *ioaddr = sis->ioaddr; ++ unsigned long timeout; + u16 status; + int count; + int i; +@@ -1102,21 +1109,45 @@ static int sis_chip_init(struct sis7019 *sis) + while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) + udelay(1); + ++ /* Command complete, we can let go of the semaphore now. ++ */ ++ outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); ++ if (!count) ++ return -EIO; ++ + /* Now that we've finished the reset, find out what's attached. ++ * There are some codec/board combinations that take an extremely ++ * long time to come up. 350+ ms has been observed in the field, ++ * so we'll give them up to 500ms. + */ +- status = inl(io + SIS_AC97_STATUS); +- if (status & SIS_AC97_STATUS_CODEC_READY) +- sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; +- if (status & SIS_AC97_STATUS_CODEC2_READY) +- sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; +- if (status & SIS_AC97_STATUS_CODEC3_READY) +- sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; +- +- /* All done, let go of the semaphore, and check for errors ++ sis->codecs_present = 0; ++ timeout = msecs_to_jiffies(500) + jiffies; ++ while (time_before_eq(jiffies, timeout)) { ++ status = inl(io + SIS_AC97_STATUS); ++ if (status & SIS_AC97_STATUS_CODEC_READY) ++ sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; ++ if (status & SIS_AC97_STATUS_CODEC2_READY) ++ sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; ++ if (status & SIS_AC97_STATUS_CODEC3_READY) ++ sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; ++ ++ if (sis->codecs_present == codecs) ++ break; ++ ++ msleep(1); ++ } ++ ++ /* All done, check for errors. + */ +- outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); +- if (!sis->codecs_present || !count) ++ if (!sis->codecs_present) { ++ printk(KERN_ERR "sis7019: could not find any codecs\n"); + return -EIO; ++ } ++ ++ if (sis->codecs_present != codecs) { ++ printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", ++ sis->codecs_present, codecs); ++ } + + /* Let the hardware know that the audio driver is alive, + * and enable PCM slots on the AC-link for L/R playback (3 & 4) and +@@ -1388,6 +1419,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, + if (!enable) + goto error_out; + ++ /* The user can specify which codecs should be present so that we ++ * can wait for them to show up if they are slow to recover from ++ * the AC97 cold reset. We default to a single codec, the primary. ++ * ++ * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. ++ */ ++ codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | ++ SIS_TERTIARY_CODEC_PRESENT; ++ if (!codecs) ++ codecs = SIS_PRIMARY_CODEC_PRESENT; ++ + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); + if (rc < 0) + goto error_out; +-- +1.7.12.1 + diff --git a/queue/ARM-davinci-dm646x-evm-wrong-register-used-in-setup_.patch b/queue/ARM-davinci-dm646x-evm-wrong-register-used-in-setup_.patch new file mode 100644 index 0000000..7abcbe0 --- /dev/null +++ b/queue/ARM-davinci-dm646x-evm-wrong-register-used-in-setup_.patch @@ -0,0 +1,56 @@ +From 1ecaea6802cc79f65f0bd398e69b8dbd14ec8c2b Mon Sep 17 00:00:00 2001 +From: Hans Verkuil <hans.verkuil@cisco.com> +Date: Mon, 14 Nov 2011 19:20:49 +0100 +Subject: [PATCH] ARM: davinci: dm646x evm: wrong register used in + setup_vpif_input_channel_mode + +commit 83713fc9373be2e943f82e9d36213708c6b0050e upstream. + +The function setup_vpif_input_channel_mode() used the VSCLKDIS register +instead of VIDCLKCTL. This meant that when in HD mode videoport channel 0 +used a different clock from channel 1. + +Clearly a copy-and-paste error. + +Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> +Acked-by: Manjunath Hadli <manjunath.hadli@ti.com> +Signed-off-by: Sekhar Nori <nsekhar@ti.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + arch/arm/mach-davinci/board-dm646x-evm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c +index 5ba3cb2..ff0fd90 100644 +--- a/arch/arm/mach-davinci/board-dm646x-evm.c ++++ b/arch/arm/mach-davinci/board-dm646x-evm.c +@@ -555,7 +555,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) + int val; + u32 value; + +- if (!vpif_vsclkdis_reg || !cpld_client) ++ if (!vpif_vidclkctl_reg || !cpld_client) + return -ENXIO; + + val = i2c_smbus_read_byte(cpld_client); +@@ -563,7 +563,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) + return val; + + spin_lock_irqsave(&vpif_reg_lock, flags); +- value = __raw_readl(vpif_vsclkdis_reg); ++ value = __raw_readl(vpif_vidclkctl_reg); + if (mux_mode) { + val &= VPIF_INPUT_TWO_CHANNEL; + value |= VIDCH1CLK; +@@ -571,7 +571,7 @@ static int setup_vpif_input_channel_mode(int mux_mode) + val |= VPIF_INPUT_ONE_CHANNEL; + value &= ~VIDCH1CLK; + } +- __raw_writel(value, vpif_vsclkdis_reg); ++ __raw_writel(value, vpif_vidclkctl_reg); + spin_unlock_irqrestore(&vpif_reg_lock, flags); + + err = i2c_smbus_write_byte(cpld_client, val); +-- +1.7.12.1 + diff --git a/queue/Make-TASKSTATS-require-root-access.patch b/queue/Make-TASKSTATS-require-root-access.patch new file mode 100644 index 0000000..b148a03 --- /dev/null +++ b/queue/Make-TASKSTATS-require-root-access.patch @@ -0,0 +1,39 @@ +From a8544896d36e1820d919b67f10da3f9883ccae7e Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Mon, 19 Sep 2011 17:04:37 -0700 +Subject: [PATCH] Make TASKSTATS require root access + +commit 1a51410abe7d0ee4b1d112780f46df87d3621043 upstream. + +Ok, this isn't optimal, since it means that 'iotop' needs admin +capabilities, and we may have to work on this some more. But at the +same time it is very much not acceptable to let anybody just read +anybody elses IO statistics quite at this level. + +Use of the GENL_ADMIN_PERM suggested by Johannes Berg as an alternative +to checking the capabilities by hand. + +Reported-by: Vasiliy Kulikov <segoon@openwall.com> +Cc: Johannes Berg <johannes.berg@intel.com> +Acked-by: Balbir Singh <bsingharora@gmail.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + kernel/taskstats.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/taskstats.c b/kernel/taskstats.c +index 5e21645..d5a70a0 100644 +--- a/kernel/taskstats.c ++++ b/kernel/taskstats.c +@@ -591,6 +591,7 @@ static struct genl_ops taskstats_ops = { + .cmd = TASKSTATS_CMD_GET, + .doit = taskstats_user_cmd, + .policy = taskstats_cmd_get_policy, ++ .flags = GENL_ADMIN_PERM, + }; + + static struct genl_ops cgroupstats_ops = { +-- +1.7.12.1 + diff --git a/queue/USB-cdc-acm-add-IDs-for-Motorola-H24-HSPA-USB-module.patch b/queue/USB-cdc-acm-add-IDs-for-Motorola-H24-HSPA-USB-module.patch new file mode 100644 index 0000000..81fa58c --- /dev/null +++ b/queue/USB-cdc-acm-add-IDs-for-Motorola-H24-HSPA-USB-module.patch @@ -0,0 +1,45 @@ +From 244358bbf4c276b271106c4e346223a1bfd67231 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Krzysztof=20Ha=C5=82asa?= <khalasa@piap.pl> +Date: Mon, 12 Dec 2011 14:51:00 +0100 +Subject: [PATCH] USB: cdc-acm: add IDs for Motorola H24 HSPA USB module. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 6abff5dc4d5a2c90e597137ce8987e7fd439259b upstream. + +Add USB IDs for Motorola H24 HSPA USB module. + +Signed-off-by: Krzysztof HaĆasa <khalasa@piap.pl> +Acked-by: Oliver Neukum <oneukum@suse.de> +Cc: stable <stable@vger.kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/usb/class/cdc-acm.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index db34eb4..af45f73 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1545,6 +1545,16 @@ static const struct usb_device_id acm_ids[] = { + }, + { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ + }, ++ /* Motorola H24 HSPA module: */ ++ { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */ ++ { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */ ++ { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */ ++ { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */ ++ { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */ ++ { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */ ++ { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */ ++ { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */ ++ + { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ + .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on + data interface instead of +-- +1.7.12.1 + diff --git a/queue/export-__get_user_pages_fast-function.patch b/queue/export-__get_user_pages_fast-function.patch new file mode 100644 index 0000000..6ed0b8b --- /dev/null +++ b/queue/export-__get_user_pages_fast-function.patch @@ -0,0 +1,46 @@ +From ced5b1a7324cd41664e46d21efd2f245d7d8bd5b Mon Sep 17 00:00:00 2001 +From: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> +Date: Sun, 22 Aug 2010 19:08:57 +0800 +Subject: [PATCH] export __get_user_pages_fast() function + +commit 45888a0c6edc305495b6bd72a30e66bc40b324c6 upstream. + +This function is used by KVM to pin process's page in the atomic context. + +Define the 'weak' function to avoid other architecture not support it + +Acked-by: Nick Piggin <npiggin@suse.de> +Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> +Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/util.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/mm/util.c b/mm/util.c +index f5712e8..4f0d32b 100644 +--- a/mm/util.c ++++ b/mm/util.c +@@ -250,6 +250,19 @@ void arch_pick_mmap_layout(struct mm_struct *mm) + } + #endif + ++/* ++ * Like get_user_pages_fast() except its IRQ-safe in that it won't fall ++ * back to the regular GUP. ++ * If the architecture not support this fucntion, simply return with no ++ * page pinned ++ */ ++int __attribute__((weak)) __get_user_pages_fast(unsigned long start, ++ int nr_pages, int write, struct page **pages) ++{ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(__get_user_pages_fast); ++ + /** + * get_user_pages_fast() - pin user pages in memory + * @start: starting user address +-- +1.7.12.1 + diff --git a/queue/ext4-avoid-hangs-in-ext4_da_should_update_i_disksize.patch b/queue/ext4-avoid-hangs-in-ext4_da_should_update_i_disksize.patch new file mode 100644 index 0000000..d9cfb7b --- /dev/null +++ b/queue/ext4-avoid-hangs-in-ext4_da_should_update_i_disksize.patch @@ -0,0 +1,95 @@ +From 52abc74418d9cbf23e78dcfcca719d4b91b08ae4 Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli <aarcange@redhat.com> +Date: Tue, 13 Dec 2011 21:41:15 -0500 +Subject: [PATCH] ext4: avoid hangs in ext4_da_should_update_i_disksize() + +commit ea51d132dbf9b00063169c1159bee253d9649224 upstream. + +If the pte mapping in generic_perform_write() is unmapped between +iov_iter_fault_in_readable() and iov_iter_copy_from_user_atomic(), the +"copied" parameter to ->end_write can be zero. ext4 couldn't cope with +it with delayed allocations enabled. This skips the i_disksize +enlargement logic if copied is zero and no new data was appeneded to +the inode. + + gdb> bt + #0 0xffffffff811afe80 in ext4_da_should_update_i_disksize (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x1\ + 08000, len=0x1000, copied=0x0, page=0xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2467 + #1 ext4_da_write_end (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x108000, len=0x1000, copied=0x0, page=0\ + xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2512 + #2 0xffffffff810d97f1 in generic_perform_write (iocb=<value optimized out>, iov=<value optimized out>, nr_segs=<value o\ + ptimized out>, pos=0x108000, ppos=0xffff88001e26be40, count=<value optimized out>, written=0x0) at mm/filemap.c:2440 + #3 generic_file_buffered_write (iocb=<value optimized out>, iov=<value optimized out>, nr_segs=<value optimized out>, p\ + os=0x108000, ppos=0xffff88001e26be40, count=<value optimized out>, written=0x0) at mm/filemap.c:2482 + #4 0xffffffff810db5d1 in __generic_file_aio_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=0x1, ppos=0\ + xffff88001e26be40) at mm/filemap.c:2600 + #5 0xffffffff810db853 in generic_file_aio_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=<value optimi\ + zed out>, pos=<value optimized out>) at mm/filemap.c:2632 + #6 0xffffffff811a71aa in ext4_file_write (iocb=0xffff88001e26bde8, iov=0xffff88001e26bec8, nr_segs=0x1, pos=0x108000) a\ + t fs/ext4/file.c:136 + #7 0xffffffff811375aa in do_sync_write (filp=0xffff88003f606a80, buf=<value optimized out>, len=<value optimized out>, \ + ppos=0xffff88001e26bf48) at fs/read_write.c:406 + #8 0xffffffff81137e56 in vfs_write (file=0xffff88003f606a80, buf=0x1ec2960 <Address 0x1ec2960 out of bounds>, count=0x4\ + 000, pos=0xffff88001e26bf48) at fs/read_write.c:435 + #9 0xffffffff8113816c in sys_write (fd=<value optimized out>, buf=0x1ec2960 <Address 0x1ec2960 out of bounds>, count=0x\ + 4000) at fs/read_write.c:487 + #10 <signal handler called> + #11 0x00007f120077a390 in __brk_reservation_fn_dmi_alloc__ () + #12 0x0000000000000000 in ?? () + gdb> print offset + $22 = 0xffffffffffffffff + gdb> print idx + $23 = 0xffffffff + gdb> print inode->i_blkbits + $24 = 0xc + gdb> up + #1 ext4_da_write_end (file=0xffff88003f606a80, mapping=0xffff88001d3824e0, pos=0x108000, len=0x1000, copied=0x0, page=0\ + xffffea0000d792e8, fsdata=0x0) at fs/ext4/inode.c:2512 + 2512 if (ext4_da_should_update_i_disksize(page, end)) { + gdb> print start + $25 = 0x0 + gdb> print end + $26 = 0xffffffffffffffff + gdb> print pos + $27 = 0x108000 + gdb> print new_i_size + $28 = 0x108000 + gdb> print ((struct ext4_inode_info *)((char *)inode-((int)(&((struct ext4_inode_info *)0)->vfs_inode))))->i_disksize + $29 = 0xd9000 + gdb> down + 2467 for (i = 0; i < idx; i++) + gdb> print i + $30 = 0xd44acbee + +This is 100% reproducible with some autonuma development code tuned in +a very aggressive manner (not normal way even for knumad) which does +"exotic" changes to the ptes. It wouldn't normally trigger but I don't +see why it can't happen normally if the page is added to swap cache in +between the two faults leading to "copied" being zero (which then +hangs in ext4). So it should be fixed. Especially possible with lumpy +reclaim (albeit disabled if compaction is enabled) as that would +ignore the young bits in the ptes. + +Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + fs/ext4/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 904f3e4..b8965bb 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3223,7 +3223,7 @@ static int ext4_da_write_end(struct file *file, + */ + + new_i_size = pos + copied; +- if (new_i_size > EXT4_I(inode)->i_disksize) { ++ if (copied && new_i_size > EXT4_I(inode)->i_disksize) { + if (ext4_da_should_update_i_disksize(page, end)) { + down_write(&EXT4_I(inode)->i_data_sem); + if (new_i_size > EXT4_I(inode)->i_disksize) { +-- +1.7.12.1 + diff --git a/queue/hfs-fix-hfs_find_init-sb-ext_tree-NULL-ptr-oops.patch b/queue/hfs-fix-hfs_find_init-sb-ext_tree-NULL-ptr-oops.patch new file mode 100644 index 0000000..81d290b --- /dev/null +++ b/queue/hfs-fix-hfs_find_init-sb-ext_tree-NULL-ptr-oops.patch @@ -0,0 +1,91 @@ +From 25c35c49a1a97a124bdd8b71389eaf2eb4756f70 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher <plougher@redhat.com> +Date: Wed, 2 Nov 2011 13:38:01 -0700 +Subject: [PATCH] hfs: fix hfs_find_init() sb->ext_tree NULL ptr oops + +commit 434a964daa14b9db083ce20404a4a2add54d037a upstream. + +Clement Lecigne reports a filesystem which causes a kernel oops in +hfs_find_init() trying to dereference sb->ext_tree which is NULL. + +This proves to be because the filesystem has a corrupted MDB extent +record, where the extents file does not fit into the first three extents +in the file record (the first blocks). + +In hfs_get_block() when looking up the blocks for the extent file +(HFS_EXT_CNID), it fails the first blocks special case, and falls +through to the extent code (which ultimately calls hfs_find_init()) +which is in the process of being initialised. + +Hfs avoids this scenario by always having the extents b-tree fitting +into the first blocks (the extents B-tree can't have overflow extents). + +The fix is to check at mount time that the B-tree fits into first +blocks, i.e. fail if HFS_I(inode)->alloc_blocks >= +HFS_I(inode)->first_blocks + +Note, the existing commit 47f365eb57573 ("hfs: fix oops on mount with +corrupted btree extent records") becomes subsumed into this as a special +case, but only for the extents B-tree (HFS_EXT_CNID), it is perfectly +acceptable for the catalog B-Tree file to grow beyond three extents, +with the remaining extent descriptors in the extents overfow. + +This fixes CVE-2011-2203 + +Reported-by: Clement LECIGNE <clement.lecigne@netasq.com> +Signed-off-by: Phillip Lougher <plougher@redhat.com> +Cc: Jeff Mahoney <jeffm@suse.com> +Cc: Christoph Hellwig <hch@lst.de> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + fs/hfs/btree.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c +index 38a0a99..d4e98a7 100644 +--- a/fs/hfs/btree.c ++++ b/fs/hfs/btree.c +@@ -46,11 +46,26 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke + case HFS_EXT_CNID: + hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize, + mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz)); ++ if (HFS_I(tree->inode)->alloc_blocks > ++ HFS_I(tree->inode)->first_blocks) { ++ printk(KERN_ERR "hfs: invalid btree extent records\n"); ++ unlock_new_inode(tree->inode); ++ goto free_inode; ++ } ++ + tree->inode->i_mapping->a_ops = &hfs_btree_aops; + break; + case HFS_CAT_CNID: + hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize, + mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz)); ++ ++ if (!HFS_I(tree->inode)->first_blocks) { ++ printk(KERN_ERR "hfs: invalid btree extent records " ++ "(0 size).\n"); ++ unlock_new_inode(tree->inode); ++ goto free_inode; ++ } ++ + tree->inode->i_mapping->a_ops = &hfs_btree_aops; + break; + default: +@@ -59,11 +74,6 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke + } + unlock_new_inode(tree->inode); + +- if (!HFS_I(tree->inode)->first_blocks) { +- printk(KERN_ERR "hfs: invalid btree extent records (0 size).\n"); +- goto free_inode; +- } +- + mapping = tree->inode->i_mapping; + page = read_mapping_page(mapping, 0, NULL); + if (IS_ERR(page)) +-- +1.7.12.1 + diff --git a/queue/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch b/queue/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch new file mode 100644 index 0000000..4a13160 --- /dev/null +++ b/queue/jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch @@ -0,0 +1,98 @@ +From a969d570ffeb680d00db25573727611a923ed163 Mon Sep 17 00:00:00 2001 +From: Eryu Guan <guaneryu@gmail.com> +Date: Tue, 1 Nov 2011 19:04:59 -0400 +Subject: [PATCH] jbd/jbd2: validate sb->s_first in journal_get_superblock() + +commit 8762202dd0d6e46854f786bdb6fb3780a1625efe upstream. + +I hit a J_ASSERT(blocknr != 0) failure in cleanup_journal_tail() when +mounting a fsfuzzed ext3 image. It turns out that the corrupted ext3 +image has s_first = 0 in journal superblock, and the 0 is passed to +journal->j_head in journal_reset(), then to blocknr in +cleanup_journal_tail(), in the end the J_ASSERT failed. + +So validate s_first after reading journal superblock from disk in +journal_get_superblock() to ensure s_first is valid. + +The following script could reproduce it: + +fstype=ext3 +blocksize=1024 +img=$fstype.img +offset=0 +found=0 +magic="c0 3b 39 98" + +dd if=/dev/zero of=$img bs=1M count=8 +mkfs -t $fstype -b $blocksize -F $img +filesize=`stat -c %s $img` +while [ $offset -lt $filesize ] +do + if od -j $offset -N 4 -t x1 $img | grep -i "$magic";then + echo "Found journal: $offset" + found=1 + break + fi + offset=`echo "$offset+$blocksize" | bc` +done + +if [ $found -ne 1 ];then + echo "Magic \"$magic\" not found" + exit 1 +fi + +dd if=/dev/zero of=$img seek=$(($offset+23)) conv=notrunc bs=1 count=1 + +mkdir -p ./mnt +mount -o loop $img ./mnt + +Cc: Jan Kara <jack@suse.cz> +Signed-off-by: Eryu Guan <guaneryu@gmail.com> +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + fs/jbd/journal.c | 8 ++++++++ + fs/jbd2/journal.c | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c +index 45905ff..70713d5 100644 +--- a/fs/jbd/journal.c ++++ b/fs/jbd/journal.c +@@ -1070,6 +1070,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c +index c03d4dc..7f16fea 100644 +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -1186,6 +1186,14 @@ static int journal_get_superblock(journal_t *journal) + goto out; + } + ++ if (be32_to_cpu(sb->s_first) == 0 || ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) { ++ printk(KERN_WARNING ++ "JBD2: Invalid start block of journal: %u\n", ++ be32_to_cpu(sb->s_first)); ++ goto out; ++ } ++ + return 0; + + out: +-- +1.7.12.1 + diff --git a/queue/linux-log2.h-Fix-rounddown_pow_of_two-1.patch b/queue/linux-log2.h-Fix-rounddown_pow_of_two-1.patch new file mode 100644 index 0000000..520d244 --- /dev/null +++ b/queue/linux-log2.h-Fix-rounddown_pow_of_two-1.patch @@ -0,0 +1,53 @@ +From ce3b5743aa8c1aab30cbc5a2f43a84a2aed733a0 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Mon, 12 Dec 2011 22:06:55 -0800 +Subject: [PATCH] linux/log2.h: Fix rounddown_pow_of_two(1) + +commit 13c07b0286d340275f2d97adf085cecda37ede37 upstream. + +Exactly like roundup_pow_of_two(1), the rounddown version was buggy for +the case of a compile-time constant '1' argument. Probably because it +originated from the same code, sharing history with the roundup version +from before the bugfix (for that one, see commit 1a06a52ee1b0: "Fix +roundup_pow_of_two(1)"). + +However, unlike the roundup version, the fix for rounddown is to just +remove the broken special case entirely. It's simply not needed - the +generic code + + 1UL << ilog2(n) + +does the right thing for the constant '1' argment too. The only reason +roundup needed that special case was because rounding up does so by +subtracting one from the argument (and then adding one to the result) +causing the obvious problems with "ilog2(0)". + +But rounddown doesn't do any of that, since ilog2() naturally truncates +(ie "rounds down") to the right rounded down value. And without the +ilog2(0) case, there's no reason for the special case that had the wrong +value. + +tl;dr: rounddown_pow_of_two(1) should be 1, not 0. + +Acked-by: Dmitry Torokhov <dtor@vmware.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + include/linux/log2.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/include/linux/log2.h b/include/linux/log2.h +index 25b8086..fd7ff3d 100644 +--- a/include/linux/log2.h ++++ b/include/linux/log2.h +@@ -185,7 +185,6 @@ unsigned long __rounddown_pow_of_two(unsigned long n) + #define rounddown_pow_of_two(n) \ + ( \ + __builtin_constant_p(n) ? ( \ +- (n == 1) ? 0 : \ + (1UL << ilog2(n))) : \ + __rounddown_pow_of_two(n) \ + ) +-- +1.7.12.1 + diff --git a/queue/oprofile-Fix-locking-dependency-in-sync_start.patch b/queue/oprofile-Fix-locking-dependency-in-sync_start.patch new file mode 100644 index 0000000..76ea8e7 --- /dev/null +++ b/queue/oprofile-Fix-locking-dependency-in-sync_start.patch @@ -0,0 +1,156 @@ +From 89d1b6681355f59ec68e5e9fdff56baf9fbda2df Mon Sep 17 00:00:00 2001 +From: Robert Richter <robert.richter@amd.com> +Date: Thu, 26 May 2011 18:39:35 +0200 +Subject: [PATCH] oprofile: Fix locking dependency in sync_start() + +commit 130c5ce716c9bfd1c2a2ec840a746eb7ff9ce1e6 upstream. + +This fixes the A->B/B->A locking dependency, see the warning below. + +The function task_exit_notify() is called with (task_exit_notifier) +.rwsem set and then calls sync_buffer() which locks buffer_mutex. In +sync_start() the buffer_mutex was set to prevent notifier functions to +be started before sync_start() is finished. But when registering the +notifier, (task_exit_notifier).rwsem is locked too, but now in +different order than in sync_buffer(). In theory this causes a locking +dependency, what does not occur in practice since task_exit_notify() +is always called after the notifier is registered which means the lock +is already released. + +However, after checking the notifier functions it turned out the +buffer_mutex in sync_start() is unnecessary. This is because +sync_buffer() may be called from the notifiers even if sync_start() +did not finish yet, the buffers are already allocated but empty. No +need to protect this with the mutex. + +So we fix this theoretical locking dependency by removing buffer_mutex +in sync_start(). This is similar to the implementation before commit: + + 750d857 oprofile: fix crash when accessing freed task structs + +which introduced the locking dependency. + +Lockdep warning: + +oprofiled/4447 is trying to acquire lock: + (buffer_mutex){+.+...}, at: [<ffffffffa0000e55>] sync_buffer+0x31/0x3ec [oprofile] + +but task is already holding lock: + ((task_exit_notifier).rwsem){++++..}, at: [<ffffffff81058026>] __blocking_notifier_call_chain+0x39/0x67 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +-> #1 ((task_exit_notifier).rwsem){++++..}: + [<ffffffff8106557f>] lock_acquire+0xf8/0x11e + [<ffffffff81463a2b>] down_write+0x44/0x67 + [<ffffffff810581c0>] blocking_notifier_chain_register+0x52/0x8b + [<ffffffff8105a6ac>] profile_event_register+0x2d/0x2f + [<ffffffffa00013c1>] sync_start+0x47/0xc6 [oprofile] + [<ffffffffa00001bb>] oprofile_setup+0x60/0xa5 [oprofile] + [<ffffffffa00014e3>] event_buffer_open+0x59/0x8c [oprofile] + [<ffffffff810cd3b9>] __dentry_open+0x1eb/0x308 + [<ffffffff810cd59d>] nameidata_to_filp+0x60/0x67 + [<ffffffff810daad6>] do_last+0x5be/0x6b2 + [<ffffffff810dbc33>] path_openat+0xc7/0x360 + [<ffffffff810dbfc5>] do_filp_open+0x3d/0x8c + [<ffffffff810ccfd2>] do_sys_open+0x110/0x1a9 + [<ffffffff810cd09e>] sys_open+0x20/0x22 + [<ffffffff8146ad4b>] system_call_fastpath+0x16/0x1b + +-> #0 (buffer_mutex){+.+...}: + [<ffffffff81064dfb>] __lock_acquire+0x1085/0x1711 + [<ffffffff8106557f>] lock_acquire+0xf8/0x11e + [<ffffffff814634f0>] mutex_lock_nested+0x63/0x309 + [<ffffffffa0000e55>] sync_buffer+0x31/0x3ec [oprofile] + [<ffffffffa0001226>] task_exit_notify+0x16/0x1a [oprofile] + [<ffffffff81467b96>] notifier_call_chain+0x37/0x63 + [<ffffffff8105803d>] __blocking_notifier_call_chain+0x50/0x67 + [<ffffffff81058068>] blocking_notifier_call_chain+0x14/0x16 + [<ffffffff8105a718>] profile_task_exit+0x1a/0x1c + [<ffffffff81039e8f>] do_exit+0x2a/0x6fc + [<ffffffff8103a5e4>] do_group_exit+0x83/0xae + [<ffffffff8103a626>] sys_exit_group+0x17/0x1b + [<ffffffff8146ad4b>] system_call_fastpath+0x16/0x1b + +other info that might help us debug this: + +1 lock held by oprofiled/4447: + #0: ((task_exit_notifier).rwsem){++++..}, at: [<ffffffff81058026>] __blocking_notifier_call_chain+0x39/0x67 + +stack backtrace: +Pid: 4447, comm: oprofiled Not tainted 2.6.39-00007-gcf4d8d4 #10 +Call Trace: + [<ffffffff81063193>] print_circular_bug+0xae/0xbc + [<ffffffff81064dfb>] __lock_acquire+0x1085/0x1711 + [<ffffffffa0000e55>] ? sync_buffer+0x31/0x3ec [oprofile] + [<ffffffff8106557f>] lock_acquire+0xf8/0x11e + [<ffffffffa0000e55>] ? sync_buffer+0x31/0x3ec [oprofile] + [<ffffffff81062627>] ? mark_lock+0x42f/0x552 + [<ffffffffa0000e55>] ? sync_buffer+0x31/0x3ec [oprofile] + [<ffffffff814634f0>] mutex_lock_nested+0x63/0x309 + [<ffffffffa0000e55>] ? sync_buffer+0x31/0x3ec [oprofile] + [<ffffffffa0000e55>] sync_buffer+0x31/0x3ec [oprofile] + [<ffffffff81058026>] ? __blocking_notifier_call_chain+0x39/0x67 + [<ffffffff81058026>] ? __blocking_notifier_call_chain+0x39/0x67 + [<ffffffffa0001226>] task_exit_notify+0x16/0x1a [oprofile] + [<ffffffff81467b96>] notifier_call_chain+0x37/0x63 + [<ffffffff8105803d>] __blocking_notifier_call_chain+0x50/0x67 + [<ffffffff81058068>] blocking_notifier_call_chain+0x14/0x16 + [<ffffffff8105a718>] profile_task_exit+0x1a/0x1c + [<ffffffff81039e8f>] do_exit+0x2a/0x6fc + [<ffffffff81465031>] ? retint_swapgs+0xe/0x13 + [<ffffffff8103a5e4>] do_group_exit+0x83/0xae + [<ffffffff8103a626>] sys_exit_group+0x17/0x1b + [<ffffffff8146ad4b>] system_call_fastpath+0x16/0x1b + +Reported-by: Marcin Slusarz <marcin.slusarz@gmail.com> +Cc: Carl Love <carll@us.ibm.com> +Signed-off-by: Robert Richter <robert.richter@amd.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/oprofile/buffer_sync.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c +index e353ebf..5830bdc 100644 +--- a/drivers/oprofile/buffer_sync.c ++++ b/drivers/oprofile/buffer_sync.c +@@ -155,8 +155,6 @@ int sync_start(void) + if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) + return -ENOMEM; + +- mutex_lock(&buffer_mutex); +- + err = task_handoff_register(&task_free_nb); + if (err) + goto out1; +@@ -173,7 +171,6 @@ int sync_start(void) + start_cpu_work(); + + out: +- mutex_unlock(&buffer_mutex); + return err; + out4: + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); +@@ -190,14 +187,13 @@ out1: + + void sync_stop(void) + { +- /* flush buffers */ +- mutex_lock(&buffer_mutex); + end_cpu_work(); + unregister_module_notifier(&module_load_nb); + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); + task_handoff_unregister(&task_free_nb); +- mutex_unlock(&buffer_mutex); ++ barrier(); /* do all of the above first */ ++ + flush_scheduled_work(); + + free_all_tasks(); +-- +1.7.12.1 + diff --git a/queue/oprofile-Free-potentially-owned-tasks-in-case-of-err.patch b/queue/oprofile-Free-potentially-owned-tasks-in-case-of-err.patch new file mode 100644 index 0000000..4a1307d --- /dev/null +++ b/queue/oprofile-Free-potentially-owned-tasks-in-case-of-err.patch @@ -0,0 +1,58 @@ +From 104f981d2b6d817a7f782a69fb70c72ddbbd4d12 Mon Sep 17 00:00:00 2001 +From: Robert Richter <robert.richter@amd.com> +Date: Thu, 26 May 2011 18:22:54 +0200 +Subject: [PATCH] oprofile: Free potentially owned tasks in case of errors + +commit 6ac6519b93065625119a347be1cbcc1b89edb773 upstream. + +After registering the task free notifier we possibly have tasks in our +dying_tasks list. Free them after unregistering the notifier in case +of an error. + +Signed-off-by: Robert Richter <robert.richter@amd.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/oprofile/buffer_sync.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c +index b7e755f..e353ebf 100644 +--- a/drivers/oprofile/buffer_sync.c ++++ b/drivers/oprofile/buffer_sync.c +@@ -141,6 +141,13 @@ static struct notifier_block module_load_nb = { + .notifier_call = module_load_notify, + }; + ++static void free_all_tasks(void) ++{ ++ /* make sure we don't leak task structs */ ++ process_task_mortuary(); ++ process_task_mortuary(); ++} ++ + int sync_start(void) + { + int err; +@@ -174,6 +181,7 @@ out3: + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); + out2: + task_handoff_unregister(&task_free_nb); ++ free_all_tasks(); + out1: + free_cpumask_var(marked_cpus); + goto out; +@@ -192,10 +200,7 @@ void sync_stop(void) + mutex_unlock(&buffer_mutex); + flush_scheduled_work(); + +- /* make sure we don't leak task structs */ +- process_task_mortuary(); +- process_task_mortuary(); +- ++ free_all_tasks(); + free_cpumask_var(marked_cpus); + } + +-- +1.7.12.1 + diff --git a/queue/oprofile-x86-Fix-nmi-unsafe-callgraph-support.patch b/queue/oprofile-x86-Fix-nmi-unsafe-callgraph-support.patch new file mode 100644 index 0000000..8ce76a1 --- /dev/null +++ b/queue/oprofile-x86-Fix-nmi-unsafe-callgraph-support.patch @@ -0,0 +1,150 @@ +From 0e5cd4ee1da7754ea1c8814f701393976ed62201 Mon Sep 17 00:00:00 2001 +From: Robert Richter <robert.richter@amd.com> +Date: Tue, 13 Dec 2011 00:40:35 +0100 +Subject: [PATCH] oprofile, x86: Fix nmi-unsafe callgraph support + +commit a0e3e70243f5b270bc3eca718f0a9fa5e6b8262e upstream. + +Backport for stable kernel v2.6.32.y to v2.6.36.y. + +Current oprofile's x86 callgraph support may trigger page faults +throwing the BUG_ON(in_nmi()) message below. This patch fixes this by +using the same nmi-safe copy-from-user code as in perf. + +------------[ cut here ]------------ +kernel BUG at .../arch/x86/kernel/traps.c:436! +invalid opcode: 0000 [#1] SMP +last sysfs file: /sys/devices/pci0000:00/0000:00:0a.0/0000:07:00.0/0000:08:04.0/net/eth0/broadcast +CPU 5 +Modules linked in: + +Pid: 8611, comm: opcontrol Not tainted 2.6.39-00007-gfe47ae7 #1 Advanced Micro Device Anaheim/Anaheim +RIP: 0010:[<ffffffff813e8e35>] [<ffffffff813e8e35>] do_nmi+0x22/0x1ee +RSP: 0000:ffff88042fd47f28 EFLAGS: 00010002 +RAX: ffff88042c0a7fd8 RBX: 0000000000000001 RCX: 00000000c0000101 +RDX: 00000000ffff8804 RSI: ffffffffffffffff RDI: ffff88042fd47f58 +RBP: ffff88042fd47f48 R08: 0000000000000004 R09: 0000000000001484 +R10: 0000000000000001 R11: 0000000000000000 R12: ffff88042fd47f58 +R13: 0000000000000000 R14: ffff88042fd47d98 R15: 0000000000000020 +FS: 00007fca25e56700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000074 CR3: 000000042d28b000 CR4: 00000000000006e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +Process opcontrol (pid: 8611, threadinfo ffff88042c0a6000, task ffff88042c532310) +Stack: + 0000000000000000 0000000000000001 ffff88042c0a7fd8 0000000000000000 + ffff88042fd47de8 ffffffff813e897a 0000000000000020 ffff88042fd47d98 + 0000000000000000 ffff88042c0a7fd8 ffff88042fd47de8 0000000000000074 +Call Trace: + <NMI> + [<ffffffff813e897a>] nmi+0x1a/0x20 + [<ffffffff813f08ab>] ? bad_to_user+0x25/0x771 + <<EOE>> +Code: ff 59 5b 41 5c 41 5d c9 c3 55 65 48 8b 04 25 88 b5 00 00 48 89 e5 41 55 41 54 49 89 fc 53 48 83 ec 08 f6 80 47 e0 ff ff 04 74 04 <0f> 0b eb fe 81 80 44 e0 ff ff 00 00 01 04 65 ff 04 25 c4 0f 01 +RIP [<ffffffff813e8e35>] do_nmi+0x22/0x1ee + RSP <ffff88042fd47f28> +---[ end trace ed6752185092104b ]--- +Kernel panic - not syncing: Fatal exception in interrupt +Pid: 8611, comm: opcontrol Tainted: G D 2.6.39-00007-gfe47ae7 #1 +Call Trace: + <NMI> [<ffffffff813e5e0a>] panic+0x8c/0x188 + [<ffffffff813e915c>] oops_end+0x81/0x8e + [<ffffffff8100403d>] die+0x55/0x5e + [<ffffffff813e8c45>] do_trap+0x11c/0x12b + [<ffffffff810023c8>] do_invalid_op+0x91/0x9a + [<ffffffff813e8e35>] ? do_nmi+0x22/0x1ee + [<ffffffff8131e6fa>] ? oprofile_add_sample+0x83/0x95 + [<ffffffff81321670>] ? op_amd_check_ctrs+0x4f/0x2cf + [<ffffffff813ee4d5>] invalid_op+0x15/0x20 + [<ffffffff813e8e35>] ? do_nmi+0x22/0x1ee + [<ffffffff813e8e7a>] ? do_nmi+0x67/0x1ee + [<ffffffff813e897a>] nmi+0x1a/0x20 + [<ffffffff813f08ab>] ? bad_to_user+0x25/0x771 + <<EOE>> + +Cc: John Lumby <johnlumby@hotmail.com> +Cc: Maynard Johnson <maynardj@us.ibm.com> +Signed-off-by: Robert Richter <robert.richter@amd.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + arch/x86/oprofile/backtrace.c | 46 +++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 42 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c +index 3855096..9859781 100644 +--- a/arch/x86/oprofile/backtrace.c ++++ b/arch/x86/oprofile/backtrace.c +@@ -11,6 +11,8 @@ + #include <linux/oprofile.h> + #include <linux/sched.h> + #include <linux/mm.h> ++#include <linux/highmem.h> ++ + #include <asm/ptrace.h> + #include <asm/uaccess.h> + #include <asm/stacktrace.h> +@@ -48,6 +50,42 @@ static struct stacktrace_ops backtrace_ops = { + .walk_stack = print_context_stack, + }; + ++/* from arch/x86/kernel/cpu/perf_event.c: */ ++ ++/* ++ * best effort, GUP based copy_from_user() that assumes IRQ or NMI context ++ */ ++static unsigned long ++copy_from_user_nmi(void *to, const void __user *from, unsigned long n) ++{ ++ unsigned long offset, addr = (unsigned long)from; ++ unsigned long size, len = 0; ++ struct page *page; ++ void *map; ++ int ret; ++ ++ do { ++ ret = __get_user_pages_fast(addr, 1, 0, &page); ++ if (!ret) ++ break; ++ ++ offset = addr & (PAGE_SIZE - 1); ++ size = min(PAGE_SIZE - offset, n - len); ++ ++ map = kmap_atomic(page, KM_USER0); ++ memcpy(to, map+offset, size); ++ kunmap_atomic(map, KM_USER0); ++ put_page(page); ++ ++ len += size; ++ to += size; ++ addr += size; ++ ++ } while (len < n); ++ ++ return len; ++} ++ + struct frame_head { + struct frame_head *bp; + unsigned long ret; +@@ -55,12 +93,12 @@ struct frame_head { + + static struct frame_head *dump_user_backtrace(struct frame_head *head) + { ++ /* Also check accessibility of one struct frame_head beyond: */ + struct frame_head bufhead[2]; ++ unsigned long bytes; + +- /* Also check accessibility of one struct frame_head beyond */ +- if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) +- return NULL; +- if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) ++ bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); ++ if (bytes != sizeof(bufhead)) + return NULL; + + oprofile_add_trace(bufhead[0].ret); +-- +1.7.12.1 + diff --git a/queue/percpu-fix-chunk-range-calculation.patch b/queue/percpu-fix-chunk-range-calculation.patch new file mode 100644 index 0000000..cd09ad9 --- /dev/null +++ b/queue/percpu-fix-chunk-range-calculation.patch @@ -0,0 +1,147 @@ +From b0216631bd053d0fb49cab1989fac9e282957f88 Mon Sep 17 00:00:00 2001 +From: Tejun Heo <tj@kernel.org> +Date: Fri, 18 Nov 2011 10:55:35 -0800 +Subject: [PATCH] percpu: fix chunk range calculation + +commit a855b84c3d8c73220d4d3cd392a7bee7c83de70e upstream. + +Percpu allocator recorded the cpus which map to the first and last +units in pcpu_first/last_unit_cpu respectively and used them to +determine the address range of a chunk - e.g. it assumed that the +first unit has the lowest address in a chunk while the last unit has +the highest address. + +This simply isn't true. Groups in a chunk can have arbitrary positive +or negative offsets from the previous one and there is no guarantee +that the first unit occupies the lowest offset while the last one the +highest. + +Fix it by actually comparing unit offsets to determine cpus occupying +the lowest and highest offsets. Also, rename pcu_first/last_unit_cpu +to pcpu_low/high_unit_cpu to avoid confusion. + +The chunk address range is used to flush cache on vmalloc area +map/unmap and decide whether a given address is in the first chunk by +per_cpu_ptr_to_phys() and the bug was discovered by invalid +per_cpu_ptr_to_phys() translation for crash_note. + +Kudos to Dave Young for tracking down the problem. + +Signed-off-by: Tejun Heo <tj@kernel.org> +Reported-by: WANG Cong <xiyou.wangcong@gmail.com> +Reported-by: Dave Young <dyoung@redhat.com> +Tested-by: Dave Young <dyoung@redhat.com> +LKML-Reference: <4EC21F67.10905@redhat.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/percpu.c | 46 ++++++++++++++++++++++++++-------------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/mm/percpu.c b/mm/percpu.c +index 4e91b81..acd94cb 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -111,9 +111,9 @@ static int pcpu_atom_size __read_mostly; + static int pcpu_nr_slots __read_mostly; + static size_t pcpu_chunk_struct_size __read_mostly; + +-/* cpus with the lowest and highest unit numbers */ +-static unsigned int pcpu_first_unit_cpu __read_mostly; +-static unsigned int pcpu_last_unit_cpu __read_mostly; ++/* cpus with the lowest and highest unit addresses */ ++static unsigned int pcpu_low_unit_cpu __read_mostly; ++static unsigned int pcpu_high_unit_cpu __read_mostly; + + /* the address of the first chunk which starts with the kernel static area */ + void *pcpu_base_addr __read_mostly; +@@ -747,8 +747,8 @@ static void pcpu_pre_unmap_flush(struct pcpu_chunk *chunk, + int page_start, int page_end) + { + flush_cache_vunmap( +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); + } + + static void __pcpu_unmap_pages(unsigned long addr, int nr_pages) +@@ -810,8 +810,8 @@ static void pcpu_post_unmap_tlb_flush(struct pcpu_chunk *chunk, + int page_start, int page_end) + { + flush_tlb_kernel_range( +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); + } + + static int __pcpu_map_pages(unsigned long addr, struct page **pages, +@@ -888,8 +888,8 @@ static void pcpu_post_map_flush(struct pcpu_chunk *chunk, + int page_start, int page_end) + { + flush_cache_vmap( +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start), +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end)); ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start), ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end)); + } + + /** +@@ -1345,19 +1345,19 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr) + { + void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); + bool in_first_chunk = false; +- unsigned long first_start, first_end; ++ unsigned long first_low, first_high; + unsigned int cpu; + + /* +- * The following test on first_start/end isn't strictly ++ * The following test on unit_low/high isn't strictly + * necessary but will speed up lookups of addresses which + * aren't in the first chunk. + */ +- first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); +- first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, +- pcpu_unit_pages); +- if ((unsigned long)addr >= first_start && +- (unsigned long)addr < first_end) { ++ first_low = pcpu_chunk_addr(pcpu_first_chunk, pcpu_low_unit_cpu, 0); ++ first_high = pcpu_chunk_addr(pcpu_first_chunk, pcpu_high_unit_cpu, ++ pcpu_unit_pages); ++ if ((unsigned long)addr >= first_low && ++ (unsigned long)addr < first_high) { + for_each_possible_cpu(cpu) { + void *start = per_cpu_ptr(base, cpu); + +@@ -1754,7 +1754,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + + for (cpu = 0; cpu < nr_cpu_ids; cpu++) + unit_map[cpu] = UINT_MAX; +- pcpu_first_unit_cpu = NR_CPUS; ++ ++ pcpu_low_unit_cpu = NR_CPUS; ++ pcpu_high_unit_cpu = NR_CPUS; + + for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) { + const struct pcpu_group_info *gi = &ai->groups[group]; +@@ -1774,9 +1776,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, + unit_map[cpu] = unit + i; + unit_off[cpu] = gi->base_offset + i * ai->unit_size; + +- if (pcpu_first_unit_cpu == NR_CPUS) +- pcpu_first_unit_cpu = cpu; +- pcpu_last_unit_cpu = cpu; ++ /* determine low/high unit_cpu */ ++ if (pcpu_low_unit_cpu == NR_CPUS || ++ unit_off[cpu] < unit_off[pcpu_low_unit_cpu]) ++ pcpu_low_unit_cpu = cpu; ++ if (pcpu_high_unit_cpu == NR_CPUS || ++ unit_off[cpu] > unit_off[pcpu_high_unit_cpu]) ++ pcpu_high_unit_cpu = cpu; + } + } + pcpu_nr_units = unit; +-- +1.7.12.1 + diff --git a/queue/percpu-fix-first-chunk-match-in-per_cpu_ptr_to_phys.patch b/queue/percpu-fix-first-chunk-match-in-per_cpu_ptr_to_phys.patch new file mode 100644 index 0000000..4b81855 --- /dev/null +++ b/queue/percpu-fix-first-chunk-match-in-per_cpu_ptr_to_phys.patch @@ -0,0 +1,72 @@ +From dabf4ac8a53988bd6bc3aaa1070fb52f719a10b2 Mon Sep 17 00:00:00 2001 +From: Tejun Heo <tj@kernel.org> +Date: Fri, 18 Jun 2010 11:44:31 +0200 +Subject: [PATCH] percpu: fix first chunk match in per_cpu_ptr_to_phys() + +commit 9983b6f0cf8263e51bcf4c8a9dc0c1ef175b3c60 upstream. + +per_cpu_ptr_to_phys() determines whether the passed in @addr belongs +to the first_chunk or not by just matching the address against the +address range of the base unit (unit0, used by cpu0). When an adress +from another cpu was passed in, it will always determine that the +address doesn't belong to the first chunk even when it does. This +makes the function return a bogus physical address which may lead to +crash. + +This problem was discovered by Cliff Wickman while investigating a +crash during kdump on a SGI UV system. + +Signed-off-by: Tejun Heo <tj@kernel.org> +Reported-by: Cliff Wickman <cpw@sgi.com> +Tested-by: Cliff Wickman <cpw@sgi.com> +[PG: for 2.6.34, diffstat differs slightly due to a trivial indenting + difference, and 34 does not have the _maybe_unused annotation to delete] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/percpu.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +diff --git a/mm/percpu.c b/mm/percpu.c +index 717cc6e..4e91b81 100644 +--- a/mm/percpu.c ++++ b/mm/percpu.c +@@ -1343,8 +1343,34 @@ bool is_kernel_percpu_address(unsigned long addr) + */ + phys_addr_t per_cpu_ptr_to_phys(void *addr) + { +- if ((unsigned long)addr < VMALLOC_START || +- (unsigned long)addr >= VMALLOC_END) ++ void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr); ++ bool in_first_chunk = false; ++ unsigned long first_start, first_end; ++ unsigned int cpu; ++ ++ /* ++ * The following test on first_start/end isn't strictly ++ * necessary but will speed up lookups of addresses which ++ * aren't in the first chunk. ++ */ ++ first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0); ++ first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu, ++ pcpu_unit_pages); ++ if ((unsigned long)addr >= first_start && ++ (unsigned long)addr < first_end) { ++ for_each_possible_cpu(cpu) { ++ void *start = per_cpu_ptr(base, cpu); ++ ++ if (addr >= start && addr < start + pcpu_unit_size) { ++ in_first_chunk = true; ++ break; ++ } ++ } ++ } ++ ++ if (in_first_chunk) { ++ if ((unsigned long)addr < VMALLOC_START || ++ (unsigned long)addr >= VMALLOC_END) + return __pa(addr); + else + return page_to_phys(vmalloc_to_page(addr)); +-- +1.7.12.1 + diff --git a/queue/series b/queue/series index ef4a10c..587c099 100644 --- a/queue/series +++ b/queue/series @@ -38,3 +38,21 @@ oprofile-x86-Fix-crash-when-unloading-module-nmi-tim.patch genirq-Fix-race-condition-when-stopping-the-irq-thre.patch tick-broadcast-Stop-active-broadcast-device-when-rep.patch clockevents-Set-noop-handler-in-clockevents_exchange.patch + +# from .51 +ALSA-sis7019-give-slow-codecs-more-time-to-reset.patch +ALSA-hda-realtek-Fix-Oops-in-alc_mux_select.patch +ARM-davinci-dm646x-evm-wrong-register-used-in-setup_.patch +oprofile-Free-potentially-owned-tasks-in-case-of-err.patch +oprofile-Fix-locking-dependency-in-sync_start.patch +percpu-fix-first-chunk-match-in-per_cpu_ptr_to_phys.patch +percpu-fix-chunk-range-calculation.patch +xfrm-Fix-key-lengths-for-rfc3686-ctr-aes.patch +linux-log2.h-Fix-rounddown_pow_of_two-1.patch +jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch +Make-TASKSTATS-require-root-access.patch +hfs-fix-hfs_find_init-sb-ext_tree-NULL-ptr-oops.patch +export-__get_user_pages_fast-function.patch +oprofile-x86-Fix-nmi-unsafe-callgraph-support.patch +ext4-avoid-hangs-in-ext4_da_should_update_i_disksize.patch +USB-cdc-acm-add-IDs-for-Motorola-H24-HSPA-USB-module.patch diff --git a/queue/xfrm-Fix-key-lengths-for-rfc3686-ctr-aes.patch b/queue/xfrm-Fix-key-lengths-for-rfc3686-ctr-aes.patch new file mode 100644 index 0000000..030e1c0 --- /dev/null +++ b/queue/xfrm-Fix-key-lengths-for-rfc3686-ctr-aes.patch @@ -0,0 +1,40 @@ +From e90c7fcef1a4db836c445863c8e94e2bfe69d763 Mon Sep 17 00:00:00 2001 +From: Tushar Gohad <tgohad@mvista.com> +Date: Thu, 28 Jul 2011 10:36:20 +0000 +Subject: [PATCH] xfrm: Fix key lengths for rfc3686(ctr(aes)) + +commit 4203223a1aed862b4445fdcd260d6139603a51d9 upstream. + +Fix the min and max bit lengths for AES-CTR (RFC3686) keys. +The number of bits in key spec is the key length (128/256) +plus 32 bits of nonce. + +This change takes care of the "Invalid key length" errors +reported by setkey when specifying 288 bit keys for aes-ctr. + +Signed-off-by: Tushar Gohad <tgohad@mvista.com> +Acked-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + net/xfrm/xfrm_algo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c +index 8b4d6e3..2437ef2 100644 +--- a/net/xfrm/xfrm_algo.c ++++ b/net/xfrm/xfrm_algo.c +@@ -462,8 +462,8 @@ static struct xfrm_algo_desc ealg_list[] = { + .desc = { + .sadb_alg_id = SADB_X_EALG_AESCTR, + .sadb_alg_ivlen = 8, +- .sadb_alg_minbits = 128, +- .sadb_alg_maxbits = 256 ++ .sadb_alg_minbits = 160, ++ .sadb_alg_maxbits = 288 + } + }, + }; +-- +1.7.12.1 + |