From: Greg Kroah-Hartman Date: Sun, 8 Dec 2013 20:02:14 +0000 (-0800) Subject: 3.12-stable patches X-Git-Tag: v3.4.74~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4d81038aa7e642d869842235f1e77fe27abd6b7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.12-stable patches added patches: asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch asoc-wm8731-fix-dsp-mode-configuration.patch asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch efi-pstore-make-efi-pstore-return-a-unique-id.patch efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch --- diff --git a/queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch b/queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch new file mode 100644 index 00000000000..eb415891677 --- /dev/null +++ b/queue-3.12/asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch @@ -0,0 +1,39 @@ +From faf6615bf05bc5cecc6e22013b9cb21c77784fd1 Mon Sep 17 00:00:00 2001 +From: Stephen Warren +Date: Fri, 22 Nov 2013 10:29:18 -0700 +Subject: ASoC: dapm: Use SND_SOC_DAPM_INIT_REG_VAL in SND_SOC_DAPM_MUX + +From: Stephen Warren + +commit faf6615bf05bc5cecc6e22013b9cb21c77784fd1 upstream. + +SND_SOC_DAPM_MUX() doesn't currently initialize the .mask field. This +results in the mux never affecting HW, since no bits are ever set or +cleared. Fix SND_SOC_DAPM_MUX() to use SND_SOC_DAPM_INIT_REG_VAL() to +set up the reg, shift, on_val, and off_val fields like almost all other +SND_SOC_xxx() macros. It looks like this was a "typo" in the fixed +commit linked below. + +This makes the speakers on the Toshiba AC100 (PAZ00) laptop work again. + +Fixes: de9ba98b6d26 ("ASoC: dapm: Make widget power register settings more flexible") +Signed-off-by: Stephen Warren +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + include/sound/soc-dapm.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/include/sound/soc-dapm.h ++++ b/include/sound/soc-dapm.h +@@ -104,7 +104,8 @@ struct device; + SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ + .kcontrol_news = wcontrols, .num_kcontrols = 1} + #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ +-{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \ ++{ .id = snd_soc_dapm_mux, .name = wname, \ ++ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ + .kcontrol_news = wcontrols, .num_kcontrols = 1} + #define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \ + { .id = snd_soc_dapm_virt_mux, .name = wname, \ diff --git a/queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch b/queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch new file mode 100644 index 00000000000..d6b3117e419 --- /dev/null +++ b/queue-3.12/asoc-wm8731-fix-dsp-mode-configuration.patch @@ -0,0 +1,37 @@ +From b4af6ef99a60c5b56df137d7accd81ba1ee1254e Mon Sep 17 00:00:00 2001 +From: Bo Shen +Date: Tue, 3 Dec 2013 18:04:54 +0800 +Subject: ASoC: wm8731: fix dsp mode configuration + +From: Bo Shen + +commit b4af6ef99a60c5b56df137d7accd81ba1ee1254e upstream. + +According to WM8731 "PD, Rev 4.9 October 2012" datasheet, when it +works in DSP mode A, LRP = 1, while works in DSP mode B, LRP = 0. +So, fix LRP for DSP mode as the datesheet specification. + +Signed-off-by: Bo Shen +Acked-by: Charles Keepax +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8731.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -447,10 +447,10 @@ static int wm8731_set_dai_fmt(struct snd + iface |= 0x0001; + break; + case SND_SOC_DAIFMT_DSP_A: +- iface |= 0x0003; ++ iface |= 0x0013; + break; + case SND_SOC_DAIFMT_DSP_B: +- iface |= 0x0013; ++ iface |= 0x0003; + break; + default: + return -EINVAL; diff --git a/queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch b/queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch new file mode 100644 index 00000000000..7db220e2465 --- /dev/null +++ b/queue-3.12/asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch @@ -0,0 +1,30 @@ +From 2ab2b74277a86afe0dd92976db695a2bb8b93366 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 22 Nov 2013 14:17:18 +0000 +Subject: ASoC: wm8990: Mark the register map as dirty when powering down + +From: Mark Brown + +commit 2ab2b74277a86afe0dd92976db695a2bb8b93366 upstream. + +Otherwise we'll skip sync on resume. + +Signed-off-by: Mark Brown +Acked-by: Charles Keepax +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8990.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/soc/codecs/wm8990.c ++++ b/sound/soc/codecs/wm8990.c +@@ -1259,6 +1259,8 @@ static int wm8990_set_bias_level(struct + + /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ + snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); ++ ++ codec->cache_sync = 1; + break; + } + diff --git a/queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch b/queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch new file mode 100644 index 00000000000..20a7866d089 --- /dev/null +++ b/queue-3.12/can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch @@ -0,0 +1,74 @@ +From e35d46adc49b469fd92bdb64fea8af93640e6651 Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Sun, 24 Nov 2013 23:31:24 +0100 +Subject: can: c_can: don't call pm_runtime_get_sync() from interrupt context + +From: Marc Kleine-Budde + +commit e35d46adc49b469fd92bdb64fea8af93640e6651 upstream. + +The c_can driver contians a callpath (c_can_poll -> c_can_state_change -> +c_can_get_berr_counter) which may call pm_runtime_get_sync() from the IRQ +handler, which is not allowed and results in "BUG: scheduling while atomic". + +This problem is fixed by introducing __c_can_get_berr_counter, which will not +call pm_runtime_get_sync(). + +Reported-by: Andrew Glen +Tested-by: Andrew Glen +Signed-off-by: Andrew Glen +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/can/c_can/c_can.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/net/can/c_can/c_can.c ++++ b/drivers/net/can/c_can/c_can.c +@@ -712,22 +712,31 @@ static int c_can_set_mode(struct net_dev + return 0; + } + +-static int c_can_get_berr_counter(const struct net_device *dev, +- struct can_berr_counter *bec) ++static int __c_can_get_berr_counter(const struct net_device *dev, ++ struct can_berr_counter *bec) + { + unsigned int reg_err_counter; + struct c_can_priv *priv = netdev_priv(dev); + +- c_can_pm_runtime_get_sync(priv); +- + reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); + bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> + ERR_CNT_REC_SHIFT; + bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; + ++ return 0; ++} ++ ++static int c_can_get_berr_counter(const struct net_device *dev, ++ struct can_berr_counter *bec) ++{ ++ struct c_can_priv *priv = netdev_priv(dev); ++ int err; ++ ++ c_can_pm_runtime_get_sync(priv); ++ err = __c_can_get_berr_counter(dev, bec); + c_can_pm_runtime_put_sync(priv); + +- return 0; ++ return err; + } + + /* +@@ -872,7 +881,7 @@ static int c_can_handle_state_change(str + if (unlikely(!skb)) + return 0; + +- c_can_get_berr_counter(dev, &bec); ++ __c_can_get_berr_counter(dev, &bec); + reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); + rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >> + ERR_CNT_RP_SHIFT; diff --git a/queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch b/queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch new file mode 100644 index 00000000000..7c638e55945 --- /dev/null +++ b/queue-3.12/can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch @@ -0,0 +1,40 @@ +From 1a3e5173f5e72cbf7f0c8927b33082e361c16d72 Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Mon, 25 Nov 2013 22:15:20 +0100 +Subject: can: flexcan: use correct clock as base for bit rate calculation + +From: Marc Kleine-Budde + +commit 1a3e5173f5e72cbf7f0c8927b33082e361c16d72 upstream. + +The flexcan IP core uses the peripheral clock ("per") as basic clock for the +bit timing calculation. However the driver uses the the wrong clock ("ipg"). +This leads to wrong bit rates if the rates on both clock are different. + +This patch fixes the problem by using the correct clock for the bit rate +calculation. + +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/can/flexcan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/can/flexcan.c ++++ b/drivers/net/can/flexcan.c +@@ -1020,13 +1020,13 @@ static int flexcan_probe(struct platform + dev_err(&pdev->dev, "no ipg clock defined\n"); + return PTR_ERR(clk_ipg); + } +- clock_freq = clk_get_rate(clk_ipg); + + clk_per = devm_clk_get(&pdev->dev, "per"); + if (IS_ERR(clk_per)) { + dev_err(&pdev->dev, "no per clock defined\n"); + return PTR_ERR(clk_per); + } ++ clock_freq = clk_get_rate(clk_per); + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch b/queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch new file mode 100644 index 00000000000..fd23f063044 --- /dev/null +++ b/queue-3.12/can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch @@ -0,0 +1,74 @@ +From 2fea6cd303c0d0cd9067da31d873b6a6d5bd75e7 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp +Date: Thu, 21 Nov 2013 18:03:07 +0100 +Subject: can: sja1000: fix {pre,post}_irq() handling and IRQ handler return value + +From: Oliver Hartkopp + +commit 2fea6cd303c0d0cd9067da31d873b6a6d5bd75e7 upstream. + +This patch fixes the issue that the sja1000_interrupt() function may have +returned IRQ_NONE without processing the optional pre_irq() and post_irq() +function before. Further the irq processing counter 'n' is moved to the end of +the while statement to return correct IRQ_[NONE|HANDLED] values at error +conditions. + +Reported-by: Wolfgang Grandegger +Acked-by: Wolfgang Grandegger +Signed-off-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/can/sja1000/sja1000.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/net/can/sja1000/sja1000.c ++++ b/drivers/net/can/sja1000/sja1000.c +@@ -494,20 +494,20 @@ irqreturn_t sja1000_interrupt(int irq, v + uint8_t isrc, status; + int n = 0; + +- /* Shared interrupts and IRQ off? */ +- if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) +- return IRQ_NONE; +- + if (priv->pre_irq) + priv->pre_irq(priv); + ++ /* Shared interrupts and IRQ off? */ ++ if (priv->read_reg(priv, SJA1000_IER) == IRQ_OFF) ++ goto out; ++ + while ((isrc = priv->read_reg(priv, SJA1000_IR)) && + (n < SJA1000_MAX_IRQ)) { +- n++; ++ + status = priv->read_reg(priv, SJA1000_SR); + /* check for absent controller due to hw unplug */ + if (status == 0xFF && sja1000_is_absent(priv)) +- return IRQ_NONE; ++ goto out; + + if (isrc & IRQ_WUI) + netdev_warn(dev, "wakeup interrupt\n"); +@@ -535,7 +535,7 @@ irqreturn_t sja1000_interrupt(int irq, v + status = priv->read_reg(priv, SJA1000_SR); + /* check for absent controller */ + if (status == 0xFF && sja1000_is_absent(priv)) +- return IRQ_NONE; ++ goto out; + } + } + if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { +@@ -543,8 +543,9 @@ irqreturn_t sja1000_interrupt(int irq, v + if (sja1000_err(dev, isrc, status)) + break; + } ++ n++; + } +- ++out: + if (priv->post_irq) + priv->post_irq(priv); + diff --git a/queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch b/queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch new file mode 100644 index 00000000000..b616921507b --- /dev/null +++ b/queue-3.12/efi-pstore-make-efi-pstore-return-a-unique-id.patch @@ -0,0 +1,84 @@ +From fdeadb43fdf1e7d5698c027b555c389174548e5a Mon Sep 17 00:00:00 2001 +From: Madper Xie +Date: Fri, 29 Nov 2013 15:58:57 +0800 +Subject: efi-pstore: Make efi-pstore return a unique id + +From: Madper Xie + +commit fdeadb43fdf1e7d5698c027b555c389174548e5a upstream. + +Pstore fs expects that backends provide a unique id which could avoid +pstore making entries as duplication or denominating entries the same +name. So I combine the timestamp, part and count into id. + +Signed-off-by: Madper Xie +Cc: Seiji Aguchi +Signed-off-by: Matt Fleming +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firmware/efi/efi-pstore.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/firmware/efi/efi-pstore.c ++++ b/drivers/firmware/efi/efi-pstore.c +@@ -37,6 +37,12 @@ struct pstore_read_data { + char **buf; + }; + ++static inline u64 generic_id(unsigned long timestamp, ++ unsigned int part, int count) ++{ ++ return (timestamp * 100 + part) * 1000 + count; ++} ++ + static int efi_pstore_read_func(struct efivar_entry *entry, void *data) + { + efi_guid_t vendor = LINUX_EFI_CRASH_GUID; +@@ -55,7 +61,7 @@ static int efi_pstore_read_func(struct e + + if (sscanf(name, "dump-type%u-%u-%d-%lu-%c", + cb_data->type, &part, &cnt, &time, &data_type) == 5) { +- *cb_data->id = part; ++ *cb_data->id = generic_id(time, part, cnt); + *cb_data->count = cnt; + cb_data->timespec->tv_sec = time; + cb_data->timespec->tv_nsec = 0; +@@ -65,7 +71,7 @@ static int efi_pstore_read_func(struct e + *cb_data->compressed = false; + } else if (sscanf(name, "dump-type%u-%u-%d-%lu", + cb_data->type, &part, &cnt, &time) == 4) { +- *cb_data->id = part; ++ *cb_data->id = generic_id(time, part, cnt); + *cb_data->count = cnt; + cb_data->timespec->tv_sec = time; + cb_data->timespec->tv_nsec = 0; +@@ -77,7 +83,7 @@ static int efi_pstore_read_func(struct e + * which doesn't support holding + * multiple logs, remains. + */ +- *cb_data->id = part; ++ *cb_data->id = generic_id(time, part, 0); + *cb_data->count = 0; + cb_data->timespec->tv_sec = time; + cb_data->timespec->tv_nsec = 0; +@@ -320,14 +326,16 @@ static int efi_pstore_erase(enum pstore_ + char name[DUMP_NAME_LEN]; + efi_char16_t efi_name[DUMP_NAME_LEN]; + int found, i; ++ unsigned int part; + +- sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count, +- time.tv_sec); ++ do_div(id, 1000); ++ part = do_div(id, 100); ++ sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec); + + for (i = 0; i < DUMP_NAME_LEN; i++) + efi_name[i] = name[i]; + +- edata.id = id; ++ edata.id = part; + edata.type = type; + edata.count = count; + edata.time = time; diff --git a/queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch b/queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch new file mode 100644 index 00000000000..4bfb653205b --- /dev/null +++ b/queue-3.12/efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch @@ -0,0 +1,363 @@ +From e0d59733f6b1796b8d6692642c87d7dd862c3e3a Mon Sep 17 00:00:00 2001 +From: Seiji Aguchi +Date: Wed, 30 Oct 2013 15:27:26 -0400 +Subject: efivars, efi-pstore: Hold off deletion of sysfs entry until the scan is completed + +From: Seiji Aguchi + +commit e0d59733f6b1796b8d6692642c87d7dd862c3e3a upstream. + +Currently, when mounting pstore file system, a read callback of +efi_pstore driver runs mutiple times as below. + +- In the first read callback, scan efivar_sysfs_list from head and pass + a kmsg buffer of a entry to an upper pstore layer. +- In the second read callback, rescan efivar_sysfs_list from the entry + and pass another kmsg buffer to it. +- Repeat the scan and pass until the end of efivar_sysfs_list. + +In this process, an entry is read across the multiple read function +calls. To avoid race between the read and erasion, the whole process +above is protected by a spinlock, holding in open() and releasing in +close(). + +At the same time, kmemdup() is called to pass the buffer to pstore +filesystem during it. And then, it causes a following lockdep warning. + +To make the dynamic memory allocation runnable without taking spinlock, +holding off a deletion of sysfs entry if it happens while scanning it +via efi_pstore, and deleting it after the scan is completed. + +To implement it, this patch introduces two flags, scanning and deleting, +to efivar_entry. + +On the code basis, it seems that all the scanning and deleting logic is +not needed because __efivars->lock are not dropped when reading from the +EFI variable store. + +But, the scanning and deleting logic is still needed because an +efi-pstore and a pstore filesystem works as follows. + +In case an entry(A) is found, the pointer is saved to psi->data. And +efi_pstore_read() passes the entry(A) to a pstore filesystem by +releasing __efivars->lock. + +And then, the pstore filesystem calls efi_pstore_read() again and the +same entry(A), which is saved to psi->data, is used for resuming to scan +a sysfs-list. + +So, to protect the entry(A), the logic is needed. + +[ 1.143710] ------------[ cut here ]------------ +[ 1.144058] WARNING: CPU: 1 PID: 1 at kernel/lockdep.c:2740 lockdep_trace_alloc+0x104/0x110() +[ 1.144058] DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) +[ 1.144058] Modules linked in: +[ 1.144058] CPU: 1 PID: 1 Comm: systemd Not tainted 3.11.0-rc5 #2 +[ 1.144058] 0000000000000009 ffff8800797e9ae0 ffffffff816614a5 ffff8800797e9b28 +[ 1.144058] ffff8800797e9b18 ffffffff8105510d 0000000000000080 0000000000000046 +[ 1.144058] 00000000000000d0 00000000000003af ffffffff81ccd0c0 ffff8800797e9b78 +[ 1.144058] Call Trace: +[ 1.144058] [] dump_stack+0x54/0x74 +[ 1.144058] [] warn_slowpath_common+0x7d/0xa0 +[ 1.144058] [] warn_slowpath_fmt+0x4c/0x50 +[ 1.144058] [] ? vsscanf+0x57f/0x7b0 +[ 1.144058] [] lockdep_trace_alloc+0x104/0x110 +[ 1.144058] [] __kmalloc_track_caller+0x50/0x280 +[ 1.144058] [] ? efi_pstore_read_func.part.1+0x12b/0x170 +[ 1.144058] [] kmemdup+0x20/0x50 +[ 1.144058] [] efi_pstore_read_func.part.1+0x12b/0x170 +[ 1.144058] [] ? efi_pstore_read_func.part.1+0x170/0x170 +[ 1.144058] [] efi_pstore_read_func+0xb4/0xe0 +[ 1.144058] [] __efivar_entry_iter+0xfb/0x120 +[ 1.144058] [] efi_pstore_read+0x3f/0x50 +[ 1.144058] [] pstore_get_records+0x9a/0x150 +[ 1.158207] [] ? selinux_d_instantiate+0x1c/0x20 +[ 1.158207] [] ? parse_options+0x80/0x80 +[ 1.158207] [] pstore_fill_super+0xa5/0xc0 +[ 1.158207] [] mount_single+0xa2/0xd0 +[ 1.158207] [] pstore_mount+0x18/0x20 +[ 1.158207] [] mount_fs+0x39/0x1b0 +[ 1.158207] [] ? __alloc_percpu+0x10/0x20 +[ 1.158207] [] vfs_kern_mount+0x63/0xf0 +[ 1.158207] [] do_mount+0x23e/0xa20 +[ 1.158207] [] ? strndup_user+0x4b/0xf0 +[ 1.158207] [] SyS_mount+0x83/0xc0 +[ 1.158207] [] system_call_fastpath+0x16/0x1b +[ 1.158207] ---[ end trace 61981bc62de9f6f4 ]--- + +Signed-off-by: Seiji Aguchi +Tested-by: Madper Xie +Signed-off-by: Matt Fleming +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firmware/efi/efi-pstore.c | 143 +++++++++++++++++++++++++++++++++++--- + drivers/firmware/efi/efivars.c | 12 ++- + drivers/firmware/efi/vars.c | 12 ++- + include/linux/efi.h | 4 + + 4 files changed, 155 insertions(+), 16 deletions(-) + +--- a/drivers/firmware/efi/efi-pstore.c ++++ b/drivers/firmware/efi/efi-pstore.c +@@ -18,14 +18,12 @@ module_param_named(pstore_disable, efiva + + static int efi_pstore_open(struct pstore_info *psi) + { +- efivar_entry_iter_begin(); + psi->data = NULL; + return 0; + } + + static int efi_pstore_close(struct pstore_info *psi) + { +- efivar_entry_iter_end(); + psi->data = NULL; + return 0; + } +@@ -91,19 +89,125 @@ static int efi_pstore_read_func(struct e + __efivar_entry_get(entry, &entry->var.Attributes, + &entry->var.DataSize, entry->var.Data); + size = entry->var.DataSize; ++ memcpy(*cb_data->buf, entry->var.Data, ++ (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size)); + +- *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL); +- if (*cb_data->buf == NULL) +- return -ENOMEM; + return size; + } + ++/** ++ * efi_pstore_scan_sysfs_enter ++ * @entry: scanning entry ++ * @next: next entry ++ * @head: list head ++ */ ++static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos, ++ struct efivar_entry *next, ++ struct list_head *head) ++{ ++ pos->scanning = true; ++ if (&next->list != head) ++ next->scanning = true; ++} ++ ++/** ++ * __efi_pstore_scan_sysfs_exit ++ * @entry: deleting entry ++ * @turn_off_scanning: Check if a scanning flag should be turned off ++ */ ++static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry, ++ bool turn_off_scanning) ++{ ++ if (entry->deleting) { ++ list_del(&entry->list); ++ efivar_entry_iter_end(); ++ efivar_unregister(entry); ++ efivar_entry_iter_begin(); ++ } else if (turn_off_scanning) ++ entry->scanning = false; ++} ++ ++/** ++ * efi_pstore_scan_sysfs_exit ++ * @pos: scanning entry ++ * @next: next entry ++ * @head: list head ++ * @stop: a flag checking if scanning will stop ++ */ ++static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos, ++ struct efivar_entry *next, ++ struct list_head *head, bool stop) ++{ ++ __efi_pstore_scan_sysfs_exit(pos, true); ++ if (stop) ++ __efi_pstore_scan_sysfs_exit(next, &next->list != head); ++} ++ ++/** ++ * efi_pstore_sysfs_entry_iter ++ * ++ * @data: function-specific data to pass to callback ++ * @pos: entry to begin iterating from ++ * ++ * You MUST call efivar_enter_iter_begin() before this function, and ++ * efivar_entry_iter_end() afterwards. ++ * ++ * It is possible to begin iteration from an arbitrary entry within ++ * the list by passing @pos. @pos is updated on return to point to ++ * the next entry of the last one passed to efi_pstore_read_func(). ++ * To begin iterating from the beginning of the list @pos must be %NULL. ++ */ ++static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) ++{ ++ struct efivar_entry *entry, *n; ++ struct list_head *head = &efivar_sysfs_list; ++ int size = 0; ++ ++ if (!*pos) { ++ list_for_each_entry_safe(entry, n, head, list) { ++ efi_pstore_scan_sysfs_enter(entry, n, head); ++ ++ size = efi_pstore_read_func(entry, data); ++ efi_pstore_scan_sysfs_exit(entry, n, head, size < 0); ++ if (size) ++ break; ++ } ++ *pos = n; ++ return size; ++ } ++ ++ list_for_each_entry_safe_from((*pos), n, head, list) { ++ efi_pstore_scan_sysfs_enter((*pos), n, head); ++ ++ size = efi_pstore_read_func((*pos), data); ++ efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0); ++ if (size) ++ break; ++ } ++ *pos = n; ++ return size; ++} ++ ++/** ++ * efi_pstore_read ++ * ++ * This function returns a size of NVRAM entry logged via efi_pstore_write(). ++ * The meaning and behavior of efi_pstore/pstore are as below. ++ * ++ * size > 0: Got data of an entry logged via efi_pstore_write() successfully, ++ * and pstore filesystem will continue reading subsequent entries. ++ * size == 0: Entry was not logged via efi_pstore_write(), ++ * and efi_pstore driver will continue reading subsequent entries. ++ * size < 0: Failed to get data of entry logging via efi_pstore_write(), ++ * and pstore will stop reading entry. ++ */ + static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, + int *count, struct timespec *timespec, + char **buf, bool *compressed, + struct pstore_info *psi) + { + struct pstore_read_data data; ++ ssize_t size; + + data.id = id; + data.type = type; +@@ -112,8 +216,17 @@ static ssize_t efi_pstore_read(u64 *id, + data.compressed = compressed; + data.buf = buf; + +- return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data, +- (struct efivar_entry **)&psi->data); ++ *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); ++ if (!*data.buf) ++ return -ENOMEM; ++ ++ efivar_entry_iter_begin(); ++ size = efi_pstore_sysfs_entry_iter(&data, ++ (struct efivar_entry **)&psi->data); ++ efivar_entry_iter_end(); ++ if (size <= 0) ++ kfree(*data.buf); ++ return size; + } + + static int efi_pstore_write(enum pstore_type_id type, +@@ -184,9 +297,17 @@ static int efi_pstore_erase_func(struct + return 0; + } + ++ if (entry->scanning) { ++ /* ++ * Skip deletion because this entry will be deleted ++ * after scanning is completed. ++ */ ++ entry->deleting = true; ++ } else ++ list_del(&entry->list); ++ + /* found */ + __efivar_entry_delete(entry); +- list_del(&entry->list); + + return 1; + } +@@ -214,10 +335,12 @@ static int efi_pstore_erase(enum pstore_ + + efivar_entry_iter_begin(); + found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry); +- efivar_entry_iter_end(); + +- if (found) ++ if (found && !entry->scanning) { ++ efivar_entry_iter_end(); + efivar_unregister(entry); ++ } else ++ efivar_entry_iter_end(); + + return 0; + } +--- a/drivers/firmware/efi/efivars.c ++++ b/drivers/firmware/efi/efivars.c +@@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file + else if (__efivar_entry_delete(entry)) + err = -EIO; + +- efivar_entry_iter_end(); +- +- if (err) ++ if (err) { ++ efivar_entry_iter_end(); + return err; ++ } + +- efivar_unregister(entry); ++ if (!entry->scanning) { ++ efivar_entry_iter_end(); ++ efivar_unregister(entry); ++ } else ++ efivar_entry_iter_end(); + + /* It's dead Jim.... */ + return count; +--- a/drivers/firmware/efi/vars.c ++++ b/drivers/firmware/efi/vars.c +@@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(e + if (!found) + return NULL; + +- if (remove) +- list_del(&entry->list); ++ if (remove) { ++ if (entry->scanning) { ++ /* ++ * The entry will be deleted ++ * after scanning is completed. ++ */ ++ entry->deleting = true; ++ } else ++ list_del(&entry->list); ++ } + + return entry; + } +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -782,6 +782,8 @@ struct efivar_entry { + struct efi_variable var; + struct list_head list; + struct kobject kobj; ++ bool scanning; ++ bool deleting; + }; + + extern struct list_head efivar_sysfs_list; +@@ -840,6 +842,8 @@ void efivar_run_worker(void); + #if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE) + int efivars_sysfs_init(void); + ++#define EFIVARS_DATA_SIZE_MAX 1024 ++ + #endif /* CONFIG_EFI_VARS */ + + #endif /* _LINUX_EFI_H */ diff --git a/queue-3.12/series b/queue-3.12/series index 763c124e5b5..cacff9b29fe 100644 --- a/queue-3.12/series +++ b/queue-3.12/series @@ -20,3 +20,12 @@ arm-mvebu-second-pcie-unit-of-armada-xp-mv78230-is-only-x1-capable.patch arm-mvebu-fix-second-and-third-pcie-unit-of-armada-xp-mv78260.patch arm-mvebu-use-the-virtual-cpu-registers-to-access-coherency-registers.patch arm-mvebu-re-enable-pcie-on-armada-370-db.patch +asoc-wm8990-mark-the-register-map-as-dirty-when-powering-down.patch +asoc-dapm-use-snd_soc_dapm_init_reg_val-in-snd_soc_dapm_mux.patch +asoc-wm8731-fix-dsp-mode-configuration.patch +vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch +can-sja1000-fix-pre-post-_irq-handling-and-irq-handler-return-value.patch +can-flexcan-use-correct-clock-as-base-for-bit-rate-calculation.patch +can-c_can-don-t-call-pm_runtime_get_sync-from-interrupt-context.patch +efivars-efi-pstore-hold-off-deletion-of-sysfs-entry-until-the-scan-is-completed.patch +efi-pstore-make-efi-pstore-return-a-unique-id.patch diff --git a/queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch b/queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch new file mode 100644 index 00000000000..aed9775527f --- /dev/null +++ b/queue-3.12/vfs-fix-subtle-use-after-free-of-pipe_inode_info.patch @@ -0,0 +1,133 @@ +From b0d8d2292160bb63de1972361ebed100c64b5b37 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 2 Dec 2013 09:44:51 -0800 +Subject: vfs: fix subtle use-after-free of pipe_inode_info + +From: Linus Torvalds + +commit b0d8d2292160bb63de1972361ebed100c64b5b37 upstream. + +The pipe code was trying (and failing) to be very careful about freeing +the pipe info only after the last access, with a pattern like: + + spin_lock(&inode->i_lock); + if (!--pipe->files) { + inode->i_pipe = NULL; + kill = 1; + } + spin_unlock(&inode->i_lock); + __pipe_unlock(pipe); + if (kill) + free_pipe_info(pipe); + +where the final freeing is done last. + +HOWEVER. The above is actually broken, because while the freeing is +done at the end, if we have two racing processes releasing the pipe +inode info, the one that *doesn't* free it will decrement the ->files +count, and unlock the inode i_lock, but then still use the +"pipe_inode_info" afterwards when it does the "__pipe_unlock(pipe)". + +This is *very* hard to trigger in practice, since the race window is +very small, and adding debug options seems to just hide it by slowing +things down. + +Simon originally reported this way back in July as an Oops in +kmem_cache_allocate due to a single bit corruption (due to the final +"spin_unlock(pipe->mutex.wait_lock)" incrementing a field in a different +allocation that had re-used the free'd pipe-info), it's taken this long +to figure out. + +Since the 'pipe->files' accesses aren't even protected by the pipe lock +(we very much use the inode lock for that), the simple solution is to +just drop the pipe lock early. And since there were two users of this +pattern, create a helper function for it. + +Introduced commit ba5bb147330a ("pipe: take allocation and freeing of +pipe_inode_info out of ->i_mutex"). + +Reported-by: Simon Kirby +Reported-by: Ian Applegate +Acked-by: Al Viro +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/pipe.c | 39 +++++++++++++++++++-------------------- + 1 file changed, 19 insertions(+), 20 deletions(-) + +--- a/fs/pipe.c ++++ b/fs/pipe.c +@@ -726,11 +726,25 @@ pipe_poll(struct file *filp, poll_table + return mask; + } + ++static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe) ++{ ++ int kill = 0; ++ ++ spin_lock(&inode->i_lock); ++ if (!--pipe->files) { ++ inode->i_pipe = NULL; ++ kill = 1; ++ } ++ spin_unlock(&inode->i_lock); ++ ++ if (kill) ++ free_pipe_info(pipe); ++} ++ + static int + pipe_release(struct inode *inode, struct file *file) + { +- struct pipe_inode_info *pipe = inode->i_pipe; +- int kill = 0; ++ struct pipe_inode_info *pipe = file->private_data; + + __pipe_lock(pipe); + if (file->f_mode & FMODE_READ) +@@ -743,17 +757,9 @@ pipe_release(struct inode *inode, struct + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); + } +- spin_lock(&inode->i_lock); +- if (!--pipe->files) { +- inode->i_pipe = NULL; +- kill = 1; +- } +- spin_unlock(&inode->i_lock); + __pipe_unlock(pipe); + +- if (kill) +- free_pipe_info(pipe); +- ++ put_pipe_info(inode, pipe); + return 0; + } + +@@ -1014,7 +1020,6 @@ static int fifo_open(struct inode *inode + { + struct pipe_inode_info *pipe; + bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC; +- int kill = 0; + int ret; + + filp->f_version = 0; +@@ -1130,15 +1135,9 @@ err_wr: + goto err; + + err: +- spin_lock(&inode->i_lock); +- if (!--pipe->files) { +- inode->i_pipe = NULL; +- kill = 1; +- } +- spin_unlock(&inode->i_lock); + __pipe_unlock(pipe); +- if (kill) +- free_pipe_info(pipe); ++ ++ put_pipe_info(inode, pipe); + return ret; + } +