diff options
author | Zefan Li <lizefan@huawei.com> | 2015-04-02 21:55:09 +0800 |
---|---|---|
committer | Zefan Li <lizefan@huawei.com> | 2015-04-08 13:54:20 +0800 |
commit | 23f69c70517a5273302146441fcc828b22af5d0f (patch) | |
tree | dbe34063e313239712081da8aa3349922ce8da23 | |
parent | c8de10758625db1c3df438964ec567741d68e44f (diff) | |
download | linux-3.4.y-queue-23f69c70517a5273302146441fcc828b22af5d0f.tar.gz |
Add commits to 3.4.y, up to 3.19-rc7
103 files changed, 7567 insertions, 0 deletions
diff --git a/patches/alsa-hda-fix-wrong-gpio_dir-gpio_mask-hint-setups-for-idt-stac-codecs.patch b/patches/alsa-hda-fix-wrong-gpio_dir-gpio_mask-hint-setups-for-idt-stac-codecs.patch new file mode 100644 index 0000000..0432b5a --- /dev/null +++ b/patches/alsa-hda-fix-wrong-gpio_dir-gpio_mask-hint-setups-for-idt-stac-codecs.patch @@ -0,0 +1,33 @@ +From c507de88f6a336bd7296c9ec0073b2d4af8b4f5e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Mon, 5 Jan 2015 13:27:33 +0100 +Subject: ALSA: hda - Fix wrong gpio_dir & gpio_mask hint setups for IDT/STAC + codecs + +commit c507de88f6a336bd7296c9ec0073b2d4af8b4f5e upstream. + +stac_store_hints() does utterly wrong for masking the values for +gpio_dir and gpio_data, likely due to copy&paste errors. Fortunately, +this feature is used very rarely, so the impact must be really small. + +Reported-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/pci/hda/patch_sigmatel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -4246,9 +4246,9 @@ static void stac_store_hints(struct hda_ + spec->gpio_mask; + } + if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) +- spec->gpio_mask &= spec->gpio_mask; +- if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) + spec->gpio_dir &= spec->gpio_mask; ++ if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) ++ spec->gpio_data &= spec->gpio_mask; + if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) + spec->eapd_mask &= spec->gpio_mask; + if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) diff --git a/patches/alsa-seq-dummy-remove-deadlock-causing-events-on-close.patch b/patches/alsa-seq-dummy-remove-deadlock-causing-events-on-close.patch new file mode 100644 index 0000000..bb115e4 --- /dev/null +++ b/patches/alsa-seq-dummy-remove-deadlock-causing-events-on-close.patch @@ -0,0 +1,71 @@ +From 0767e95bb96d7fdddcd590fb809e6975d93aebc5 Mon Sep 17 00:00:00 2001 +From: Clemens Ladisch <clemens@ladisch.de> +Date: Sun, 25 Jan 2015 14:34:29 +0100 +Subject: ALSA: seq-dummy: remove deadlock-causing events on close + +commit 0767e95bb96d7fdddcd590fb809e6975d93aebc5 upstream. + +When the last subscriber to a "Through" port has been removed, the +subscribed destination ports might still be active, so it would be +wrong to send "all sounds off" and "reset controller" events to them. +The proper place for such a shutdown would be the closing of the actual +MIDI port (and close_substream() in rawmidi.c already can do this). + +This also fixes a deadlock when dummy_unuse() tries to send events to +its own port that is already locked because it is being freed. + +Reported-by: Peter Billam <peter@www.pjb.com.au> +Signed-off-by: Clemens Ladisch <clemens@ladisch.de> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/core/seq/seq_dummy.c | 31 ------------------------------- + 1 file changed, 31 deletions(-) + +--- a/sound/core/seq/seq_dummy.c ++++ b/sound/core/seq/seq_dummy.c +@@ -82,36 +82,6 @@ struct snd_seq_dummy_port { + static int my_client = -1; + + /* +- * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events +- * to subscribers. +- * Note: this callback is called only after all subscribers are removed. +- */ +-static int +-dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) +-{ +- struct snd_seq_dummy_port *p; +- int i; +- struct snd_seq_event ev; +- +- p = private_data; +- memset(&ev, 0, sizeof(ev)); +- if (p->duplex) +- ev.source.port = p->connect; +- else +- ev.source.port = p->port; +- ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; +- ev.type = SNDRV_SEQ_EVENT_CONTROLLER; +- for (i = 0; i < 16; i++) { +- ev.data.control.channel = i; +- ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; +- snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); +- } +- return 0; +-} +- +-/* + * event input callback - just redirect events to subscribers + */ + static int +@@ -175,7 +145,6 @@ create_port(int idx, int type) + | SNDRV_SEQ_PORT_TYPE_PORT; + memset(&pcb, 0, sizeof(pcb)); + pcb.owner = THIS_MODULE; +- pcb.unuse = dummy_unuse; + pcb.event_input = dummy_input; + pcb.private_free = dummy_free; + pcb.private_data = rec; diff --git a/patches/alsa-usb-audio-add-mic-volume-fix-quirk-for-logitech-webcam-c210.patch b/patches/alsa-usb-audio-add-mic-volume-fix-quirk-for-logitech-webcam-c210.patch new file mode 100644 index 0000000..aa67be2 --- /dev/null +++ b/patches/alsa-usb-audio-add-mic-volume-fix-quirk-for-logitech-webcam-c210.patch @@ -0,0 +1,24 @@ +From 6455931186bff407493135e74c5f32efd30860e2 Mon Sep 17 00:00:00 2001 +From: Jason Lee Cragg <jcragg@gmail.com> +Date: Sat, 17 Jan 2015 12:28:29 -0500 +Subject: ALSA: usb-audio: Add mic volume fix quirk for Logitech Webcam C210 + +commit 6455931186bff407493135e74c5f32efd30860e2 upstream. + +Signed-off-by: Jason Lee Cragg <jcragg@gmail.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/usb/mixer.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -834,6 +834,7 @@ static void volume_control_quirks(struct + case USB_ID(0x046d, 0x0807): /* Logitech Webcam C500 */ + case USB_ID(0x046d, 0x0808): + case USB_ID(0x046d, 0x0809): ++ case USB_ID(0x046d, 0x0819): /* Logitech Webcam C210 */ + case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ + case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ + case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ diff --git a/patches/alsa-usb-audio-don-t-resubmit-pending-urbs-at-midi-error-recovery.patch b/patches/alsa-usb-audio-don-t-resubmit-pending-urbs-at-midi-error-recovery.patch new file mode 100644 index 0000000..8bb988a --- /dev/null +++ b/patches/alsa-usb-audio-don-t-resubmit-pending-urbs-at-midi-error-recovery.patch @@ -0,0 +1,64 @@ +From 66139a48cee1530c91f37c145384b4ee7043f0b7 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Sat, 6 Dec 2014 18:02:55 +0100 +Subject: ALSA: usb-audio: Don't resubmit pending URBs at MIDI error recovery + +commit 66139a48cee1530c91f37c145384b4ee7043f0b7 upstream. + +In snd_usbmidi_error_timer(), the driver tries to resubmit MIDI input +URBs to reactivate the MIDI stream, but this causes the error when +some of URBs are still pending like: + + WARNING: CPU: 0 PID: 0 at ../drivers/usb/core/urb.c:339 usb_submit_urb+0x5f/0x70() + URB ef705c40 submitted while active + CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.16.6-2-desktop #1 + Hardware name: FOXCONN TPS01/TPS01, BIOS 080015 03/23/2010 + c0984bfa f4009ed4 c078deaf f4009ee4 c024c884 c09a135c f4009f00 00000000 + c0984bfa 00000153 c061ac4f c061ac4f 00000009 00000001 ef705c40 e854d1c0 + f4009eec c024c8d3 00000009 f4009ee4 c09a135c f4009f00 f4009f04 c061ac4f + Call Trace: + [<c0205df6>] try_stack_unwind+0x156/0x170 + [<c020482a>] dump_trace+0x5a/0x1b0 + [<c0205e56>] show_trace_log_lvl+0x46/0x50 + [<c02049d1>] show_stack_log_lvl+0x51/0xe0 + [<c0205eb7>] show_stack+0x27/0x50 + [<c078deaf>] dump_stack+0x45/0x65 + [<c024c884>] warn_slowpath_common+0x84/0xa0 + [<c024c8d3>] warn_slowpath_fmt+0x33/0x40 + [<c061ac4f>] usb_submit_urb+0x5f/0x70 + [<f7974104>] snd_usbmidi_submit_urb+0x14/0x60 [snd_usbmidi_lib] + [<f797483a>] snd_usbmidi_error_timer+0x6a/0xa0 [snd_usbmidi_lib] + [<c02570c0>] call_timer_fn+0x30/0x130 + [<c0257442>] run_timer_softirq+0x1c2/0x260 + [<c0251493>] __do_softirq+0xc3/0x270 + [<c0204732>] do_softirq_own_stack+0x22/0x30 + [<c025186d>] irq_exit+0x8d/0xa0 + [<c0795228>] smp_apic_timer_interrupt+0x38/0x50 + [<c0794a3c>] apic_timer_interrupt+0x34/0x3c + [<c0673d9e>] cpuidle_enter_state+0x3e/0xd0 + [<c028bb8d>] cpu_idle_loop+0x29d/0x3e0 + [<c028bd23>] cpu_startup_entry+0x53/0x60 + [<c0bfac1e>] start_kernel+0x415/0x41a + +For avoiding these errors, check the pending URBs and skip +resubmitting such ones. + +Reported-and-tested-by: Stefan Seyfried <stefan.seyfried@googlemail.com> +Acked-by: Clemens Ladisch <clemens@ladisch.de> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/usb/midi.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/usb/midi.c ++++ b/sound/usb/midi.c +@@ -364,6 +364,8 @@ static void snd_usbmidi_error_timer(unsi + if (in && in->error_resubmit) { + in->error_resubmit = 0; + for (j = 0; j < INPUT_URBS; ++j) { ++ if (atomic_read(&in->urbs[j]->use_count)) ++ continue; + in->urbs[j]->dev = umidi->dev; + snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); + } diff --git a/patches/alsa-usb-audio-extend-kef-x300a-fu-10-tweak-to-arcam-rpac.patch b/patches/alsa-usb-audio-extend-kef-x300a-fu-10-tweak-to-arcam-rpac.patch new file mode 100644 index 0000000..6291bea --- /dev/null +++ b/patches/alsa-usb-audio-extend-kef-x300a-fu-10-tweak-to-arcam-rpac.patch @@ -0,0 +1,57 @@ +From d70a1b9893f820fdbcdffac408c909c50f2e6b43 Mon Sep 17 00:00:00 2001 +From: Jiri Jaburek <jjaburek@redhat.com> +Date: Thu, 18 Dec 2014 02:03:19 +0100 +Subject: ALSA: usb-audio: extend KEF X300A FU 10 tweak to Arcam rPAC + +commit d70a1b9893f820fdbcdffac408c909c50f2e6b43 upstream. + +The Arcam rPAC seems to have the same problem - whenever anything +(alsamixer, udevd, 3.9+ kernel from 60af3d037eb8c, ..) attempts to +access mixer / control interface of the card, the firmware "locks up" +the entire device, resulting in + SNDRV_PCM_IOCTL_HW_PARAMS failed (-5): Input/output error +from alsa-lib. + +Other operating systems can somehow read the mixer (there seems to be +playback volume/mute), but any manipulation is ignored by the device +(which has hardware volume controls). + +Signed-off-by: Jiri Jaburek <jjaburek@redhat.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/usb/mixer_maps.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -304,8 +304,11 @@ static struct usbmix_name_map hercules_u + { 0 } /* terminator */ + }; + +-static const struct usbmix_name_map kef_x300a_map[] = { +- { 10, NULL }, /* firmware locks up (?) when we try to access this FU */ ++/* some (all?) SCMS USB3318 devices are affected by a firmware lock up ++ * when anything attempts to access FU 10 (control) ++ */ ++static const struct usbmix_name_map scms_usb3318_map[] = { ++ { 10, NULL }, + { 0 } + }; + +@@ -377,8 +380,14 @@ static struct usbmix_ctl_map usbmix_ctl_ + .ignore_ctl_error = 1, + }, + { ++ /* KEF X300A */ + .id = USB_ID(0x27ac, 0x1000), +- .map = kef_x300a_map, ++ .map = scms_usb3318_map, ++ }, ++ { ++ /* Arcam rPAC */ ++ .id = USB_ID(0x25c4, 0x0003), ++ .map = scms_usb3318_map, + }, + { 0 } /* terminator */ + }; diff --git a/patches/asoc-sigmadsp-refuse-to-load-firmware-files-with-a-non-supported-version.patch b/patches/asoc-sigmadsp-refuse-to-load-firmware-files-with-a-non-supported-version.patch new file mode 100644 index 0000000..8c0a092 --- /dev/null +++ b/patches/asoc-sigmadsp-refuse-to-load-firmware-files-with-a-non-supported-version.patch @@ -0,0 +1,35 @@ +From 50c0f21b42dd4cd02b51f82274f66912d9a7fa32 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen <lars@metafoo.de> +Date: Wed, 19 Nov 2014 18:29:02 +0100 +Subject: ASoC: sigmadsp: Refuse to load firmware files with a non-supported + version + +commit 50c0f21b42dd4cd02b51f82274f66912d9a7fa32 upstream. + +Make sure to check the version field of the firmware header to make sure to +not accidentally try to parse a firmware file with a different layout. +Trying to do so can result in loading invalid firmware code to the device. + +Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/soc/codecs/sigmadsp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/sound/soc/codecs/sigmadsp.c ++++ b/sound/soc/codecs/sigmadsp.c +@@ -176,6 +176,13 @@ static int _process_sigma_firmware(struc + goto done; + } + ++ if (ssfw_head->version != 1) { ++ dev_err(dev, ++ "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", ++ ssfw_head->version); ++ goto done; ++ } ++ + crc = crc32(0, fw->data + sizeof(*ssfw_head), + fw->size - sizeof(*ssfw_head)); + pr_debug("%s: crc=%x\n", __func__, crc); diff --git a/patches/asoc-wm8960-fix-capture-sample-rate-from-11250-to-11025.patch b/patches/asoc-wm8960-fix-capture-sample-rate-from-11250-to-11025.patch new file mode 100644 index 0000000..b249494 --- /dev/null +++ b/patches/asoc-wm8960-fix-capture-sample-rate-from-11250-to-11025.patch @@ -0,0 +1,28 @@ +From 22ee76daddb87f88d2336d1b4737ef27c4f307ac Mon Sep 17 00:00:00 2001 +From: Zidan Wang <b50113@freescale.com> +Date: Wed, 31 Dec 2014 11:39:14 +0800 +Subject: ASoC: wm8960: Fix capture sample rate from 11250 to 11025 + +commit 22ee76daddb87f88d2336d1b4737ef27c4f307ac upstream. + +wm8960 codec can't support sample rate 11250, it must be 11025. + +Signed-off-by: Zidan Wang <b50113@freescale.com> +Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + sound/soc/codecs/wm8960.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -496,7 +496,7 @@ static struct { + { 22050, 2 }, + { 24000, 2 }, + { 16000, 3 }, +- { 11250, 4 }, ++ { 11025, 4 }, + { 12000, 4 }, + { 8000, 5 }, + }; diff --git a/patches/ath5k-fix-hardware-queue-index-assignment.patch b/patches/ath5k-fix-hardware-queue-index-assignment.patch new file mode 100644 index 0000000..e2bc79e --- /dev/null +++ b/patches/ath5k-fix-hardware-queue-index-assignment.patch @@ -0,0 +1,35 @@ +From 9e4982f6a51a2442f1bb588fee42521b44b4531c Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Sun, 30 Nov 2014 21:52:57 +0100 +Subject: ath5k: fix hardware queue index assignment + +commit 9e4982f6a51a2442f1bb588fee42521b44b4531c upstream. + +Like with ath9k, ath5k queues also need to be ordered by priority. +queue_info->tqi_subtype already contains the correct index, so use it +instead of relying on the order of ath5k_hw_setup_tx_queue calls. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: John W. Linville <linville@tuxdriver.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/wireless/ath/ath5k/qcu.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/qcu.c ++++ b/drivers/net/wireless/ath/ath5k/qcu.c +@@ -223,13 +223,7 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw + } else { + switch (queue_type) { + case AR5K_TX_QUEUE_DATA: +- for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; +- ah->ah_txq[queue].tqi_type != +- AR5K_TX_QUEUE_INACTIVE; queue++) { +- +- if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) +- return -EINVAL; +- } ++ queue = queue_info->tqi_subtype; + break; + case AR5K_TX_QUEUE_UAPSD: + queue = AR5K_TX_QUEUE_ID_UAPSD; diff --git a/patches/ath9k-fix-be-bk-queue-order.patch b/patches/ath9k-fix-be-bk-queue-order.patch new file mode 100644 index 0000000..d13a399 --- /dev/null +++ b/patches/ath9k-fix-be-bk-queue-order.patch @@ -0,0 +1,30 @@ +From 78063d81d353e10cbdd279c490593113b8fdae1c Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Sun, 30 Nov 2014 20:38:41 +0100 +Subject: ath9k: fix BE/BK queue order + +commit 78063d81d353e10cbdd279c490593113b8fdae1c upstream. + +Hardware queues are ordered by priority. Use queue index 0 for BK, which +has lower priority than BE. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: John W. Linville <linville@tuxdriver.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/wireless/ath/ath9k/hw.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -181,8 +181,8 @@ + #define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0 + + enum ath_hw_txq_subtype { +- ATH_TXQ_AC_BE = 0, +- ATH_TXQ_AC_BK = 1, ++ ATH_TXQ_AC_BK = 0, ++ ATH_TXQ_AC_BE = 1, + ATH_TXQ_AC_VI = 2, + ATH_TXQ_AC_VO = 3, + }; diff --git a/patches/ath9k_hw-fix-hardware-queue-allocation.patch b/patches/ath9k_hw-fix-hardware-queue-allocation.patch new file mode 100644 index 0000000..7a68739 --- /dev/null +++ b/patches/ath9k_hw-fix-hardware-queue-allocation.patch @@ -0,0 +1,37 @@ +From ad8fdccf9c197a89e2d2fa78c453283dcc2c343f Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Sun, 30 Nov 2014 20:38:40 +0100 +Subject: ath9k_hw: fix hardware queue allocation + +commit ad8fdccf9c197a89e2d2fa78c453283dcc2c343f upstream. + +The driver passes the desired hardware queue index for a WMM data queue +in qinfo->tqi_subtype. This was ignored in ath9k_hw_setuptxqueue, which +instead relied on the order in which the function is called. + +Reported-by: Hubert Feurstein <h.feurstein@gmail.com> +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: John W. Linville <linville@tuxdriver.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/wireless/ath/ath9k/mac.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -303,14 +303,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw + q = ATH9K_NUM_TX_QUEUES - 3; + break; + case ATH9K_TX_QUEUE_DATA: +- for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) +- if (ah->txq[q].tqi_type == +- ATH9K_TX_QUEUE_INACTIVE) +- break; +- if (q == ATH9K_NUM_TX_QUEUES) { +- ath_err(common, "No available TX queue\n"); +- return -1; +- } ++ q = qinfo->tqi_subtype; + break; + default: + ath_err(common, "Invalid TX queue type: %u\n", type); diff --git a/patches/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch b/patches/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch new file mode 100644 index 0000000..d5219a6 --- /dev/null +++ b/patches/btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch @@ -0,0 +1,170 @@ +From 678886bdc6378c1cbd5072da2c5a3035000214e3 Mon Sep 17 00:00:00 2001 +From: Filipe Manana <fdmanana@suse.com> +Date: Sun, 7 Dec 2014 21:31:47 +0000 +Subject: Btrfs: fix fs corruption on transaction abort if device supports + discard + +commit 678886bdc6378c1cbd5072da2c5a3035000214e3 upstream. + +When we abort a transaction we iterate over all the ranges marked as dirty +in fs_info->freed_extents[0] and fs_info->freed_extents[1], clear them +from those trees, add them back (unpin) to the free space caches and, if +the fs was mounted with "-o discard", perform a discard on those regions. +Also, after adding the regions to the free space caches, a fitrim ioctl call +can see those ranges in a block group's free space cache and perform a discard +on the ranges, so the same issue can happen without "-o discard" as well. + +This causes corruption, affecting one or multiple btree nodes (in the worst +case leaving the fs unmountable) because some of those ranges (the ones in +the fs_info->pinned_extents tree) correspond to btree nodes/leafs that are +referred by the last committed super block - breaking the rule that anything +that was committed by a transaction is untouched until the next transaction +commits successfully. + +I ran into this while running in a loop (for several hours) the fstest that +I recently submitted: + + [PATCH] fstests: add btrfs test to stress chunk allocation/removal and fstrim + +The corruption always happened when a transaction aborted and then fsck complained +like this: + + _check_btrfs_filesystem: filesystem on /dev/sdc is inconsistent + *** fsck.btrfs output *** + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + Check tree block failed, want=94945280, have=0 + read block failed check_tree_block + Couldn't open file system + +In this case 94945280 corresponded to the root of a tree. +Using frace what I observed was the following sequence of steps happened: + + 1) transaction N started, fs_info->pinned_extents pointed to + fs_info->freed_extents[0]; + + 2) node/eb 94945280 is created; + + 3) eb is persisted to disk; + + 4) transaction N commit starts, fs_info->pinned_extents now points to + fs_info->freed_extents[1], and transaction N completes; + + 5) transaction N + 1 starts; + + 6) eb is COWed, and btrfs_free_tree_block() called for this eb; + + 7) eb range (94945280 to 94945280 + 16Kb) is added to + fs_info->pinned_extents (fs_info->freed_extents[1]); + + 8) Something goes wrong in transaction N + 1, like hitting ENOSPC + for example, and the transaction is aborted, turning the fs into + readonly mode. The stack trace I got for example: + + [112065.253935] [<ffffffff8140c7b6>] dump_stack+0x4d/0x66 + [112065.254271] [<ffffffff81042984>] warn_slowpath_common+0x7f/0x98 + [112065.254567] [<ffffffffa0325990>] ? __btrfs_abort_transaction+0x50/0x10b [btrfs] + [112065.261674] [<ffffffff810429e5>] warn_slowpath_fmt+0x48/0x50 + [112065.261922] [<ffffffffa032949e>] ? btrfs_free_path+0x26/0x29 [btrfs] + [112065.262211] [<ffffffffa0325990>] __btrfs_abort_transaction+0x50/0x10b [btrfs] + [112065.262545] [<ffffffffa036b1d6>] btrfs_remove_chunk+0x537/0x58b [btrfs] + [112065.262771] [<ffffffffa033840f>] btrfs_delete_unused_bgs+0x1de/0x21b [btrfs] + [112065.263105] [<ffffffffa0343106>] cleaner_kthread+0x100/0x12f [btrfs] + (...) + [112065.264493] ---[ end trace dd7903a975a31a08 ]--- + [112065.264673] BTRFS: error (device sdc) in btrfs_remove_chunk:2625: errno=-28 No space left + [112065.264997] BTRFS info (device sdc): forced readonly + + 9) The clear kthread sees that the BTRFS_FS_STATE_ERROR bit is set in + fs_info->fs_state and calls btrfs_cleanup_transaction(), which in + turn calls btrfs_destroy_pinned_extent(); + + 10) Then btrfs_destroy_pinned_extent() iterates over all the ranges + marked as dirty in fs_info->freed_extents[], and for each one + it calls discard, if the fs was mounted with "-o discard", and + adds the range to the free space cache of the respective block + group; + + 11) btrfs_trim_block_group(), invoked from the fitrim ioctl code path, + sees the free space entries and performs a discard; + + 12) After an umount and mount (or fsck), our eb's location on disk was full + of zeroes, and it should have been untouched, because it was marked as + dirty in the fs_info->pinned_extents tree, and therefore used by the + trees that the last committed superblock points to. + +Fix this by not performing a discard and not adding the ranges to the free space +caches - it's useless from this point since the fs is now in readonly mode and +we won't write free space caches to disk anymore (otherwise we would leak space) +nor any new superblock. By not adding the ranges to the free space caches, it +prevents other code paths from allocating that space and write to it as well, +therefore being safer and simpler. + +This isn't a new problem, as it's been present since 2011 (git commit +acce952b0263825da32cf10489413dec78053347). + +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: Chris Mason <clm@fb.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/btrfs/disk-io.c | 6 ------ + fs/btrfs/extent-tree.c | 10 ++++++---- + 2 files changed, 6 insertions(+), 10 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -3556,12 +3556,6 @@ static int btrfs_destroy_pinned_extent(s + if (ret) + break; + +- /* opt_discard */ +- if (btrfs_test_opt(root, DISCARD)) +- ret = btrfs_error_discard_extent(root, start, +- end + 1 - start, +- NULL); +- + clear_extent_dirty(unpin, start, end, GFP_NOFS); + btrfs_error_unpin_extent_range(root, start, end); + cond_resched(); +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4892,7 +4892,8 @@ void btrfs_prepare_extent_commit(struct + update_global_block_rsv(fs_info); + } + +-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) ++static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, ++ const bool return_free_space) + { + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_group_cache *cache = NULL; +@@ -4912,7 +4913,8 @@ static int unpin_extent_range(struct btr + + if (start < cache->last_byte_to_unpin) { + len = min(len, cache->last_byte_to_unpin - start); +- btrfs_add_free_space(cache, start, len); ++ if (return_free_space) ++ btrfs_add_free_space(cache, start, len); + } + + start += len; +@@ -4960,7 +4962,7 @@ int btrfs_finish_extent_commit(struct bt + end + 1 - start, NULL); + + clear_extent_dirty(unpin, start, end, GFP_NOFS); +- unpin_extent_range(root, start, end); ++ unpin_extent_range(root, start, end, true); + cond_resched(); + } + +@@ -8008,7 +8010,7 @@ out: + + int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) + { +- return unpin_extent_range(root, start, end); ++ return unpin_extent_range(root, start, end, false); + } + + int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, diff --git a/patches/can-dev-fix-crtlmode_supported-check.patch b/patches/can-dev-fix-crtlmode_supported-check.patch new file mode 100644 index 0000000..f0411ae --- /dev/null +++ b/patches/can-dev-fix-crtlmode_supported-check.patch @@ -0,0 +1,44 @@ +From 9b1087aa5e86448fe6ad40a58964e35f3ba423d5 Mon Sep 17 00:00:00 2001 +From: Oliver Hartkopp <socketcan@hartkopp.net> +Date: Mon, 5 Jan 2015 18:40:15 +0100 +Subject: can: dev: fix crtlmode_supported check + +commit 9b1087aa5e86448fe6ad40a58964e35f3ba423d5 upstream. + +When changing flags in the CAN drivers ctrlmode the provided new content has to +be checked whether the bits are allowed to be changed. The bits that are to be +changed are given as a bitfield in cm->mask. Therefore checking against +cm->flags is wrong as the content can hold any kind of values. + +The iproute2 tool sets the bits in cm->mask and cm->flags depending on the +detected command line options. To be robust against bogus user space +applications additionally sanitize the provided flags with the provided mask. + +Cc: Wolfgang Grandegger <wg@grandegger.com> +Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/can/dev.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/dev.c ++++ b/drivers/net/can/dev.c +@@ -612,10 +612,14 @@ static int can_changelink(struct net_dev + if (dev->flags & IFF_UP) + return -EBUSY; + cm = nla_data(data[IFLA_CAN_CTRLMODE]); +- if (cm->flags & ~priv->ctrlmode_supported) ++ ++ /* check whether changed bits are allowed to be modified */ ++ if (cm->mask & ~priv->ctrlmode_supported) + return -EOPNOTSUPP; ++ ++ /* clear bits to be modified and copy the flag values */ + priv->ctrlmode &= ~cm->mask; +- priv->ctrlmode |= cm->flags; ++ priv->ctrlmode |= (cm->flags & cm->mask); + } + + if (data[IFLA_CAN_BITTIMING]) { diff --git a/patches/can-peak_usb-fix-cleanup-sequence-order-in-case-of-error-during-init.patch b/patches/can-peak_usb-fix-cleanup-sequence-order-in-case-of-error-during-init.patch new file mode 100644 index 0000000..f7d3c15 --- /dev/null +++ b/patches/can-peak_usb-fix-cleanup-sequence-order-in-case-of-error-during-init.patch @@ -0,0 +1,75 @@ +From af35d0f1cce7a990286e2b94c260a2c2d2a0e4b0 Mon Sep 17 00:00:00 2001 +From: Stephane Grosjean <s.grosjean@peak-system.com> +Date: Fri, 28 Nov 2014 13:49:10 +0100 +Subject: can: peak_usb: fix cleanup sequence order in case of error during + init + +commit af35d0f1cce7a990286e2b94c260a2c2d2a0e4b0 upstream. + +This patch sets the correct reverse sequence order to the instructions +set to run, when any failure occurs during the initialization steps. +It also adds the missing unregistration call of the can device if the +failure appears after having been registered. + +Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/can/usb/peak_usb/pcan_usb_core.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -737,7 +737,7 @@ static int peak_usb_create_dev(struct pe + dev_err(&intf->dev, "%s: couldn't alloc cmd buffer\n", + PCAN_USB_DRIVER_NAME); + err = -ENOMEM; +- goto lbl_set_intf_data; ++ goto lbl_free_candev; + } + + dev->udev = usb_dev; +@@ -776,7 +776,7 @@ static int peak_usb_create_dev(struct pe + err = register_candev(netdev); + if (err) { + dev_err(&intf->dev, "couldn't register CAN device: %d\n", err); +- goto lbl_free_cmd_buf; ++ goto lbl_restore_intf_data; + } + + if (dev->prev_siblings) +@@ -789,14 +789,14 @@ static int peak_usb_create_dev(struct pe + if (dev->adapter->dev_init) { + err = dev->adapter->dev_init(dev); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* set bus off */ + if (dev->adapter->dev_set_bus) { + err = dev->adapter->dev_set_bus(dev, 0); + if (err) +- goto lbl_free_cmd_buf; ++ goto lbl_unregister_candev; + } + + /* get device number early */ +@@ -808,11 +808,14 @@ static int peak_usb_create_dev(struct pe + + return 0; + +-lbl_free_cmd_buf: +- kfree(dev->cmd_buf); ++lbl_unregister_candev: ++ unregister_candev(netdev); + +-lbl_set_intf_data: ++lbl_restore_intf_data: + usb_set_intfdata(intf, dev->prev_siblings); ++ kfree(dev->cmd_buf); ++ ++lbl_free_candev: + free_candev(netdev); + + return err; diff --git a/patches/can-peak_usb-fix-memset-usage.patch b/patches/can-peak_usb-fix-memset-usage.patch new file mode 100644 index 0000000..05ab21d --- /dev/null +++ b/patches/can-peak_usb-fix-memset-usage.patch @@ -0,0 +1,40 @@ +From dc50ddcd4c58a5a0226038307d6ef884bec9f8c2 Mon Sep 17 00:00:00 2001 +From: Stephane Grosjean <s.grosjean@peak-system.com> +Date: Fri, 28 Nov 2014 14:08:48 +0100 +Subject: can: peak_usb: fix memset() usage + +commit dc50ddcd4c58a5a0226038307d6ef884bec9f8c2 upstream. + +This patchs fixes a misplaced call to memset() that fills the request +buffer with 0. The problem was with sending PCAN_USBPRO_REQ_FCT +requests, the content set by the caller was thus lost. + +With this patch, the memory area is zeroed only when requesting info +from the device. + +Signed-off-by: Stephane Grosjean <s.grosjean@peak-system.com> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +@@ -333,8 +333,6 @@ static int pcan_usb_pro_send_req(struct + if (!(dev->state & PCAN_USB_STATE_CONNECTED)) + return 0; + +- memset(req_addr, '\0', req_size); +- + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER; + + switch (req_id) { +@@ -345,6 +343,7 @@ static int pcan_usb_pro_send_req(struct + default: + p = usb_rcvctrlpipe(dev->udev, 0); + req_type |= USB_DIR_IN; ++ memset(req_addr, '\0', req_size); + break; + } + diff --git a/patches/cdc-acm-memory-leak-in-error-case.patch b/patches/cdc-acm-memory-leak-in-error-case.patch new file mode 100644 index 0000000..5ed9d2e --- /dev/null +++ b/patches/cdc-acm-memory-leak-in-error-case.patch @@ -0,0 +1,28 @@ +From d908f8478a8d18e66c80a12adb27764920c1f1ca Mon Sep 17 00:00:00 2001 +From: Oliver Neukum <oneukum@suse.de> +Date: Thu, 20 Nov 2014 14:54:35 +0100 +Subject: cdc-acm: memory leak in error case + +commit d908f8478a8d18e66c80a12adb27764920c1f1ca upstream. + +If probe() fails not only the attributes need to be removed +but also the memory freed. + +Reported-by: Ahmed Tamrawi <ahmedtamrawi@gmail.com> +Signed-off-by: Oliver Neukum <oneukum@suse.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/class/cdc-acm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1429,6 +1429,7 @@ static void acm_disconnect(struct usb_in + &dev_attr_wCountryCodes); + device_remove_file(&acm->control->dev, + &dev_attr_iCountryCodeRelDate); ++ kfree(acm->country_codes); + } + device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); + usb_set_intfdata(acm->control, NULL); diff --git a/patches/crypto-af_alg-fix-backlog-handling.patch b/patches/crypto-af_alg-fix-backlog-handling.patch new file mode 100644 index 0000000..33b35bf --- /dev/null +++ b/patches/crypto-af_alg-fix-backlog-handling.patch @@ -0,0 +1,45 @@ +From 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e Mon Sep 17 00:00:00 2001 +From: Rabin Vincent <rabin.vincent@axis.com> +Date: Fri, 19 Dec 2014 13:36:08 +0100 +Subject: crypto: af_alg - fix backlog handling + +commit 7e77bdebff5cb1e9876c561f69710b9ab8fa1f7e upstream. + +If a request is backlogged, it's complete() handler will get called +twice: once with -EINPROGRESS, and once with the final error code. + +af_alg's complete handler, unlike other users, does not handle the +-EINPROGRESS but instead always completes the completion that recvmsg() +is waiting on. This can lead to a return to user space while the +request is still pending in the driver. If userspace closes the sockets +before the requests are handled by the driver, this will lead to +use-after-frees (and potential crashes) in the kernel due to the tfm +having been freed. + +The crashes can be easily reproduced (for example) by reducing the max +queue length in cryptod.c and running the following (from +http://www.chronox.de/libkcapi.html) on AES-NI capable hardware: + + $ while true; do kcapi -x 1 -e -c '__ecb-aes-aesni' \ + -k 00000000000000000000000000000000 \ + -p 00000000000000000000000000000000 >/dev/null & done + +Signed-off-by: Rabin Vincent <rabin.vincent@axis.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + crypto/af_alg.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -449,6 +449,9 @@ void af_alg_complete(struct crypto_async + { + struct af_alg_completion *completion = req->data; + ++ if (err == -EINPROGRESS) ++ return; ++ + completion->err = err; + complete(&completion->completion); + } diff --git a/patches/drbd-merge_bvec_fn-properly-remap-bvm-bi_bdev.patch b/patches/drbd-merge_bvec_fn-properly-remap-bvm-bi_bdev.patch new file mode 100644 index 0000000..5237186 --- /dev/null +++ b/patches/drbd-merge_bvec_fn-properly-remap-bvm-bi_bdev.patch @@ -0,0 +1,29 @@ +From 3b9d35d744bb5139f9fed57f38c019bb8c7d351c Mon Sep 17 00:00:00 2001 +From: Lars Ellenberg <lars.ellenberg@linbit.com> +Date: Mon, 10 Nov 2014 17:21:13 +0100 +Subject: drbd: merge_bvec_fn: properly remap bvm->bi_bdev + +commit 3b9d35d744bb5139f9fed57f38c019bb8c7d351c upstream. + +This was not noticed for many years. Affects operation if +md raid is used a backing device for DRBD. + +Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> +Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> +Signed-off-by: Jens Axboe <axboe@fb.com> +[lizf: Backported to 3.4: s/device/mdev] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/block/drbd/drbd_req.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/block/drbd/drbd_req.c ++++ b/drivers/block/drbd/drbd_req.c +@@ -1184,6 +1184,7 @@ int drbd_merge_bvec(struct request_queue + struct request_queue * const b = + mdev->ldev->backing_bdev->bd_disk->queue; + if (b->merge_bvec_fn) { ++ bvm->bi_bdev = mdev->ldev->backing_bdev; + backing_limit = b->merge_bvec_fn(b, bvm, bvec); + limit = min(limit, backing_limit); + } diff --git a/patches/driver-core-fix-unbalanced-device-reference-in-drivers_probe.patch b/patches/driver-core-fix-unbalanced-device-reference-in-drivers_probe.patch new file mode 100644 index 0000000..c8ea90f --- /dev/null +++ b/patches/driver-core-fix-unbalanced-device-reference-in-drivers_probe.patch @@ -0,0 +1,78 @@ +From bb34cb6bbd287b57e955bc5cfd42fcde6aaca279 Mon Sep 17 00:00:00 2001 +From: Alex Williamson <alex.williamson@redhat.com> +Date: Fri, 31 Oct 2014 11:13:07 -0600 +Subject: driver core: Fix unbalanced device reference in drivers_probe + +commit bb34cb6bbd287b57e955bc5cfd42fcde6aaca279 upstream. + +bus_find_device_by_name() acquires a device reference which is never +released. This results in an object leak, which on older kernels +results in failure to release all resources of PCI devices. libvirt +uses drivers_probe to re-attach devices to the host after assignment +and is therefore a common trigger for this leak. + +Example: + +# cd /sys/bus/pci/ +# dmesg -C +# echo 1 > devices/0000\:01\:00.0/sriov_numvfs +# echo 0 > devices/0000\:01\:00.0/sriov_numvfs +# dmesg | grep 01:10 + pci 0000:01:10.0: [8086:10ca] type 00 class 0x020000 + kobject: '0000:01:10.0' (ffff8801d79cd0a8): kobject_add_internal: parent: '0000:00:01.0', set: 'devices' + kobject: '0000:01:10.0' (ffff8801d79cd0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79cd0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + kobject: '0000:01:10.0' (ffff8801d79cd0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79cd0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + kobject: '0000:01:10.0' (ffff8801d79cd0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79cd0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + kobject: '0000:01:10.0' (ffff8801d79cd0a8): kobject_cleanup, parent (null) + kobject: '0000:01:10.0' (ffff8801d79cd0a8): calling ktype release + kobject: '0000:01:10.0': free name + +[kobject freed as expected] + +# dmesg -C +# echo 1 > devices/0000\:01\:00.0/sriov_numvfs +# echo 0000:01:10.0 > drivers_probe +# echo 0 > devices/0000\:01\:00.0/sriov_numvfs +# dmesg | grep 01:10 + pci 0000:01:10.0: [8086:10ca] type 00 class 0x020000 + kobject: '0000:01:10.0' (ffff8801d79ce0a8): kobject_add_internal: parent: '0000:00:01.0', set: 'devices' + kobject: '0000:01:10.0' (ffff8801d79ce0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79ce0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + kobject: '0000:01:10.0' (ffff8801d79ce0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79ce0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + kobject: '0000:01:10.0' (ffff8801d79ce0a8): kobject_uevent_env + kobject: '0000:01:10.0' (ffff8801d79ce0a8): fill_kobj_path: path = '/devices/pci0000:00/0000:00:01.0/0000:01:10.0' + +[no free] + +Signed-off-by: Alex Williamson <alex.williamson@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/base/bus.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -245,13 +245,15 @@ static ssize_t store_drivers_probe(struc + const char *buf, size_t count) + { + struct device *dev; ++ int err = -EINVAL; + + dev = bus_find_device_by_name(bus, NULL, buf); + if (!dev) + return -ENODEV; +- if (bus_rescan_devices_helper(dev, NULL) != 0) +- return -EINVAL; +- return count; ++ if (bus_rescan_devices_helper(dev, NULL) == 0) ++ err = count; ++ put_device(dev); ++ return err; + } + #endif + diff --git a/patches/driver-core-introduce-device_create_groups.patch b/patches/driver-core-introduce-device_create_groups.patch new file mode 100644 index 0000000..be44ba4 --- /dev/null +++ b/patches/driver-core-introduce-device_create_groups.patch @@ -0,0 +1,179 @@ +From 39ef311204941ddd01ea2950d6220c8ccc710d15 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck <linux@roeck-us.net> +Date: Sun, 14 Jul 2013 16:05:57 -0700 +Subject: driver core: Introduce device_create_groups + +commit 39ef311204941ddd01ea2950d6220c8ccc710d15 upstream. + +device_create_groups lets callers create devices as well as associated +sysfs attributes with a single call. This avoids race conditions seen +if sysfs attributes on new devices are created later. + +[fixed up comment block placement and add checks for printk buffer +formats - gregkh] + +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Cc: Jean Delvare <khali@linux-fr.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/base/core.c | 111 ++++++++++++++++++++++++++++++++++++------------- + include/linux/device.h | 5 ++ + 2 files changed, 88 insertions(+), 28 deletions(-) + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -1494,34 +1494,11 @@ static void device_create_release(struct + kfree(dev); + } + +-/** +- * device_create_vargs - creates a device and registers it with sysfs +- * @class: pointer to the struct class that this device should be registered to +- * @parent: pointer to the parent struct device of this new device, if any +- * @devt: the dev_t for the char device to be added +- * @drvdata: the data to be added to the device for callbacks +- * @fmt: string for the device's name +- * @args: va_list for the device's name +- * +- * This function can be used by char device classes. A struct device +- * will be created in sysfs, registered to the specified class. +- * +- * A "dev" file will be created, showing the dev_t for the device, if +- * the dev_t is not 0,0. +- * If a pointer to a parent struct device is passed in, the newly created +- * struct device will be a child of that device in sysfs. +- * The pointer to the struct device will be returned from the call. +- * Any further sysfs files that might be required can be created using this +- * pointer. +- * +- * Returns &struct device pointer on success, or ERR_PTR() on error. +- * +- * Note: the struct class passed to this function must have previously +- * been created with a call to class_create(). +- */ +-struct device *device_create_vargs(struct class *class, struct device *parent, +- dev_t devt, void *drvdata, const char *fmt, +- va_list args) ++static struct device * ++device_create_groups_vargs(struct class *class, struct device *parent, ++ dev_t devt, void *drvdata, ++ const struct attribute_group **groups, ++ const char *fmt, va_list args) + { + struct device *dev = NULL; + int retval = -ENODEV; +@@ -1538,6 +1515,7 @@ struct device *device_create_vargs(struc + dev->devt = devt; + dev->class = class; + dev->parent = parent; ++ dev->groups = groups; + dev->release = device_create_release; + dev_set_drvdata(dev, drvdata); + +@@ -1555,6 +1533,39 @@ error: + put_device(dev); + return ERR_PTR(retval); + } ++ ++/** ++ * device_create_vargs - creates a device and registers it with sysfs ++ * @class: pointer to the struct class that this device should be registered to ++ * @parent: pointer to the parent struct device of this new device, if any ++ * @devt: the dev_t for the char device to be added ++ * @drvdata: the data to be added to the device for callbacks ++ * @fmt: string for the device's name ++ * @args: va_list for the device's name ++ * ++ * This function can be used by char device classes. A struct device ++ * will be created in sysfs, registered to the specified class. ++ * ++ * A "dev" file will be created, showing the dev_t for the device, if ++ * the dev_t is not 0,0. ++ * If a pointer to a parent struct device is passed in, the newly created ++ * struct device will be a child of that device in sysfs. ++ * The pointer to the struct device will be returned from the call. ++ * Any further sysfs files that might be required can be created using this ++ * pointer. ++ * ++ * Returns &struct device pointer on success, or ERR_PTR() on error. ++ * ++ * Note: the struct class passed to this function must have previously ++ * been created with a call to class_create(). ++ */ ++struct device *device_create_vargs(struct class *class, struct device *parent, ++ dev_t devt, void *drvdata, const char *fmt, ++ va_list args) ++{ ++ return device_create_groups_vargs(class, parent, devt, drvdata, NULL, ++ fmt, args); ++} + EXPORT_SYMBOL_GPL(device_create_vargs); + + /** +@@ -1594,6 +1605,50 @@ struct device *device_create(struct clas + } + EXPORT_SYMBOL_GPL(device_create); + ++/** ++ * device_create_with_groups - creates a device and registers it with sysfs ++ * @class: pointer to the struct class that this device should be registered to ++ * @parent: pointer to the parent struct device of this new device, if any ++ * @devt: the dev_t for the char device to be added ++ * @drvdata: the data to be added to the device for callbacks ++ * @groups: NULL-terminated list of attribute groups to be created ++ * @fmt: string for the device's name ++ * ++ * This function can be used by char device classes. A struct device ++ * will be created in sysfs, registered to the specified class. ++ * Additional attributes specified in the groups parameter will also ++ * be created automatically. ++ * ++ * A "dev" file will be created, showing the dev_t for the device, if ++ * the dev_t is not 0,0. ++ * If a pointer to a parent struct device is passed in, the newly created ++ * struct device will be a child of that device in sysfs. ++ * The pointer to the struct device will be returned from the call. ++ * Any further sysfs files that might be required can be created using this ++ * pointer. ++ * ++ * Returns &struct device pointer on success, or ERR_PTR() on error. ++ * ++ * Note: the struct class passed to this function must have previously ++ * been created with a call to class_create(). ++ */ ++struct device *device_create_with_groups(struct class *class, ++ struct device *parent, dev_t devt, ++ void *drvdata, ++ const struct attribute_group **groups, ++ const char *fmt, ...) ++{ ++ va_list vargs; ++ struct device *dev; ++ ++ va_start(vargs, fmt); ++ dev = device_create_groups_vargs(class, parent, devt, drvdata, groups, ++ fmt, vargs); ++ va_end(vargs); ++ return dev; ++} ++EXPORT_SYMBOL_GPL(device_create_with_groups); ++ + static int __match_devt(struct device *dev, void *data) + { + dev_t *devt = data; +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -835,6 +835,11 @@ extern __printf(5, 6) + struct device *device_create(struct class *cls, struct device *parent, + dev_t devt, void *drvdata, + const char *fmt, ...); ++extern __printf(6, 7) ++struct device *device_create_with_groups(struct class *cls, ++ struct device *parent, dev_t devt, void *drvdata, ++ const struct attribute_group **groups, ++ const char *fmt, ...); + extern void device_destroy(struct class *cls, dev_t devt); + + /* diff --git a/patches/drm-i915-only-fence-tiled-region-of-object.patch b/patches/drm-i915-only-fence-tiled-region-of-object.patch new file mode 100644 index 0000000..00e88c9 --- /dev/null +++ b/patches/drm-i915-only-fence-tiled-region-of-object.patch @@ -0,0 +1,62 @@ +From af1a7301c7cf8912dca03065d448c4437c5c239f Mon Sep 17 00:00:00 2001 +From: Bob Paauwe <bob.j.paauwe@intel.com> +Date: Thu, 18 Dec 2014 09:51:26 -0800 +Subject: drm/i915: Only fence tiled region of object. + +commit af1a7301c7cf8912dca03065d448c4437c5c239f upstream. + +When creating a fence for a tiled object, only fence the area that +makes up the actual tiles. The object may be larger than the tiled +area and if we allow those extra addresses to be fenced, they'll +get converted to addresses beyond where the object is mapped. This +opens up the possiblity of writes beyond the end of object. + +To prevent this, we adjust the size of the fence to only encompass +the area that makes up the actual tiles. The extra space is considered +un-tiled and now behaves as if it was a linear object. + +Testcase: igt/gem_tiled_fence_overflow +Reported-by: Dan Hettena <danh@ghs.com> +Signed-off-by: Bob Paauwe <bob.j.paauwe@intel.com> +Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Signed-off-by: Jani Nikula <jani.nikula@intel.com> +[lizf: Backported to 3.4: + - adjust context + - adjust indentation + - make the same change to both sandybridge_write_fence_reg() + and i965_write_fence_reg()] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpu/drm/i915/i915_gem.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -2193,6 +2193,13 @@ static int sandybridge_write_fence_reg(s + int regnum = obj->fence_reg; + uint64_t val; + ++ /* Adjust fence size to match tiled area */ ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ uint32_t row_size = obj->stride * ++ (obj->tiling_mode == I915_TILING_Y ? 32 : 8); ++ size = (size / row_size) * row_size; ++ } ++ + val = (uint64_t)((obj->gtt_offset + size - 4096) & + 0xfffff000) << 32; + val |= obj->gtt_offset & 0xfffff000; +@@ -2230,6 +2237,13 @@ static int i965_write_fence_reg(struct d + int regnum = obj->fence_reg; + uint64_t val; + ++ /* Adjust fence size to match tiled area */ ++ if (obj->tiling_mode != I915_TILING_NONE) { ++ uint32_t row_size = obj->stride * ++ (obj->tiling_mode == I915_TILING_Y ? 32 : 8); ++ size = (size / row_size) * row_size; ++ } ++ + val = (uint64_t)((obj->gtt_offset + size - 4096) & + 0xfffff000) << 32; + val |= obj->gtt_offset & 0xfffff000; diff --git a/patches/drm-radeon-check-the-right-ring-in-radeon_evict_flags.patch b/patches/drm-radeon-check-the-right-ring-in-radeon_evict_flags.patch new file mode 100644 index 0000000..2817431 --- /dev/null +++ b/patches/drm-radeon-check-the-right-ring-in-radeon_evict_flags.patch @@ -0,0 +1,32 @@ +From 5e5c21cac1001089007260c48b0c89ebaace0e71 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Wed, 3 Dec 2014 00:03:49 -0500 +Subject: drm/radeon: check the right ring in radeon_evict_flags() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 5e5c21cac1001089007260c48b0c89ebaace0e71 upstream. + +Check the that ring we are using for copies is functional +rather than the GFX ring. On newer asics we use the DMA +ring for bo moves. + +Reviewed-by: Christian König <christian.koenig@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/radeon_ttm.c ++++ b/drivers/gpu/drm/radeon/radeon_ttm.c +@@ -188,7 +188,7 @@ static void radeon_evict_flags(struct tt + rbo = container_of(bo, struct radeon_bo, tbo); + switch (bo->mem.mem_type) { + case TTM_PL_VRAM: +- if (rbo->rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready == false) ++ if (rbo->rdev->ring[radeon_copy_ring_index(rbo->rdev)].ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); diff --git a/patches/drm-vmwgfx-don-t-use-memory-accounting-for-kernel-side-fence-objects.patch b/patches/drm-vmwgfx-don-t-use-memory-accounting-for-kernel-side-fence-objects.patch new file mode 100644 index 0000000..5543816 --- /dev/null +++ b/patches/drm-vmwgfx-don-t-use-memory-accounting-for-kernel-side-fence-objects.patch @@ -0,0 +1,78 @@ +From 1f563a6a46544602183e7493b6ef69769d3d76d9 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom <thellstrom@vmware.com> +Date: Tue, 2 Dec 2014 03:32:24 -0800 +Subject: drm/vmwgfx: Don't use memory accounting for kernel-side fence objects + +commit 1f563a6a46544602183e7493b6ef69769d3d76d9 upstream. + +Kernel side fence objects are used when unbinding resources and may thus be +created as part of a memory reclaim operation. This might trigger recursive +memory reclaims and result in the kernel running out of stack space. + +So a simple way out is to avoid accounting of these fence objects. +In principle this is OK since while user-space can trigger the creation of +such objects, it can't really hold on to them. However, their lifetime is +quite long, so some form of accounting should perhaps be implemented in the +future. + +Fixes kernel crashes when running, for example viewperf11 ensight-04 test 3 +with low system memory settings. + +Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> +Reviewed-by: Jakob Bornecrantz <jakob@vmware.com> +Reviewed-by: Sinclair Yeh <syeh@vmware.com> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 21 ++------------------- + 1 file changed, 2 insertions(+), 19 deletions(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -485,14 +485,7 @@ void vmw_fence_obj_flush(struct vmw_fenc + + static void vmw_fence_destroy(struct vmw_fence_obj *fence) + { +- struct vmw_fence_manager *fman = fence->fman; +- + kfree(fence); +- /* +- * Free kernel space accounting. +- */ +- ttm_mem_global_free(vmw_mem_glob(fman->dev_priv), +- fman->fence_size); + } + + int vmw_fence_create(struct vmw_fence_manager *fman, +@@ -500,20 +493,12 @@ int vmw_fence_create(struct vmw_fence_ma + uint32_t mask, + struct vmw_fence_obj **p_fence) + { +- struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv); + struct vmw_fence_obj *fence; + int ret; + +- ret = ttm_mem_global_alloc(mem_glob, fman->fence_size, +- false, false); +- if (unlikely(ret != 0)) +- return ret; +- + fence = kzalloc(sizeof(*fence), GFP_KERNEL); +- if (unlikely(fence == NULL)) { +- ret = -ENOMEM; +- goto out_no_object; +- } ++ if (unlikely(fence == NULL)) ++ return -ENOMEM; + + ret = vmw_fence_obj_init(fman, fence, seqno, mask, + vmw_fence_destroy); +@@ -525,8 +510,6 @@ int vmw_fence_create(struct vmw_fence_ma + + out_err_init: + kfree(fence); +-out_no_object: +- ttm_mem_global_free(mem_glob, fman->fence_size); + return ret; + } + diff --git a/patches/drm-vmwgfx-fix-fence-event-code.patch b/patches/drm-vmwgfx-fix-fence-event-code.patch new file mode 100644 index 0000000..9bb3cec --- /dev/null +++ b/patches/drm-vmwgfx-fix-fence-event-code.patch @@ -0,0 +1,55 @@ +From 89669e7a7f96be3ee8d9a22a071d7c0d3b4428fc Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom <thellstrom@vmware.com> +Date: Tue, 2 Dec 2014 03:36:57 -0800 +Subject: drm/vmwgfx: Fix fence event code + +commit 89669e7a7f96be3ee8d9a22a071d7c0d3b4428fc upstream. + +The commit "vmwgfx: Rework fence event action" introduced a number of bugs +that are fixed with this commit: + +a) A forgotten return stateemnt. +b) An if statement with identical branches. + +Reported-by: Rob Clark <robdclark@gmail.com> +Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> +Reviewed-by: Jakob Bornecrantz <jakob@vmware.com> +Reviewed-by: Sinclair Yeh <syeh@vmware.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -1032,6 +1032,8 @@ int vmw_event_fence_action_create(struct + if (ret != 0) + goto out_no_queue; + ++ return 0; ++ + out_no_queue: + event->base.destroy(&event->base); + out_no_event: +@@ -1106,17 +1108,10 @@ int vmw_fence_event_ioctl(struct drm_dev + + BUG_ON(fence == NULL); + +- if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- else +- ret = vmw_event_fence_action_create(file_priv, fence, +- arg->flags, +- arg->user_data, +- true); +- ++ ret = vmw_event_fence_action_create(file_priv, fence, ++ arg->flags, ++ arg->user_data, ++ true); + if (unlikely(ret != 0)) { + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to attach event to fence.\n"); diff --git a/patches/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch b/patches/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch new file mode 100644 index 0000000..645b763 --- /dev/null +++ b/patches/ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch @@ -0,0 +1,102 @@ +From 332b122d39c9cbff8b799007a825d94b2e7c12f2 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks <tyhicks@canonical.com> +Date: Tue, 7 Oct 2014 15:51:55 -0500 +Subject: eCryptfs: Force RO mount when encrypted view is enabled + +commit 332b122d39c9cbff8b799007a825d94b2e7c12f2 upstream. + +The ecryptfs_encrypted_view mount option greatly changes the +functionality of an eCryptfs mount. Instead of encrypting and decrypting +lower files, it provides a unified view of the encrypted files in the +lower filesystem. The presence of the ecryptfs_encrypted_view mount +option is intended to force a read-only mount and modifying files is not +supported when the feature is in use. See the following commit for more +information: + + e77a56d [PATCH] eCryptfs: Encrypted passthrough + +This patch forces the mount to be read-only when the +ecryptfs_encrypted_view mount option is specified by setting the +MS_RDONLY flag on the superblock. Additionally, this patch removes some +broken logic in ecryptfs_open() that attempted to prevent modifications +of files when the encrypted view feature was in use. The check in +ecryptfs_open() was not sufficient to prevent file modifications using +system calls that do not operate on a file descriptor. + +Signed-off-by: Tyler Hicks <tyhicks@canonical.com> +Reported-by: Priya Bansal <p.bansal@samsung.com> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/ecryptfs/file.c | 12 ------------ + fs/ecryptfs/main.c | 16 +++++++++++++--- + 2 files changed, 13 insertions(+), 15 deletions(-) + +--- a/fs/ecryptfs/file.c ++++ b/fs/ecryptfs/file.c +@@ -195,24 +195,12 @@ static int ecryptfs_open(struct inode *i + { + int rc = 0; + struct ecryptfs_crypt_stat *crypt_stat = NULL; +- struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct dentry *ecryptfs_dentry = file->f_path.dentry; + /* Private value of ecryptfs_dentry allocated in + * ecryptfs_lookup() */ + struct dentry *lower_dentry; + struct ecryptfs_file_info *file_info; + +- mount_crypt_stat = &ecryptfs_superblock_to_private( +- ecryptfs_dentry->d_sb)->mount_crypt_stat; +- if ((mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) +- && ((file->f_flags & O_WRONLY) || (file->f_flags & O_RDWR) +- || (file->f_flags & O_CREAT) || (file->f_flags & O_TRUNC) +- || (file->f_flags & O_APPEND))) { +- printk(KERN_WARNING "Mount has encrypted view enabled; " +- "files may only be read\n"); +- rc = -EPERM; +- goto out; +- } + /* Released in ecryptfs_release or end of function if failure */ + file_info = kmem_cache_zalloc(ecryptfs_file_info_cache, GFP_KERNEL); + ecryptfs_set_file_private(file, file_info); +--- a/fs/ecryptfs/main.c ++++ b/fs/ecryptfs/main.c +@@ -494,6 +494,7 @@ static struct dentry *ecryptfs_mount(str + { + struct super_block *s; + struct ecryptfs_sb_info *sbi; ++ struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + struct ecryptfs_dentry_info *root_info; + const char *err = "Getting sb failed"; + struct inode *inode; +@@ -512,6 +513,7 @@ static struct dentry *ecryptfs_mount(str + err = "Error parsing options"; + goto out; + } ++ mount_crypt_stat = &sbi->mount_crypt_stat; + + s = sget(fs_type, NULL, set_anon_super, NULL); + if (IS_ERR(s)) { +@@ -557,11 +559,19 @@ static struct dentry *ecryptfs_mount(str + + /** + * Set the POSIX ACL flag based on whether they're enabled in the lower +- * mount. Force a read-only eCryptfs mount if the lower mount is ro. +- * Allow a ro eCryptfs mount even when the lower mount is rw. ++ * mount. + */ + s->s_flags = flags & ~MS_POSIXACL; +- s->s_flags |= path.dentry->d_sb->s_flags & (MS_RDONLY | MS_POSIXACL); ++ s->s_flags |= path.dentry->d_sb->s_flags & MS_POSIXACL; ++ ++ /** ++ * Force a read-only eCryptfs mount when: ++ * 1) The lower mount is ro ++ * 2) The ecryptfs_encrypted_view mount option is specified ++ */ ++ if (path.dentry->d_sb->s_flags & MS_RDONLY || ++ mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) ++ s->s_flags |= MS_RDONLY; + + s->s_maxbytes = path.dentry->d_sb->s_maxbytes; + s->s_blocksize = path.dentry->d_sb->s_blocksize; diff --git a/patches/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch b/patches/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch new file mode 100644 index 0000000..add0aa9 --- /dev/null +++ b/patches/ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch @@ -0,0 +1,32 @@ +From 942080643bce061c3dd9d5718d3b745dcb39a8bc Mon Sep 17 00:00:00 2001 +From: Michael Halcrow <mhalcrow@google.com> +Date: Wed, 26 Nov 2014 09:09:16 -0800 +Subject: eCryptfs: Remove buggy and unnecessary write in file name decode + routine + +commit 942080643bce061c3dd9d5718d3b745dcb39a8bc upstream. + +Dmitry Chernenkov used KASAN to discover that eCryptfs writes past the +end of the allocated buffer during encrypted filename decoding. This +fix corrects the issue by getting rid of the unnecessary 0 write when +the current bit offset is 2. + +Signed-off-by: Michael Halcrow <mhalcrow@google.com> +Reported-by: Dmitry Chernenkov <dmitryc@google.com> +Suggested-by: Kees Cook <keescook@chromium.org> +Signed-off-by: Tyler Hicks <tyhicks@canonical.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/ecryptfs/crypto.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -2044,7 +2044,6 @@ ecryptfs_decode_from_filename(unsigned c + break; + case 2: + dst[dst_byte_offset++] |= (src_byte); +- dst[dst_byte_offset] = 0; + current_bit_offset = 0; + break; + } diff --git a/patches/ftrace-jprobes-x86-fix-conflict-between-jprobes-and-function-graph-tracing.patch b/patches/ftrace-jprobes-x86-fix-conflict-between-jprobes-and-function-graph-tracing.patch new file mode 100644 index 0000000..15314aa --- /dev/null +++ b/patches/ftrace-jprobes-x86-fix-conflict-between-jprobes-and-function-graph-tracing.patch @@ -0,0 +1,114 @@ +From 237d28db036e411f22c03cfd5b0f6dc2aa9bf3bc Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> +Date: Mon, 12 Jan 2015 12:12:03 -0500 +Subject: ftrace/jprobes/x86: Fix conflict between jprobes and function graph + tracing + +commit 237d28db036e411f22c03cfd5b0f6dc2aa9bf3bc upstream. + +If the function graph tracer traces a jprobe callback, the system will +crash. This can easily be demonstrated by compiling the jprobe +sample module that is in the kernel tree, loading it and running the +function graph tracer. + + # modprobe jprobe_example.ko + # echo function_graph > /sys/kernel/debug/tracing/current_tracer + # ls + +The first two commands end up in a nice crash after the first fork. +(do_fork has a jprobe attached to it, so "ls" just triggers that fork) + +The problem is caused by the jprobe_return() that all jprobe callbacks +must end with. The way jprobes works is that the function a jprobe +is attached to has a breakpoint placed at the start of it (or it uses +ftrace if fentry is supported). The breakpoint handler (or ftrace callback) +will copy the stack frame and change the ip address to return to the +jprobe handler instead of the function. The jprobe handler must end +with jprobe_return() which swaps the stack and does an int3 (breakpoint). +This breakpoint handler will then put back the saved stack frame, +simulate the instruction at the beginning of the function it added +a breakpoint to, and then continue on. + +For function tracing to work, it hijakes the return address from the +stack frame, and replaces it with a hook function that will trace +the end of the call. This hook function will restore the return +address of the function call. + +If the function tracer traces the jprobe handler, the hook function +for that handler will not be called, and its saved return address +will be used for the next function. This will result in a kernel crash. + +To solve this, pause function tracing before the jprobe handler is called +and unpause it before it returns back to the function it probed. + +Some other updates: + +Used a variable "saved_sp" to hold kcb->jprobe_saved_sp. This makes the +code look a bit cleaner and easier to understand (various tries to fix +this bug required this change). + +Note, if fentry is being used, jprobes will change the ip address before +the function graph tracer runs and it will not be able to trace the +function that the jprobe is probing. + +Link: http://lkml.kernel.org/r/20150114154329.552437962@goodmis.org + +Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> +Signed-off-by: Steven Rostedt <rostedt@goodmis.org> +[lizf: Backported to 3.4: + - adjust filename + - adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/kernel/kprobes.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/arch/x86/kernel/kprobes.c ++++ b/arch/x86/kernel/kprobes.c +@@ -1003,6 +1003,15 @@ int __kprobes setjmp_pre_handler(struct + regs->flags &= ~X86_EFLAGS_IF; + trace_hardirqs_off(); + regs->ip = (unsigned long)(jp->entry); ++ ++ /* ++ * jprobes use jprobe_return() which skips the normal return ++ * path of the function, and this messes up the accounting of the ++ * function graph tracer to get messed up. ++ * ++ * Pause function graph tracing while performing the jprobe function. ++ */ ++ pause_graph_tracing(); + return 1; + } + +@@ -1028,24 +1037,25 @@ int __kprobes longjmp_break_handler(stru + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + u8 *addr = (u8 *) (regs->ip - 1); + struct jprobe *jp = container_of(p, struct jprobe, kp); ++ void *saved_sp = kcb->jprobe_saved_sp; + + if ((addr > (u8 *) jprobe_return) && + (addr < (u8 *) jprobe_return_end)) { +- if (stack_addr(regs) != kcb->jprobe_saved_sp) { ++ if (stack_addr(regs) != saved_sp) { + struct pt_regs *saved_regs = &kcb->jprobe_saved_regs; + printk(KERN_ERR + "current sp %p does not match saved sp %p\n", +- stack_addr(regs), kcb->jprobe_saved_sp); ++ stack_addr(regs), saved_sp); + printk(KERN_ERR "Saved registers for jprobe %p\n", jp); + show_registers(saved_regs); + printk(KERN_ERR "Current registers\n"); + show_registers(regs); + BUG(); + } ++ /* It's OK to start function graph tracing again */ ++ unpause_graph_tracing(); + *regs = kcb->jprobe_saved_regs; +- memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp), +- kcb->jprobes_stack, +- MIN_STACK_SIZE(kcb->jprobe_saved_sp)); ++ memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp)); + preempt_enable_no_resched(); + return 1; + } diff --git a/patches/genhd-check-for-int-overflow-in-disk_expand_part_tbl.patch b/patches/genhd-check-for-int-overflow-in-disk_expand_part_tbl.patch new file mode 100644 index 0000000..0178ae5 --- /dev/null +++ b/patches/genhd-check-for-int-overflow-in-disk_expand_part_tbl.patch @@ -0,0 +1,41 @@ +From 5fabcb4c33fe11c7e3afdf805fde26c1a54d0953 Mon Sep 17 00:00:00 2001 +From: Jens Axboe <axboe@fb.com> +Date: Wed, 19 Nov 2014 13:06:22 -0700 +Subject: genhd: check for int overflow in disk_expand_part_tbl() + +commit 5fabcb4c33fe11c7e3afdf805fde26c1a54d0953 upstream. + +We can get here from blkdev_ioctl() -> blkpg_ioctl() -> add_partition() +with a user passed in partno value. If we pass in 0x7fffffff, the +new target in disk_expand_part_tbl() overflows the 'int' and we +access beyond the end of ptbl->part[] and even write to it when we +do the rcu_assign_pointer() to assign the new partition. + +Reported-by: David Ramos <daramos@stanford.edu> +Signed-off-by: Jens Axboe <axboe@fb.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + block/genhd.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -1069,9 +1069,16 @@ int disk_expand_part_tbl(struct gendisk + struct disk_part_tbl *old_ptbl = disk->part_tbl; + struct disk_part_tbl *new_ptbl; + int len = old_ptbl ? old_ptbl->len : 0; +- int target = partno + 1; ++ int i, target; + size_t size; +- int i; ++ ++ /* ++ * check for int overflow, since we can get here from blkpg_ioctl() ++ * with a user passed 'partno'. ++ */ ++ target = partno + 1; ++ if (target < 0) ++ return -EINVAL; + + /* disk_max_parts() is zero during initialization, ignore if so */ + if (disk_max_parts(disk) && target > disk_max_parts(disk)) diff --git a/patches/genirq-prevent-proc-race-against-freeing-of-irq-descriptors.patch b/patches/genirq-prevent-proc-race-against-freeing-of-irq-descriptors.patch new file mode 100644 index 0000000..a99fe6d --- /dev/null +++ b/patches/genirq-prevent-proc-race-against-freeing-of-irq-descriptors.patch @@ -0,0 +1,235 @@ +From c291ee622165cb2c8d4e7af63fffd499354a23be Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Thu, 11 Dec 2014 23:01:41 +0100 +Subject: genirq: Prevent proc race against freeing of irq descriptors + +commit c291ee622165cb2c8d4e7af63fffd499354a23be upstream. + +Since the rework of the sparse interrupt code to actually free the +unused interrupt descriptors there exists a race between the /proc +interfaces to the irq subsystem and the code which frees the interrupt +descriptor. + +CPU0 CPU1 + show_interrupts() + desc = irq_to_desc(X); +free_desc(desc) + remove_from_radix_tree(); + kfree(desc); + raw_spinlock_irq(&desc->lock); + +/proc/interrupts is the only interface which can actively corrupt +kernel memory via the lock access. /proc/stat can only read from freed +memory. Extremly hard to trigger, but possible. + +The interfaces in /proc/irq/N/ are not affected by this because the +removal of the proc file is serialized in procfs against concurrent +readers/writers. The removal happens before the descriptor is freed. + +For architectures which have CONFIG_SPARSE_IRQ=n this is a non issue +as the descriptor is never freed. It's merely cleared out with the irq +descriptor lock held. So any concurrent proc access will either see +the old correct value or the cleared out ones. + +Protect the lookup and access to the irq descriptor in +show_interrupts() with the sparse_irq_lock. + +Provide kstat_irqs_usr() which is protecting the lookup and access +with sparse_irq_lock and switch /proc/stat to use it. + +Document the existing kstat_irqs interfaces so it's clear that the +caller needs to take care about protection. The users of these +interfaces are either not affected due to SPARSE_IRQ=n or already +protected against removal. + +Fixes: 1f5a5b87f78f "genirq: Implement a sane sparse_irq allocator" +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +[lizf: Backported to 3.4: + - define kstat_irqs() for CONFIG_GENERIC_HARDIRQS + - add ifdef/endif CONFIG_SPARSE_IRQ] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/proc/stat.c | 2 - + include/linux/kernel_stat.h | 5 ++++ + kernel/irq/internals.h | 8 ++++++ + kernel/irq/irqdesc.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ + kernel/irq/proc.c | 22 +++++++++++++++++- + 5 files changed, 87 insertions(+), 2 deletions(-) + +--- a/fs/proc/stat.c ++++ b/fs/proc/stat.c +@@ -159,7 +159,7 @@ static int show_stat(struct seq_file *p, + + /* sum again ? it could be updated? */ + for_each_irq_nr(j) +- seq_put_decimal_ull(p, ' ', kstat_irqs(j)); ++ seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j)); + + seq_printf(p, + "\nctxt %llu\n" +--- a/include/linux/kernel_stat.h ++++ b/include/linux/kernel_stat.h +@@ -104,8 +104,13 @@ static inline unsigned int kstat_irqs(un + + return sum; + } ++static inline unsigned int kstat_irqs_usr(unsigned int irq) ++{ ++ return kstat_irqs(irq); ++} + #else + extern unsigned int kstat_irqs(unsigned int irq); ++extern unsigned int kstat_irqs_usr(unsigned int irq); + #endif + + /* +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -74,6 +74,14 @@ extern void irq_percpu_disable(struct ir + extern void mask_irq(struct irq_desc *desc); + extern void unmask_irq(struct irq_desc *desc); + ++#ifdef CONFIG_SPARSE_IRQ ++extern void irq_lock_sparse(void); ++extern void irq_unlock_sparse(void); ++#else ++static inline void irq_lock_sparse(void) { } ++static inline void irq_unlock_sparse(void) { } ++#endif ++ + extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); + + irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action); +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -131,6 +131,16 @@ static void free_masks(struct irq_desc * + static inline void free_masks(struct irq_desc *desc) { } + #endif + ++void irq_lock_sparse(void) ++{ ++ mutex_lock(&sparse_irq_lock); ++} ++ ++void irq_unlock_sparse(void) ++{ ++ mutex_unlock(&sparse_irq_lock); ++} ++ + static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) + { + struct irq_desc *desc; +@@ -167,6 +177,12 @@ static void free_desc(unsigned int irq) + + unregister_irq_proc(irq, desc); + ++ /* ++ * sparse_irq_lock protects also show_interrupts() and ++ * kstat_irq_usr(). Once we deleted the descriptor from the ++ * sparse tree we can free it. Access in proc will fail to ++ * lookup the descriptor. ++ */ + mutex_lock(&sparse_irq_lock); + delete_irq_desc(irq); + mutex_unlock(&sparse_irq_lock); +@@ -489,6 +505,15 @@ void dynamic_irq_cleanup(unsigned int ir + raw_spin_unlock_irqrestore(&desc->lock, flags); + } + ++/** ++ * kstat_irqs_cpu - Get the statistics for an interrupt on a cpu ++ * @irq: The interrupt number ++ * @cpu: The cpu number ++ * ++ * Returns the sum of interrupt counts on @cpu since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -497,6 +522,14 @@ unsigned int kstat_irqs_cpu(unsigned int + *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; + } + ++/** ++ * kstat_irqs - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. The caller must ensure that the interrupt is not removed ++ * concurrently. ++ */ + unsigned int kstat_irqs(unsigned int irq) + { + struct irq_desc *desc = irq_to_desc(irq); +@@ -509,3 +542,22 @@ unsigned int kstat_irqs(unsigned int irq + sum += *per_cpu_ptr(desc->kstat_irqs, cpu); + return sum; + } ++ ++/** ++ * kstat_irqs_usr - Get the statistics for an interrupt ++ * @irq: The interrupt number ++ * ++ * Returns the sum of interrupt counts on all cpus since boot for ++ * @irq. Contrary to kstat_irqs() this can be called from any ++ * preemptible context. It's protected against concurrent removal of ++ * an interrupt descriptor when sparse irqs are enabled. ++ */ ++unsigned int kstat_irqs_usr(unsigned int irq) ++{ ++ int sum; ++ ++ irq_lock_sparse(); ++ sum = kstat_irqs(irq); ++ irq_unlock_sparse(); ++ return sum; ++} +--- a/kernel/irq/proc.c ++++ b/kernel/irq/proc.c +@@ -15,6 +15,23 @@ + + #include "internals.h" + ++/* ++ * Access rules: ++ * ++ * procfs protects read/write of /proc/irq/N/ files against a ++ * concurrent free of the interrupt descriptor. remove_proc_entry() ++ * immediately prevents new read/writes to happen and waits for ++ * already running read/write functions to complete. ++ * ++ * We remove the proc entries first and then delete the interrupt ++ * descriptor from the radix tree and free it. So it is guaranteed ++ * that irq_to_desc(N) is valid as long as the read/writes are ++ * permitted by procfs. ++ * ++ * The read from /proc/interrupts is a different problem because there ++ * is no protection. So the lookup and the access to irqdesc ++ * information must be protected by sparse_irq_lock. ++ */ + static struct proc_dir_entry *root_irq_dir; + + #ifdef CONFIG_SMP +@@ -441,9 +458,10 @@ int show_interrupts(struct seq_file *p, + seq_putc(p, '\n'); + } + ++ irq_lock_sparse(); + desc = irq_to_desc(i); + if (!desc) +- return 0; ++ goto outsparse; + + raw_spin_lock_irqsave(&desc->lock, flags); + for_each_online_cpu(j) +@@ -481,6 +499,8 @@ int show_interrupts(struct seq_file *p, + seq_putc(p, '\n'); + out: + raw_spin_unlock_irqrestore(&desc->lock, flags); ++outsparse: ++ irq_unlock_sparse(); + return 0; + } + #endif diff --git a/patches/gpio-fix-memory-and-reference-leaks-in-gpiochip_add-error-path.patch b/patches/gpio-fix-memory-and-reference-leaks-in-gpiochip_add-error-path.patch new file mode 100644 index 0000000..ab7e5bc --- /dev/null +++ b/patches/gpio-fix-memory-and-reference-leaks-in-gpiochip_add-error-path.patch @@ -0,0 +1,53 @@ +From 5539b3c938d64a60cb1fc442ac3ce9263d52de0c Mon Sep 17 00:00:00 2001 +From: Johan Hovold <johan@kernel.org> +Date: Mon, 12 Jan 2015 17:12:24 +0100 +Subject: gpio: fix memory and reference leaks in gpiochip_add error path + +commit 5539b3c938d64a60cb1fc442ac3ce9263d52de0c upstream. + +Memory allocated and references taken by of_gpiochip_add and +acpi_gpiochip_add were never released on errors in gpiochip_add (e.g. +failure to find free gpio range). + +Fixes: 391c970c0dd1 ("of/gpio: add default of_xlate function if device +has a node pointer") +Fixes: 664e3e5ac64c ("gpio / ACPI: register to ACPI events +automatically") + +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +[lizf: Backported to 3.4: + - move the call to of_gpiochip_add() into the above if condition. + - remove the call to acpi_gpiochip_remove()] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpio/gpiolib.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1081,19 +1081,18 @@ int gpiochip_add(struct gpio_chip *chip) + ? (1 << FLAG_IS_OUT) + : 0; + } +- } + +- of_gpiochip_add(chip); ++ of_gpiochip_add(chip); ++ } + + unlock: + spin_unlock_irqrestore(&gpio_lock, flags); + +- if (status) +- goto fail; +- + status = gpiochip_export(chip); +- if (status) ++ if (status) { ++ of_gpiochip_remove(chip); + goto fail; ++ } + + pr_info("gpiochip_add: registered GPIOs %d to %d on device: %s\n", + chip->base, chip->base + chip->ngpio - 1, diff --git a/patches/gpio-sysfs-fix-gpio-attribute-creation-race.patch b/patches/gpio-sysfs-fix-gpio-attribute-creation-race.patch new file mode 100644 index 0000000..90a2459 --- /dev/null +++ b/patches/gpio-sysfs-fix-gpio-attribute-creation-race.patch @@ -0,0 +1,137 @@ +From ebbeba120ab2ec6ac5f3afc1425ec6ff0b77ad6f Mon Sep 17 00:00:00 2001 +From: Johan Hovold <johan@kernel.org> +Date: Tue, 13 Jan 2015 13:00:06 +0100 +Subject: gpio: sysfs: fix gpio attribute-creation race + +commit ebbeba120ab2ec6ac5f3afc1425ec6ff0b77ad6f upstream. + +Fix attribute-creation race with userspace by using the default group +to create also the contingent gpio device attributes. + +Fixes: d8f388d8dc8d ("gpio: sysfs interface") +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +[lizf: + - adjust filename + - call gpio_to_irq() instead of gpiod_to_irq] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpio/gpiolib.c | 63 +++++++++++++++++++++++++++++++------------------ + 1 file changed, 41 insertions(+), 22 deletions(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -60,6 +60,7 @@ struct gpio_desc { + #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */ + #define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */ + #define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */ ++#define FLAG_SYSFS_DIR 10 /* show sysfs direction attribute */ + + #define ID_SHIFT 16 /* add new flags before this one */ + +@@ -545,12 +546,45 @@ static ssize_t gpio_active_low_store(str + static DEVICE_ATTR(active_low, 0644, + gpio_active_low_show, gpio_active_low_store); + ++static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr, ++ int n) ++{ ++ struct device *dev = container_of(kobj, struct device, kobj); ++ struct gpio_desc *desc = dev_get_drvdata(dev); ++ unsigned gpio = desc - gpio_desc; ++ umode_t mode = attr->mode; ++ bool show_direction = test_bit(FLAG_SYSFS_DIR, &desc->flags); ++ ++ if (attr == &dev_attr_direction.attr) { ++ if (!show_direction) ++ mode = 0; ++ } else if (attr == &dev_attr_edge.attr) { ++ if (gpio_to_irq(gpio) < 0) ++ mode = 0; ++ if (!show_direction && test_bit(FLAG_IS_OUT, &desc->flags)) ++ mode = 0; ++ } ++ ++ return mode; ++} ++ + static struct attribute *gpio_attrs[] = { ++ &dev_attr_direction.attr, ++ &dev_attr_edge.attr, + &dev_attr_value.attr, + &dev_attr_active_low.attr, + NULL, + }; +-ATTRIBUTE_GROUPS(gpio); ++ ++static const struct attribute_group gpio_group = { ++ .attrs = gpio_attrs, ++ .is_visible = gpio_is_visible, ++}; ++ ++static const struct attribute_group *gpio_groups[] = { ++ &gpio_group, ++ NULL ++}; + + /* + * /sys/class/gpio/gpiochipN/ +@@ -727,8 +761,11 @@ int gpio_export(unsigned gpio, bool dire + return -EPERM; + } + +- if (!desc->chip->direction_input || !desc->chip->direction_output) +- direction_may_change = false; ++ if (desc->chip->direction_input && desc->chip->direction_output && ++ direction_may_change) { ++ set_bit(FLAG_SYSFS_DIR, &desc->flags); ++ } ++ + spin_unlock_irqrestore(&gpio_lock, flags); + + if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) +@@ -742,27 +779,10 @@ int gpio_export(unsigned gpio, bool dire + goto fail_unlock; + } + +- if (direction_may_change) { +- status = device_create_file(dev, &dev_attr_direction); +- if (status) +- goto fail_unregister_device; +- } +- +- if (gpio_to_irq(gpio) >= 0 && (direction_may_change || +- !test_bit(FLAG_IS_OUT, &desc->flags))) { +- status = device_create_file(dev, &dev_attr_edge); +- if (status) +- goto fail_remove_attr_direction; +- } +- + set_bit(FLAG_EXPORT, &desc->flags); + mutex_unlock(&sysfs_lock); + return 0; + +-fail_remove_attr_direction: +- device_remove_file(dev, &dev_attr_direction); +-fail_unregister_device: +- device_unregister(dev); + fail_unlock: + mutex_unlock(&sysfs_lock); + pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +@@ -893,6 +913,7 @@ void gpio_unexport(unsigned gpio) + dev = class_find_device(&gpio_class, NULL, desc, match_export); + if (dev) { + gpio_setup_irq(desc, dev, 0); ++ clear_bit(FLAG_SYSFS_DIR, &desc->flags); + clear_bit(FLAG_EXPORT, &desc->flags); + } else + status = -ENODEV; +@@ -900,8 +921,6 @@ void gpio_unexport(unsigned gpio) + + mutex_unlock(&sysfs_lock); + if (dev) { +- device_remove_file(dev, &dev_attr_edge); +- device_remove_file(dev, &dev_attr_direction); + device_unregister(dev); + put_device(dev); + } diff --git a/patches/gpio-sysfs-fix-gpio-chip-device-attribute-leak.patch b/patches/gpio-sysfs-fix-gpio-chip-device-attribute-leak.patch new file mode 100644 index 0000000..6d4875c --- /dev/null +++ b/patches/gpio-sysfs-fix-gpio-chip-device-attribute-leak.patch @@ -0,0 +1,65 @@ +From 121b6a79955a3a3fd7bbb9b8cb88d5b9dad6283d Mon Sep 17 00:00:00 2001 +From: Johan Hovold <johan@kernel.org> +Date: Tue, 13 Jan 2015 13:00:04 +0100 +Subject: gpio: sysfs: fix gpio-chip device-attribute leak + +commit 121b6a79955a3a3fd7bbb9b8cb88d5b9dad6283d upstream. + +The gpio-chip device attributes were never destroyed when the device was +removed. + +Fix by using device_create_with_groups() to create the device attributes +of the chip class device. + +Note that this also fixes the attribute-creation race with userspace. + +Fixes: d8f388d8dc8d ("gpio: sysfs interface") +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +[lizf: Backported to 3.4: adjust filename] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpio/gpiolib.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -589,16 +589,13 @@ static ssize_t chip_ngpio_show(struct de + } + static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); + +-static const struct attribute *gpiochip_attrs[] = { ++static struct attribute *gpiochip_attrs[] = { + &dev_attr_base.attr, + &dev_attr_label.attr, + &dev_attr_ngpio.attr, + NULL, + }; +- +-static const struct attribute_group gpiochip_attr_group = { +- .attrs = (struct attribute **) gpiochip_attrs, +-}; ++ATTRIBUTE_GROUPS(gpiochip); + + /* + * /sys/class/gpio/export ... write-only +@@ -924,13 +921,13 @@ static int gpiochip_export(struct gpio_c + + /* use chip->base for the ID; it's already known to be unique */ + mutex_lock(&sysfs_lock); +- dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip, +- "gpiochip%d", chip->base); +- if (!IS_ERR(dev)) { +- status = sysfs_create_group(&dev->kobj, +- &gpiochip_attr_group); +- } else ++ dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0), ++ chip, gpiochip_groups, ++ "gpiochip%d", chip->base); ++ if (IS_ERR(dev)) + status = PTR_ERR(dev); ++ else ++ status = 0; + chip->exported = (status == 0); + mutex_unlock(&sysfs_lock); + diff --git a/patches/gpio-sysfs-fix-gpio-device-attribute-leak.patch b/patches/gpio-sysfs-fix-gpio-device-attribute-leak.patch new file mode 100644 index 0000000..cf9f47e --- /dev/null +++ b/patches/gpio-sysfs-fix-gpio-device-attribute-leak.patch @@ -0,0 +1,107 @@ +From 0915e6feb38de8d3601819992a5bd050201a56fa Mon Sep 17 00:00:00 2001 +From: Johan Hovold <johan@kernel.org> +Date: Tue, 13 Jan 2015 13:00:05 +0100 +Subject: gpio: sysfs: fix gpio device-attribute leak + +commit 0915e6feb38de8d3601819992a5bd050201a56fa upstream. + +The gpio device attributes were never destroyed when the gpio was +unexported (or on export failures). + +Use device_create_with_groups() to create the default device attributes +of the gpio class device. Note that this also fixes the +attribute-creation race with userspace for these attributes. + +Remove contingent attributes in export error path and on unexport. + +Fixes: d8f388d8dc8d ("gpio: sysfs interface") +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +[lizf: Backported to 3.4: + - adjust filename + - adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpio/gpiolib.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -319,7 +319,7 @@ static ssize_t gpio_value_store(struct d + return status; + } + +-static const DEVICE_ATTR(value, 0644, ++static DEVICE_ATTR(value, 0644, + gpio_value_show, gpio_value_store); + + static irqreturn_t gpio_sysfs_irq(int irq, void *priv) +@@ -542,18 +542,15 @@ static ssize_t gpio_active_low_store(str + return status ? : size; + } + +-static const DEVICE_ATTR(active_low, 0644, ++static DEVICE_ATTR(active_low, 0644, + gpio_active_low_show, gpio_active_low_store); + +-static const struct attribute *gpio_attrs[] = { ++static struct attribute *gpio_attrs[] = { + &dev_attr_value.attr, + &dev_attr_active_low.attr, + NULL, + }; +- +-static const struct attribute_group gpio_attr_group = { +- .attrs = (struct attribute **) gpio_attrs, +-}; ++ATTRIBUTE_GROUPS(gpio); + + /* + * /sys/class/gpio/gpiochipN/ +@@ -737,17 +734,14 @@ int gpio_export(unsigned gpio, bool dire + if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) + ioname = desc->chip->names[gpio - desc->chip->base]; + +- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), +- desc, ioname ? ioname : "gpio%u", gpio); ++ dev = device_create_with_groups(&gpio_class, desc->chip->dev, ++ MKDEV(0, 0), desc, gpio_groups, ++ ioname ? ioname : "gpio%u", gpio); + if (IS_ERR(dev)) { + status = PTR_ERR(dev); + goto fail_unlock; + } + +- status = sysfs_create_group(&dev->kobj, &gpio_attr_group); +- if (status) +- goto fail_unregister_device; +- + if (direction_may_change) { + status = device_create_file(dev, &dev_attr_direction); + if (status) +@@ -758,13 +752,15 @@ int gpio_export(unsigned gpio, bool dire + !test_bit(FLAG_IS_OUT, &desc->flags))) { + status = device_create_file(dev, &dev_attr_edge); + if (status) +- goto fail_unregister_device; ++ goto fail_remove_attr_direction; + } + + set_bit(FLAG_EXPORT, &desc->flags); + mutex_unlock(&sysfs_lock); + return 0; + ++fail_remove_attr_direction: ++ device_remove_file(dev, &dev_attr_direction); + fail_unregister_device: + device_unregister(dev); + fail_unlock: +@@ -904,6 +900,8 @@ void gpio_unexport(unsigned gpio) + + mutex_unlock(&sysfs_lock); + if (dev) { ++ device_remove_file(dev, &dev_attr_edge); ++ device_remove_file(dev, &dev_attr_direction); + device_unregister(dev); + put_device(dev); + } diff --git a/patches/gpiolib-refactor-gpio_export.patch b/patches/gpiolib-refactor-gpio_export.patch new file mode 100644 index 0000000..190d329 --- /dev/null +++ b/patches/gpiolib-refactor-gpio_export.patch @@ -0,0 +1,137 @@ +From fc4e2514995d9cd7f3e1a67098ce65d72acf8ec7 Mon Sep 17 00:00:00 2001 +From: Ryan Mallon <rmallon@gmail.com> +Date: Mon, 22 Oct 2012 11:39:12 +1100 +Subject: gpiolib: Refactor gpio_export + +commit fc4e2514995d9cd7f3e1a67098ce65d72acf8ec7 upstream. + +The gpio_export function uses nested if statements and the status +variable to handle the failure cases. This makes the function logic +difficult to follow. Refactor the code to abort immediately on failure +using goto. This makes the code slightly longer, but significantly +reduces the nesting and number of split lines and makes the code easier +to read. + +Signed-off-by: Ryan Mallon <rmallon@gmail.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/gpio/gpiolib.c | 83 ++++++++++++++++++++++++++----------------------- + 1 file changed, 45 insertions(+), 38 deletions(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -701,8 +701,9 @@ int gpio_export(unsigned gpio, bool dire + { + unsigned long flags; + struct gpio_desc *desc; +- int status = -EINVAL; ++ int status; + const char *ioname = NULL; ++ struct device *dev; + + /* can't export until sysfs is available ... */ + if (!gpio_class.p) { +@@ -710,59 +711,65 @@ int gpio_export(unsigned gpio, bool dire + return -ENOENT; + } + +- if (!gpio_is_valid(gpio)) +- goto done; ++ if (!gpio_is_valid(gpio)) { ++ pr_debug("%s: gpio %d is not valid\n", __func__, gpio); ++ return -EINVAL; ++ } + + mutex_lock(&sysfs_lock); + + spin_lock_irqsave(&gpio_lock, flags); + desc = &gpio_desc[gpio]; +- if (test_bit(FLAG_REQUESTED, &desc->flags) +- && !test_bit(FLAG_EXPORT, &desc->flags)) { +- status = 0; +- if (!desc->chip->direction_input +- || !desc->chip->direction_output) +- direction_may_change = false; ++ if (!test_bit(FLAG_REQUESTED, &desc->flags) || ++ test_bit(FLAG_EXPORT, &desc->flags)) { ++ spin_unlock_irqrestore(&gpio_lock, flags); ++ pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n", ++ __func__, gpio, ++ test_bit(FLAG_REQUESTED, &desc->flags), ++ test_bit(FLAG_EXPORT, &desc->flags)); ++ return -EPERM; + } ++ ++ if (!desc->chip->direction_input || !desc->chip->direction_output) ++ direction_may_change = false; + spin_unlock_irqrestore(&gpio_lock, flags); + + if (desc->chip->names && desc->chip->names[gpio - desc->chip->base]) + ioname = desc->chip->names[gpio - desc->chip->base]; + +- if (status == 0) { +- struct device *dev; ++ dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), ++ desc, ioname ? ioname : "gpio%u", gpio); ++ if (IS_ERR(dev)) { ++ status = PTR_ERR(dev); ++ goto fail_unlock; ++ } ++ ++ status = sysfs_create_group(&dev->kobj, &gpio_attr_group); ++ if (status) ++ goto fail_unregister_device; ++ ++ if (direction_may_change) { ++ status = device_create_file(dev, &dev_attr_direction); ++ if (status) ++ goto fail_unregister_device; ++ } + +- dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), +- desc, ioname ? ioname : "gpio%u", gpio); +- if (!IS_ERR(dev)) { +- status = sysfs_create_group(&dev->kobj, +- &gpio_attr_group); +- +- if (!status && direction_may_change) +- status = device_create_file(dev, +- &dev_attr_direction); +- +- if (!status && gpio_to_irq(gpio) >= 0 +- && (direction_may_change +- || !test_bit(FLAG_IS_OUT, +- &desc->flags))) +- status = device_create_file(dev, +- &dev_attr_edge); +- +- if (status != 0) +- device_unregister(dev); +- } else +- status = PTR_ERR(dev); +- if (status == 0) +- set_bit(FLAG_EXPORT, &desc->flags); ++ if (gpio_to_irq(gpio) >= 0 && (direction_may_change || ++ !test_bit(FLAG_IS_OUT, &desc->flags))) { ++ status = device_create_file(dev, &dev_attr_edge); ++ if (status) ++ goto fail_unregister_device; + } + ++ set_bit(FLAG_EXPORT, &desc->flags); + mutex_unlock(&sysfs_lock); ++ return 0; + +-done: +- if (status) +- pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); +- ++fail_unregister_device: ++ device_unregister(dev); ++fail_unlock: ++ mutex_unlock(&sysfs_lock); ++ pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); + return status; + } + EXPORT_SYMBOL_GPL(gpio_export); diff --git a/patches/hid-roccat-potential-out-of-bounds-in-pyra_sysfs_write_settings.patch b/patches/hid-roccat-potential-out-of-bounds-in-pyra_sysfs_write_settings.patch new file mode 100644 index 0000000..de78096 --- /dev/null +++ b/patches/hid-roccat-potential-out-of-bounds-in-pyra_sysfs_write_settings.patch @@ -0,0 +1,50 @@ +From 606185b20caf4c57d7e41e5a5ea4aff460aef2ab Mon Sep 17 00:00:00 2001 +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Fri, 9 Jan 2015 15:32:31 +0300 +Subject: HID: roccat: potential out of bounds in pyra_sysfs_write_settings() + +commit 606185b20caf4c57d7e41e5a5ea4aff460aef2ab upstream. + +This is a static checker fix. We write some binary settings to the +sysfs file. One of the settings is the "->startup_profile". There +isn't any checking to make sure it fits into the +pyra->profile_settings[] array in the profile_activated() function. + +I added a check to pyra_sysfs_write_settings() in both places because +I wasn't positive that the other callers were correct. + +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +[lizf: Backported to 3.4: define the variable @settings] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/hid/hid-roccat-pyra.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/hid/hid-roccat-pyra.c ++++ b/drivers/hid/hid-roccat-pyra.c +@@ -35,6 +35,8 @@ static struct class *pyra_class; + static void profile_activated(struct pyra_device *pyra, + unsigned int new_profile) + { ++ if (new_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return; + pyra->actual_profile = new_profile; + pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; + } +@@ -299,10 +301,15 @@ static ssize_t pyra_sysfs_write_settings + int retval = 0; + int difference; + struct pyra_roccat_report roccat_report; ++ struct pyra_settings const *settings; + + if (off != 0 || count != sizeof(struct pyra_settings)) + return -EINVAL; + ++ settings = (struct pyra_settings const *)buf; ++ if (settings->startup_profile >= ARRAY_SIZE(pyra->profile_settings)) ++ return -EINVAL; ++ + mutex_lock(&pyra->pyra_lock); + difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings)); + if (difference) { diff --git a/patches/hp_accel-add-support-for-hp-zbook-15.patch b/patches/hp_accel-add-support-for-hp-zbook-15.patch new file mode 100644 index 0000000..8199b81 --- /dev/null +++ b/patches/hp_accel-add-support-for-hp-zbook-15.patch @@ -0,0 +1,28 @@ +From 6583659e0f92e38079a8dd081e0a1181a0f37747 Mon Sep 17 00:00:00 2001 +From: Dominique Leuenberger <dimstar@opensuse.org> +Date: Thu, 13 Nov 2014 20:57:37 +0100 +Subject: hp_accel: Add support for HP ZBook 15 + +commit 6583659e0f92e38079a8dd081e0a1181a0f37747 upstream. + +HP ZBook 15 laptop needs a non-standard mapping (x_inverted). + +BugLink: http://bugzilla.opensuse.org/show_bug.cgi?id=905329 +Signed-off-by: Dominique Leuenberger <dimstar@opensuse.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Darren Hart <dvhart@linux.intel.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/platform/x86/hp_accel.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/x86/hp_accel.c ++++ b/drivers/platform/x86/hp_accel.c +@@ -237,6 +237,7 @@ static struct dmi_system_id lis3lv02d_dm + AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap), + AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), + AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), ++ AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted), + { NULL, } + /* Laptop models without axis info (yet): + * "NC6910" "HP Compaq 6910" diff --git a/patches/input-i8042-add-acer-aspire-7738-to-the-nomux-list.patch b/patches/input-i8042-add-acer-aspire-7738-to-the-nomux-list.patch new file mode 100644 index 0000000..2c5f8c0 --- /dev/null +++ b/patches/input-i8042-add-acer-aspire-7738-to-the-nomux-list.patch @@ -0,0 +1,33 @@ +From 9333caeaeae4f831054e0e127a6ed3948b604d3e Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Date: Thu, 8 Jan 2015 14:53:23 -0800 +Subject: Input: I8042 - add Acer Aspire 7738 to the nomux list + +commit 9333caeaeae4f831054e0e127a6ed3948b604d3e upstream. + +When KBC is in active multiplexing mode the touchpad on this laptop does +not work. + +Reported-by: Bilal Koc <koc.bilo@googlemail.com> +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -408,6 +408,13 @@ static const struct dmi_system_id __init + }, + }, + { ++ /* Acer Aspire 7738 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"), ++ }, ++ }, ++ { + /* Gericom Bellagio */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), diff --git a/patches/input-i8042-reset-keyboard-to-fix-elantech-touchpad-detection.patch b/patches/input-i8042-reset-keyboard-to-fix-elantech-touchpad-detection.patch new file mode 100644 index 0000000..011fd3f --- /dev/null +++ b/patches/input-i8042-reset-keyboard-to-fix-elantech-touchpad-detection.patch @@ -0,0 +1,121 @@ +From 148e9a711e034e06310a8c36b64957934ebe30f2 Mon Sep 17 00:00:00 2001 +From: Srihari Vijayaraghavan <linux.bug.reporting@gmail.com> +Date: Wed, 7 Jan 2015 16:25:53 -0800 +Subject: Input: i8042 - reset keyboard to fix Elantech touchpad detection +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 148e9a711e034e06310a8c36b64957934ebe30f2 upstream. + +On some laptops, keyboard needs to be reset in order to successfully detect +touchpad (e.g., some Gigabyte laptop models with Elantech touchpads). +Without resettin keyboard touchpad pretends to be completely dead. + +Based on the original patch by Mateusz JoÅ„czyk this version has been +expanded to include DMI based detection & application of the fix +automatically on the affected models of laptops. This has been confirmed to +fix problem by three users already on three different models of laptops. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=81331 +Signed-off-by: Srihari Vijayaraghavan <linux.bug.reporting@gmail.com> +Acked-by: Mateusz JoÅ„czyk <mat.jonczyk@o2.pl> +Tested-by: Srihari Vijayaraghavan <linux.bug.reporting@gmail.com> +Tested by: Zakariya Dehlawi <zdehlawi@gmail.com> +Tested-by: Guillaum Bouchard <guillaum.bouchard@gmail.com> +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + Documentation/kernel-parameters.txt | 1 + + drivers/input/serio/i8042-x86ia64io.h | 32 ++++++++++++++++++++++++++++++++ + drivers/input/serio/i8042.c | 14 ++++++++++++++ + 3 files changed, 47 insertions(+) + +--- a/Documentation/kernel-parameters.txt ++++ b/Documentation/kernel-parameters.txt +@@ -979,6 +979,7 @@ bytes respectively. Such letter suffixes + i8042.notimeout [HW] Ignore timeout condition signalled by controller + i8042.reset [HW] Reset the controller during init and cleanup + i8042.unlock [HW] Unlock (ignore) the keylock ++ i8042.kbdreset [HW] Reset device connected to KBD port + + i810= [HW,DRM] + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -721,6 +721,35 @@ static const struct dmi_system_id __init + { } + }; + ++/* ++ * Some laptops need keyboard reset before probing for the trackpad to get ++ * it detected, initialised & finally work. ++ */ ++static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { ++ { ++ /* Gigabyte P35 v2 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"), ++ }, ++ }, ++ { ++ /* Aorus branded Gigabyte X3 Plus - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "X3"), ++ }, ++ }, ++ { ++ /* Gigabyte P34 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P34"), ++ }, ++ }, ++ { } ++}; ++ + #endif /* CONFIG_X86 */ + + #ifdef CONFIG_PNP +@@ -1001,6 +1030,9 @@ static int __init i8042_platform_init(vo + if (dmi_check_system(i8042_dmi_dritek_table)) + i8042_dritek = true; + ++ if (dmi_check_system(i8042_dmi_kbdreset_table)) ++ i8042_kbdreset = true; ++ + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to +--- a/drivers/input/serio/i8042.c ++++ b/drivers/input/serio/i8042.c +@@ -67,6 +67,10 @@ static bool i8042_notimeout; + module_param_named(notimeout, i8042_notimeout, bool, 0); + MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); + ++static bool i8042_kbdreset; ++module_param_named(kbdreset, i8042_kbdreset, bool, 0); ++MODULE_PARM_DESC(kbdreset, "Reset device connected to KBD port"); ++ + #ifdef CONFIG_X86 + static bool i8042_dritek; + module_param_named(dritek, i8042_dritek, bool, 0); +@@ -783,6 +787,16 @@ static int __init i8042_check_aux(void) + return -1; + + /* ++ * Reset keyboard (needed on some laptops to successfully detect ++ * touchpad, e.g., some Gigabyte laptop models with Elantech ++ * touchpads). ++ */ ++ if (i8042_kbdreset) { ++ pr_warn("Attempting to reset device connected to KBD port\n"); ++ i8042_kbd_write(NULL, (unsigned char) 0xff); ++ } ++ ++/* + * Test AUX IRQ delivery to make sure BIOS did not grab the IRQ and + * used it for a PCI card or somethig else. + */ diff --git a/patches/iommu-vt-d-fix-an-off-by-one-bug-in-__domain_mapping.patch b/patches/iommu-vt-d-fix-an-off-by-one-bug-in-__domain_mapping.patch new file mode 100644 index 0000000..ec0bf6d --- /dev/null +++ b/patches/iommu-vt-d-fix-an-off-by-one-bug-in-__domain_mapping.patch @@ -0,0 +1,52 @@ +From cc4f14aa170d895c9a43bdb56f62070c8a6da908 Mon Sep 17 00:00:00 2001 +From: Jiang Liu <jiang.liu@linux.intel.com> +Date: Wed, 26 Nov 2014 09:42:10 +0800 +Subject: iommu/vt-d: Fix an off-by-one bug in __domain_mapping() + +commit cc4f14aa170d895c9a43bdb56f62070c8a6da908 upstream. + +There's an off-by-one bug in function __domain_mapping(), which may +trigger the BUG_ON(nr_pages < lvl_pages) when + (nr_pages + 1) & superpage_mask == 0 + +The issue was introduced by commit 9051aa0268dc "intel-iommu: Combine +domain_pfn_mapping() and domain_sg_mapping()", which sets sg_res to +"nr_pages + 1" to avoid some of the 'sg_res==0' code paths. + +It's safe to remove extra "+1" because sg_res is only used to calculate +page size now. + +Reported-And-Tested-by: Sudeep Dutt <sudeep.dutt@intel.com> +Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> +Acked-By: David Woodhouse <David.Woodhouse@intel.com> +Signed-off-by: Joerg Roedel <jroedel@suse.de> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/iommu/intel-iommu.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -1792,7 +1792,7 @@ static int __domain_mapping(struct dmar_ + struct dma_pte *first_pte = NULL, *pte = NULL; + phys_addr_t uninitialized_var(pteval); + int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; +- unsigned long sg_res; ++ unsigned long sg_res = 0; + unsigned int largepage_lvl = 0; + unsigned long lvl_pages = 0; + +@@ -1803,10 +1803,8 @@ static int __domain_mapping(struct dmar_ + + prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP; + +- if (sg) +- sg_res = 0; +- else { +- sg_res = nr_pages + 1; ++ if (!sg) { ++ sg_res = nr_pages; + pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot; + } + diff --git a/patches/ipv6-replacing-a-rt6_info-needs-to-purge-possible-propagated-rt6_infos-too.patch b/patches/ipv6-replacing-a-rt6_info-needs-to-purge-possible-propagated-rt6_infos-too.patch new file mode 100644 index 0000000..700251b --- /dev/null +++ b/patches/ipv6-replacing-a-rt6_info-needs-to-purge-possible-propagated-rt6_infos-too.patch @@ -0,0 +1,114 @@ +From 6e9e16e6143b725662e47026a1d0f270721cdd24 Mon Sep 17 00:00:00 2001 +From: Hannes Frederic Sowa <hannes@stressinduktion.org> +Date: Mon, 26 Jan 2015 15:11:17 +0100 +Subject: ipv6: replacing a rt6_info needs to purge possible propagated + rt6_infos too + +commit 6e9e16e6143b725662e47026a1d0f270721cdd24 upstream. + +Lubomir Rintel reported that during replacing a route the interface +reference counter isn't correctly decremented. + +To quote bug <https://bugzilla.kernel.org/show_bug.cgi?id=91941>: +| [root@rhel7-5 lkundrak]# sh -x lal +| + ip link add dev0 type dummy +| + ip link set dev0 up +| + ip link add dev1 type dummy +| + ip link set dev1 up +| + ip addr add 2001:db8:8086::2/64 dev dev0 +| + ip route add 2001:db8:8086::/48 dev dev0 proto static metric 20 +| + ip route add 2001:db8:8088::/48 dev dev1 proto static metric 10 +| + ip route replace 2001:db8:8086::/48 dev dev1 proto static metric 20 +| + ip link del dev0 type dummy +| Message from syslogd@rhel7-5 at Jan 23 10:54:41 ... +| kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2 +| +| Message from syslogd@rhel7-5 at Jan 23 10:54:51 ... +| kernel:unregister_netdevice: waiting for dev0 to become free. Usage count = 2 + +During replacement of a rt6_info we must walk all parent nodes and check +if the to be replaced rt6_info got propagated. If so, replace it with +an alive one. + +Fixes: 4a287eba2de3957 ("IPv6 routing, NLM_F_* flag support: REPLACE and EXCL flags support, warn about missing CREATE flag") +Reported-by: Lubomir Rintel <lkundrak@v3.sk> +Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> +Tested-by: Lubomir Rintel <lkundrak@v3.sk> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + net/ipv6/ip6_fib.c | 45 ++++++++++++++++++++++++++------------------- + 1 file changed, 26 insertions(+), 19 deletions(-) + +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -633,6 +633,29 @@ insert_above: + return ln; + } + ++static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, ++ struct net *net) ++{ ++ if (atomic_read(&rt->rt6i_ref) != 1) { ++ /* This route is used as dummy address holder in some split ++ * nodes. It is not leaked, but it still holds other resources, ++ * which must be released in time. So, scan ascendant nodes ++ * and replace dummy references to this route with references ++ * to still alive ones. ++ */ ++ while (fn) { ++ if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { ++ fn->leaf = fib6_find_prefix(net, fn); ++ atomic_inc(&fn->leaf->rt6i_ref); ++ rt6_release(rt); ++ } ++ fn = fn->parent; ++ } ++ /* No more references are possible at this point. */ ++ BUG_ON(atomic_read(&rt->rt6i_ref) != 1); ++ } ++} ++ + /* + * Insert routing information in a node. + */ +@@ -723,11 +746,12 @@ add: + rt->dst.rt6_next = iter->dst.rt6_next; + atomic_inc(&rt->rt6i_ref); + inet6_rt_notify(RTM_NEWROUTE, rt, info); +- rt6_release(iter); + if (!(fn->fn_flags & RTN_RTINFO)) { + info->nl_net->ipv6.rt6_stats->fib_route_nodes++; + fn->fn_flags |= RTN_RTINFO; + } ++ fib6_purge_rt(iter, fn, info->nl_net); ++ rt6_release(iter); + } + + return 0; +@@ -1229,24 +1253,7 @@ static void fib6_del_route(struct fib6_n + fn = fib6_repair_tree(net, fn); + } + +- if (atomic_read(&rt->rt6i_ref) != 1) { +- /* This route is used as dummy address holder in some split +- * nodes. It is not leaked, but it still holds other resources, +- * which must be released in time. So, scan ascendant nodes +- * and replace dummy references to this route with references +- * to still alive ones. +- */ +- while (fn) { +- if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { +- fn->leaf = fib6_find_prefix(net, fn); +- atomic_inc(&fn->leaf->rt6i_ref); +- rt6_release(rt); +- } +- fn = fn->parent; +- } +- /* No more references are possible at this point. */ +- BUG_ON(atomic_read(&rt->rt6i_ref) != 1); +- } ++ fib6_purge_rt(rt, fn, net); + + inet6_rt_notify(RTM_DELROUTE, rt, info); + rt6_release(rt); diff --git a/patches/iscsi-target-fail-connection-on-short-sendmsg-writes.patch b/patches/iscsi-target-fail-connection-on-short-sendmsg-writes.patch new file mode 100644 index 0000000..b50c750 --- /dev/null +++ b/patches/iscsi-target-fail-connection-on-short-sendmsg-writes.patch @@ -0,0 +1,83 @@ +From 6bf6ca7515c1df06f5c03737537f5e0eb191e29e Mon Sep 17 00:00:00 2001 +From: Nicholas Bellinger <nab@linux-iscsi.org> +Date: Thu, 20 Nov 2014 20:50:07 -0800 +Subject: iscsi-target: Fail connection on short sendmsg writes + +commit 6bf6ca7515c1df06f5c03737537f5e0eb191e29e upstream. + +This patch changes iscsit_do_tx_data() to fail on short writes +when kernel_sendmsg() returns a value different than requested +transfer length, returning -EPIPE and thus causing a connection +reset to occur. + +This avoids a potential bug in the original code where a short +write would result in kernel_sendmsg() being called again with +the original iovec base + length. + +In practice this has not been an issue because iscsit_do_tx_data() +is only used for transferring 48 byte headers + 4 byte digests, +along with seldom used control payloads from NOPIN + TEXT_RSP + +REJECT with less than 32k of data. + +So following Al's audit of iovec consumers, go ahead and fail +the connection on short writes for now, and remove the bogus +logic ahead of his proper upstream fix. + +Reported-by: Al Viro <viro@zeniv.linux.org.uk> +Cc: David S. Miller <davem@davemloft.net> +Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/target/iscsi/iscsi_target_util.c | 26 +++++++++++--------------- + 1 file changed, 11 insertions(+), 15 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_util.c ++++ b/drivers/target/iscsi/iscsi_target_util.c +@@ -1480,15 +1480,15 @@ static int iscsit_do_tx_data( + struct iscsi_conn *conn, + struct iscsi_data_count *count) + { +- int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; ++ int ret, iov_len; + struct kvec *iov_p; + struct msghdr msg; + + if (!conn || !conn->sock || !conn->conn_ops) + return -1; + +- if (data <= 0) { +- pr_err("Data length is: %d\n", data); ++ if (count->data_length <= 0) { ++ pr_err("Data length is: %d\n", count->data_length); + return -1; + } + +@@ -1497,20 +1497,16 @@ static int iscsit_do_tx_data( + iov_p = count->iov; + iov_len = count->iov_count; + +- while (total_tx < data) { +- tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, +- (data - total_tx)); +- if (tx_loop <= 0) { +- pr_debug("tx_loop: %d total_tx %d\n", +- tx_loop, total_tx); +- return tx_loop; +- } +- total_tx += tx_loop; +- pr_debug("tx_loop: %d, total_tx: %d, data: %d\n", +- tx_loop, total_tx, data); ++ ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, ++ count->data_length); ++ if (ret != count->data_length) { ++ pr_err("Unexpected ret: %d send data %d\n", ++ ret, count->data_length); ++ return -EPIPE; + } ++ pr_debug("ret: %d, sent data: %d\n", ret, count->data_length); + +- return total_tx; ++ return ret; + } + + int rx_data( diff --git a/patches/isofs-fix-infinite-looping-over-ce-entries.patch b/patches/isofs-fix-infinite-looping-over-ce-entries.patch new file mode 100644 index 0000000..e19dfe7 --- /dev/null +++ b/patches/isofs-fix-infinite-looping-over-ce-entries.patch @@ -0,0 +1,52 @@ +From f54e18f1b831c92f6512d2eedb224cd63d607d3d Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Mon, 15 Dec 2014 14:22:46 +0100 +Subject: isofs: Fix infinite looping over CE entries + +commit f54e18f1b831c92f6512d2eedb224cd63d607d3d upstream. + +Rock Ridge extensions define so called Continuation Entries (CE) which +define where is further space with Rock Ridge data. Corrupted isofs +image can contain arbitrarily long chain of these, including a one +containing loop and thus causing kernel to end in an infinite loop when +traversing these entries. + +Limit the traversal to 32 entries which should be more than enough space +to store all the Rock Ridge data. + +Reported-by: P J P <ppandit@redhat.com> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/isofs/rock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -30,6 +30,7 @@ struct rock_state { + int cont_size; + int cont_extent; + int cont_offset; ++ int cont_loops; + struct inode *inode; + }; + +@@ -73,6 +74,9 @@ static void init_rock_state(struct rock_ + rs->inode = inode; + } + ++/* Maximum number of Rock Ridge continuation entries */ ++#define RR_MAX_CE_ENTRIES 32 ++ + /* + * Returns 0 if the caller should continue scanning, 1 if the scan must end + * and -ve on error. +@@ -105,6 +109,8 @@ static int rock_continue(struct rock_sta + goto out; + } + ret = -EIO; ++ if (++rs->cont_loops >= RR_MAX_CE_ENTRIES) ++ goto out; + bh = sb_bread(rs->inode->i_sb, rs->cont_extent); + if (bh) { + memcpy(rs->buffer, bh->b_data + rs->cont_offset, diff --git a/patches/isofs-fix-unchecked-printing-of-er-records.patch b/patches/isofs-fix-unchecked-printing-of-er-records.patch new file mode 100644 index 0000000..d702b9b --- /dev/null +++ b/patches/isofs-fix-unchecked-printing-of-er-records.patch @@ -0,0 +1,30 @@ +From 4e2024624e678f0ebb916e6192bd23c1f9fdf696 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Thu, 18 Dec 2014 17:26:10 +0100 +Subject: isofs: Fix unchecked printing of ER records + +commit 4e2024624e678f0ebb916e6192bd23c1f9fdf696 upstream. + +We didn't check length of rock ridge ER records before printing them. +Thus corrupted isofs image can cause us to access and print some memory +behind the buffer with obvious consequences. + +Reported-and-tested-by: Carl Henrik Lunde <chlunde@ping.uio.no> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/isofs/rock.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/isofs/rock.c ++++ b/fs/isofs/rock.c +@@ -362,6 +362,9 @@ repeat: + rs.cont_size = isonum_733(rr->u.CE.size); + break; + case SIG('E', 'R'): ++ /* Invalid length of ER tag id? */ ++ if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len) ++ goto out; + ISOFS_SB(inode->i_sb)->s_rock = 1; + printk(KERN_DEBUG "ISO 9660 Extensions: "); + { diff --git a/patches/keys-fix-stale-key-registration-at-error-path.patch b/patches/keys-fix-stale-key-registration-at-error-path.patch new file mode 100644 index 0000000..11ded8e --- /dev/null +++ b/patches/keys-fix-stale-key-registration-at-error-path.patch @@ -0,0 +1,42 @@ +From b26bdde5bb27f3f900e25a95e33a0c476c8c2c48 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Thu, 4 Dec 2014 18:25:19 +0100 +Subject: KEYS: Fix stale key registration at error path + +commit b26bdde5bb27f3f900e25a95e33a0c476c8c2c48 upstream. + +When loading encrypted-keys module, if the last check of +aes_get_sizes() in init_encrypted() fails, the driver just returns an +error without unregistering its key type. This results in the stale +entry in the list. In addition to memory leaks, this leads to a kernel +crash when registering a new key type later. + +This patch fixes the problem by swapping the calls of aes_get_sizes() +and register_key_type(), and releasing resources properly at the error +paths. + +Bugzilla: https://bugzilla.opensuse.org/show_bug.cgi?id=908163 +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + security/keys/encrypted-keys/encrypted.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/security/keys/encrypted-keys/encrypted.c ++++ b/security/keys/encrypted-keys/encrypted.c +@@ -1016,10 +1016,13 @@ static int __init init_encrypted(void) + ret = encrypted_shash_alloc(); + if (ret < 0) + return ret; ++ ret = aes_get_sizes(); ++ if (ret < 0) ++ goto out; + ret = register_key_type(&key_type_encrypted); + if (ret < 0) + goto out; +- return aes_get_sizes(); ++ return 0; + out: + encrypted_shash_release(); + return ret; diff --git a/patches/kvm-s390-flush-cpu-on-load-control.patch b/patches/kvm-s390-flush-cpu-on-load-control.patch new file mode 100644 index 0000000..61b545a --- /dev/null +++ b/patches/kvm-s390-flush-cpu-on-load-control.patch @@ -0,0 +1,42 @@ +From 2dca485f8740208604543c3960be31a5dd3ea603 Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger <borntraeger@de.ibm.com> +Date: Fri, 31 Oct 2014 09:24:20 +0100 +Subject: KVM: s390: flush CPU on load control + +commit 2dca485f8740208604543c3960be31a5dd3ea603 upstream. + +some control register changes will flush some aspects of the CPU, e.g. +POP explicitely mentions that for CR9-CR11 "TLBs may be cleared". +Instead of trying to be clever and only flush on specific CRs, let +play safe and flush on all lctl(g) as future machines might define +new bits in CRs. Load control intercept should not happen that often. + +Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> +Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> +Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> +[lizf: Backported to 3.4: + - adjust filename + - adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/s390/kvm/intercept.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/s390/kvm/intercept.c ++++ b/arch/s390/kvm/intercept.c +@@ -58,6 +58,7 @@ static int handle_lctlg(struct kvm_vcpu + break; + reg = (reg + 1) % 16; + } while (1); ++ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); + return 0; + } + +@@ -97,6 +98,7 @@ static int handle_lctl(struct kvm_vcpu * + break; + reg = (reg + 1) % 16; + } while (1); ++ kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); + return 0; + } + diff --git a/patches/libata-allow-sata_sil24-to-opt-out-of-tag-ordered-submission.patch b/patches/libata-allow-sata_sil24-to-opt-out-of-tag-ordered-submission.patch new file mode 100644 index 0000000..8f03660 --- /dev/null +++ b/patches/libata-allow-sata_sil24-to-opt-out-of-tag-ordered-submission.patch @@ -0,0 +1,65 @@ +From 72dd299d5039a336493993dcc63413cf31d0e662 Mon Sep 17 00:00:00 2001 +From: Dan Williams <dan.j.williams@intel.com> +Date: Fri, 16 Jan 2015 15:13:02 -0800 +Subject: libata: allow sata_sil24 to opt-out of tag ordered submission + +commit 72dd299d5039a336493993dcc63413cf31d0e662 upstream. + +Ronny reports: https://bugzilla.kernel.org/show_bug.cgi?id=87101 + "Since commit 8a4aeec8d "libata/ahci: accommodate tag ordered + controllers" the access to the harddisk on the first SATA-port is + failing on its first access. The access to the harddisk on the + second port is working normal. + + When reverting the above commit, access to both harddisks is working + fine again." + +Maintain tag ordered submission as the default, but allow sata_sil24 to +continue with the old behavior. + +Cc: Tejun Heo <tj@kernel.org> +Reported-by: Ronny Hegewald <Ronny.Hegewald@online.de> +Signed-off-by: Dan Williams <dan.j.williams@intel.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/ata/libata-core.c | 5 ++++- + drivers/ata/sata_sil24.c | 2 +- + include/linux/libata.h | 1 + + 3 files changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4712,7 +4712,10 @@ static struct ata_queued_cmd *ata_qc_new + return NULL; + + for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) { +- tag = tag < max_queue ? tag : 0; ++ if (ap->flags & ATA_FLAG_LOWTAG) ++ tag = i; ++ else ++ tag = tag < max_queue ? tag : 0; + + /* the last tag is reserved for internal command. */ + if (tag == ATA_TAG_INTERNAL) +--- a/drivers/ata/sata_sil24.c ++++ b/drivers/ata/sata_sil24.c +@@ -246,7 +246,7 @@ enum { + /* host flags */ + SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | + ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA | +- ATA_FLAG_AN | ATA_FLAG_PMP, ++ ATA_FLAG_AN | ATA_FLAG_PMP | ATA_FLAG_LOWTAG, + SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ + + IRQ_STAT_4PORTS = 0xf, +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -207,6 +207,7 @@ enum { + ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity + * led */ + ATA_FLAG_NO_DIPM = (1 << 23), /* host not happy with DIPM */ ++ ATA_FLAG_LOWTAG = (1 << 24), /* host wants lowest available tag */ + + /* bits 24:31 of ap->flags are reserved for LLD specific flags */ + diff --git a/patches/libata-prevent-hsm-state-change-race-between-isr-and-pio.patch b/patches/libata-prevent-hsm-state-change-race-between-isr-and-pio.patch new file mode 100644 index 0000000..44f3635 --- /dev/null +++ b/patches/libata-prevent-hsm-state-change-race-between-isr-and-pio.patch @@ -0,0 +1,70 @@ +From ce7514526742c0898b837d4395f515b79dfb5a12 Mon Sep 17 00:00:00 2001 +From: David Jeffery <djeffery@redhat.com> +Date: Mon, 19 Jan 2015 13:03:25 -0600 +Subject: libata: prevent HSM state change race between ISR and PIO + +commit ce7514526742c0898b837d4395f515b79dfb5a12 upstream. + +It is possible for ata_sff_flush_pio_task() to set ap->hsm_task_state to +HSM_ST_IDLE in between the time __ata_sff_port_intr() checks for HSM_ST_IDLE +and before it calls ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG(). + +This problem is hard to reproduce making this patch hard to verify, but this +fix will prevent the race. + +I have not been able to reproduce the problem, but here is a crash dump from +a 2.6.32 kernel. + +On examining the ata port's state, its hsm_task_state field has a value of HSM_ST_IDLE: + +crash> struct ata_port.hsm_task_state ffff881c1121c000 + hsm_task_state = 0 + +Normally, this should not be possible as ata_sff_hsm_move() was called from ata_sff_host_intr(), +which checks hsm_task_state and won't call ata_sff_hsm_move() if it has a HSM_ST_IDLE value. + +PID: 11053 TASK: ffff8816e846cae0 CPU: 0 COMMAND: "sshd" + #0 [ffff88008ba03960] machine_kexec at ffffffff81038f3b + #1 [ffff88008ba039c0] crash_kexec at ffffffff810c5d92 + #2 [ffff88008ba03a90] oops_end at ffffffff8152b510 + #3 [ffff88008ba03ac0] die at ffffffff81010e0b + #4 [ffff88008ba03af0] do_trap at ffffffff8152ad74 + #5 [ffff88008ba03b50] do_invalid_op at ffffffff8100cf95 + #6 [ffff88008ba03bf0] invalid_op at ffffffff8100bf9b + [exception RIP: ata_sff_hsm_move+317] + RIP: ffffffff813a77ad RSP: ffff88008ba03ca0 RFLAGS: 00010097 + RAX: 0000000000000000 RBX: ffff881c1121dc60 RCX: 0000000000000000 + RDX: ffff881c1121dd10 RSI: ffff881c1121dc60 RDI: ffff881c1121c000 + RBP: ffff88008ba03d00 R8: 0000000000000000 R9: 000000000000002e + R10: 000000000001003f R11: 000000000000009b R12: ffff881c1121c000 + R13: 0000000000000000 R14: 0000000000000050 R15: ffff881c1121dd78 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + #7 [ffff88008ba03d08] ata_sff_host_intr at ffffffff813a7fbd + #8 [ffff88008ba03d38] ata_sff_interrupt at ffffffff813a821e + #9 [ffff88008ba03d78] handle_IRQ_event at ffffffff810e6ec0 +--- + drivers/ata/libata-sff.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -1333,7 +1333,19 @@ void ata_sff_flush_pio_task(struct ata_p + DPRINTK("ENTER\n"); + + cancel_delayed_work_sync(&ap->sff_pio_task); ++ ++ /* ++ * We wanna reset the HSM state to IDLE. If we do so without ++ * grabbing the port lock, critical sections protected by it which ++ * expect the HSM state to stay stable may get surprised. For ++ * example, we may set IDLE in between the time ++ * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls ++ * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG(). ++ */ ++ spin_lock_irq(ap->lock); + ap->hsm_task_state = HSM_ST_IDLE; ++ spin_unlock_irq(ap->lock); ++ + ap->sff_pio_task_link = NULL; + + if (ata_msg_ctl(ap)) diff --git a/patches/mac80211-fix-multicast-led-blinking-and-counter.patch b/patches/mac80211-fix-multicast-led-blinking-and-counter.patch new file mode 100644 index 0000000..3b5663e --- /dev/null +++ b/patches/mac80211-fix-multicast-led-blinking-and-counter.patch @@ -0,0 +1,60 @@ +From d025933e29872cb1fe19fc54d80e4dfa4ee5779c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andreas=20M=C3=BCller?= <goo@stapelspeicher.org> +Date: Fri, 12 Dec 2014 12:11:11 +0100 +Subject: mac80211: fix multicast LED blinking and counter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit d025933e29872cb1fe19fc54d80e4dfa4ee5779c upstream. + +As multicast-frames can't be fragmented, "dot11MulticastReceivedFrameCount" +stopped being incremented after the use-after-free fix. Furthermore, the +RX-LED will be triggered by every multicast frame (which wouldn't happen +before) which wouldn't allow the LED to rest at all. + +Fixes https://bugzilla.kernel.org/show_bug.cgi?id=89431 which also had the +patch. + +Fixes: b8fff407a180 ("mac80211: fix use-after-free in defragmentation") +Signed-off-by: Andreas Müller <goo@stapelspeicher.org> +[rewrite commit message] +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + net/mac80211/rx.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1486,14 +1486,14 @@ ieee80211_rx_h_defragment(struct ieee802 + sc = le16_to_cpu(hdr->seq_ctrl); + frag = sc & IEEE80211_SCTL_FRAG; + +- if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) +- goto out; +- + if (is_multicast_ether_addr(hdr->addr1)) { + rx->local->dot11MulticastReceivedFrameCount++; +- goto out; ++ goto out_no_led; + } + ++ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) ++ goto out; ++ + I802_DEBUG_INC(rx->local->rx_handlers_fragments); + + if (skb_linearize(rx->skb)) +@@ -1584,9 +1584,10 @@ ieee80211_rx_h_defragment(struct ieee802 + status->rx_flags |= IEEE80211_RX_FRAGMENTED; + + out: ++ ieee80211_led_rx(rx->local); ++ out_no_led: + if (rx->sta) + rx->sta->rx_packets++; +- ieee80211_led_rx(rx->local); + return RX_CONTINUE; + } + diff --git a/patches/megaraid_sas-corrected-return-of-wait_event-from-abort-frame-path.patch b/patches/megaraid_sas-corrected-return-of-wait_event-from-abort-frame-path.patch new file mode 100644 index 0000000..d39eba0 --- /dev/null +++ b/patches/megaraid_sas-corrected-return-of-wait_event-from-abort-frame-path.patch @@ -0,0 +1,30 @@ +From 170c238701ec38b1829321b17c70671c101bac55 Mon Sep 17 00:00:00 2001 +From: "Sumit.Saxena@avagotech.com" <Sumit.Saxena@avagotech.com> +Date: Mon, 17 Nov 2014 15:24:23 +0530 +Subject: megaraid_sas: corrected return of wait_event from abort frame path + +commit 170c238701ec38b1829321b17c70671c101bac55 upstream. + +Corrected wait_event() call which was waiting for wrong completion +status (0xFF). + +Signed-off-by: Sumit Saxena <sumit.saxena@avagotech.com> +Signed-off-by: Kashyap Desai <kashyap.desai@avagotech.com> +Reviewed-by: Tomas Henzl <thenzl@redhat.com> +Signed-off-by: Christoph Hellwig <hch@lst.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/megaraid/megaraid_sas_base.c ++++ b/drivers/scsi/megaraid/megaraid_sas_base.c +@@ -919,7 +919,7 @@ megasas_issue_blocked_abort_cmd(struct m + abort_fr->abort_mfi_phys_addr_hi = 0; + + cmd->sync_cmd = 1; +- cmd->cmd_status = 0xFF; ++ cmd->cmd_status = ENODATA; + + instance->instancet->issue_dcmd(instance, cmd); + diff --git a/patches/mfd-tc6393xb-fail-ohci-suspend-if-full-state-restore-is-required.patch b/patches/mfd-tc6393xb-fail-ohci-suspend-if-full-state-restore-is-required.patch new file mode 100644 index 0000000..05472ca --- /dev/null +++ b/patches/mfd-tc6393xb-fail-ohci-suspend-if-full-state-restore-is-required.patch @@ -0,0 +1,52 @@ +From 1a5fb99de4850cba710d91becfa2c65653048589 Mon Sep 17 00:00:00 2001 +From: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> +Date: Fri, 24 Oct 2014 21:19:57 +0400 +Subject: mfd: tc6393xb: Fail ohci suspend if full state restore is required + +commit 1a5fb99de4850cba710d91becfa2c65653048589 upstream. + +Some boards with TC6393XB chip require full state restore during system +resume thanks to chip's VCC being cut off during suspend (Sharp SL-6000 +tosa is one of them). Failing to do so would result in ohci Oops on +resume due to internal memory contentes being changed. Fail ohci suspend +on tc6393xb is full state restore is required. + +Recommended workaround is to unbind tmio-ohci driver before suspend and +rebind it after resume. + +Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> +Signed-off-by: Lee Jones <lee.jones@linaro.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/mfd/tc6393xb.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/mfd/tc6393xb.c ++++ b/drivers/mfd/tc6393xb.c +@@ -263,6 +263,17 @@ static int tc6393xb_ohci_disable(struct + return 0; + } + ++static int tc6393xb_ohci_suspend(struct platform_device *dev) ++{ ++ struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent); ++ ++ /* We can't properly store/restore OHCI state, so fail here */ ++ if (tcpd->resume_restore) ++ return -EBUSY; ++ ++ return tc6393xb_ohci_disable(dev); ++} ++ + static int tc6393xb_fb_enable(struct platform_device *dev) + { + struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent); +@@ -403,7 +414,7 @@ static struct mfd_cell __devinitdata tc6 + .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources), + .resources = tc6393xb_ohci_resources, + .enable = tc6393xb_ohci_enable, +- .suspend = tc6393xb_ohci_disable, ++ .suspend = tc6393xb_ohci_suspend, + .resume = tc6393xb_ohci_enable, + .disable = tc6393xb_ohci_disable, + }, diff --git a/patches/mm-don-t-count-the-stack-guard-page-towards-rlimit_stack.patch b/patches/mm-don-t-count-the-stack-guard-page-towards-rlimit_stack.patch new file mode 100644 index 0000000..cbbf267 --- /dev/null +++ b/patches/mm-don-t-count-the-stack-guard-page-towards-rlimit_stack.patch @@ -0,0 +1,51 @@ +From 690eac53daff34169a4d74fc7bfbd388c4896abb Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Sun, 11 Jan 2015 11:33:57 -0800 +Subject: mm: Don't count the stack guard page towards RLIMIT_STACK + +commit 690eac53daff34169a4d74fc7bfbd388c4896abb upstream. + +Commit fee7e49d4514 ("mm: propagate error from stack expansion even for +guard page") made sure that we return the error properly for stack +growth conditions. It also theorized that counting the guard page +towards the stack limit might break something, but also said "Let's see +if anybody notices". + +Somebody did notice. Apparently android-x86 sets the stack limit very +close to the limit indeed, and including the guard page in the rlimit +check causes the android 'zygote' process problems. + +So this adds the (fairly trivial) code to make the stack rlimit check be +against the actual real stack size, rather than the size of the vma that +includes the guard page. + +Reported-and-tested-by: Chih-Wei Huang <cwhuang@android-x86.org> +Cc: Jay Foad <jay.foad@gmail.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + mm/mmap.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1727,14 +1727,17 @@ static int acct_stack_growth(struct vm_a + { + struct mm_struct *mm = vma->vm_mm; + struct rlimit *rlim = current->signal->rlim; +- unsigned long new_start; ++ unsigned long new_start, actual_size; + + /* address space limit tests */ + if (!may_expand_vm(mm, grow)) + return -ENOMEM; + + /* Stack limit test */ +- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) ++ actual_size = size; ++ if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN))) ++ actual_size -= PAGE_SIZE; ++ if (actual_size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur)) + return -ENOMEM; + + /* mlock limit tests */ diff --git a/patches/mm-fix-corner-case-in-anon_vma-endless-growing-prevention.patch b/patches/mm-fix-corner-case-in-anon_vma-endless-growing-prevention.patch new file mode 100644 index 0000000..a18cb4e --- /dev/null +++ b/patches/mm-fix-corner-case-in-anon_vma-endless-growing-prevention.patch @@ -0,0 +1,59 @@ +From b800c91a0517071156e772d4fb329ad33590da62 Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov <koct9i@gmail.com> +Date: Sun, 11 Jan 2015 16:54:06 +0300 +Subject: mm: fix corner case in anon_vma endless growing prevention + +commit b800c91a0517071156e772d4fb329ad33590da62 upstream. + +Fix for BUG_ON(anon_vma->degree) splashes in unlink_anon_vmas() ("kernel +BUG at mm/rmap.c:399!") caused by commit 7a3ef208e662 ("mm: prevent +endless growth of anon_vma hierarchy") + +Anon_vma_clone() is usually called for a copy of source vma in +destination argument. If source vma has anon_vma it should be already +in dst->anon_vma. NULL in dst->anon_vma is used as a sign that it's +called from anon_vma_fork(). In this case anon_vma_clone() finds +anon_vma for reusing. + +Vma_adjust() calls it differently and this breaks anon_vma reusing +logic: anon_vma_clone() links vma to old anon_vma and updates degree +counters but vma_adjust() overrides vma->anon_vma right after that. As +a result final unlink_anon_vmas() decrements degree for wrong anon_vma. + +This patch assigns ->anon_vma before calling anon_vma_clone(). + +Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com> +Reported-and-tested-by: Chris Clayton <chris2553@googlemail.com> +Reported-and-tested-by: Oded Gabbay <oded.gabbay@amd.com> +Reported-and-tested-by: Chih-Wei Huang <cwhuang@android-x86.org> +Acked-by: Rik van Riel <riel@redhat.com> +Acked-by: Vlastimil Babka <vbabka@suse.cz> +Cc: Daniel Forrest <dan.forrest@ssec.wisc.edu> +Cc: Michal Hocko <mhocko@suse.cz> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[lizf: Backported to 3.4: define variable @error and return this instead + of returning -ENOMEM] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + mm/mmap.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -567,9 +567,14 @@ again: remove_next = 1 + (end > next-> + * shrinking vma had, to cover any anon pages imported. + */ + if (exporter && exporter->anon_vma && !importer->anon_vma) { +- if (anon_vma_clone(importer, exporter)) +- return -ENOMEM; ++ int error; ++ + importer->anon_vma = exporter->anon_vma; ++ error = anon_vma_clone(importer, exporter); ++ if (error) { ++ importer->anon_vma = NULL; ++ return error; ++ } + } + } + diff --git a/patches/mm-prevent-endless-growth-of-anon_vma-hierarchy.patch b/patches/mm-prevent-endless-growth-of-anon_vma-hierarchy.patch new file mode 100644 index 0000000..8d91d91 --- /dev/null +++ b/patches/mm-prevent-endless-growth-of-anon_vma-hierarchy.patch @@ -0,0 +1,180 @@ +From 7a3ef208e662f4b63d43a23f61a64a129c525bbc Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov <koct9i@gmail.com> +Date: Thu, 8 Jan 2015 14:32:15 -0800 +Subject: mm: prevent endless growth of anon_vma hierarchy + +commit 7a3ef208e662f4b63d43a23f61a64a129c525bbc upstream. + +Constantly forking task causes unlimited grow of anon_vma chain. Each +next child allocates new level of anon_vmas and links vma to all +previous levels because pages might be inherited from any level. + +This patch adds heuristic which decides to reuse existing anon_vma +instead of forking new one. It adds counter anon_vma->degree which +counts linked vmas and directly descending anon_vmas and reuses anon_vma +if counter is lower than two. As a result each anon_vma has either vma +or at least two descending anon_vmas. In such trees half of nodes are +leafs with alive vmas, thus count of anon_vmas is no more than two times +bigger than count of vmas. + +This heuristic reuses anon_vmas as few as possible because each reuse +adds false aliasing among vmas and rmap walker ought to scan more ptes +when it searches where page is might be mapped. + +Link: http://lkml.kernel.org/r/20120816024610.GA5350@evergreen.ssec.wisc.edu +Fixes: 5beb49305251 ("mm: change anon_vma linking to fix multi-process server scalability issue") +[akpm@linux-foundation.org: fix typo, per Rik] +Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com> +Reported-by: Daniel Forrest <dan.forrest@ssec.wisc.edu> +Tested-by: Michal Hocko <mhocko@suse.cz> +Tested-by: Jerome Marchand <jmarchan@redhat.com> +Reviewed-by: Michal Hocko <mhocko@suse.cz> +Reviewed-by: Rik van Riel <riel@redhat.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + include/linux/rmap.h | 10 ++++++++++ + mm/rmap.c | 42 +++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 51 insertions(+), 1 deletion(-) + +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -72,6 +72,8 @@ static inline struct anon_vma *anon_vma_ + anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL); + if (anon_vma) { + atomic_set(&anon_vma->refcount, 1); ++ anon_vma->degree = 1; /* Reference for first vma */ ++ anon_vma->parent = anon_vma; + /* + * Initialise the anon_vma root to point to itself. If called + * from fork, the root will be reset to the parents anon_vma. +@@ -193,6 +195,8 @@ int anon_vma_prepare(struct vm_area_stru + if (likely(!vma->anon_vma)) { + vma->anon_vma = anon_vma; + anon_vma_chain_link(vma, avc, anon_vma); ++ /* vma reference or self-parent link for new root */ ++ anon_vma->degree++; + allocated = NULL; + avc = NULL; + } +@@ -241,6 +245,14 @@ static inline void unlock_anon_vma_root( + /* + * Attach the anon_vmas from src to dst. + * Returns 0 on success, -ENOMEM on failure. ++ * ++ * If dst->anon_vma is NULL this function tries to find and reuse existing ++ * anon_vma which has no vmas and only one child anon_vma. This prevents ++ * degradation of anon_vma hierarchy to endless linear chain in case of ++ * constantly forking task. On the other hand, an anon_vma with more than one ++ * child isn't reused even if there was no alive vma, thus rmap walker has a ++ * good chance of avoiding scanning the whole hierarchy when it searches where ++ * page is mapped. + */ + int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) + { +@@ -261,7 +273,21 @@ int anon_vma_clone(struct vm_area_struct + anon_vma = pavc->anon_vma; + root = lock_anon_vma_root(root, anon_vma); + anon_vma_chain_link(dst, avc, anon_vma); ++ ++ /* ++ * Reuse existing anon_vma if its degree lower than two, ++ * that means it has no vma and only one anon_vma child. ++ * ++ * Do not chose parent anon_vma, otherwise first child ++ * will always reuse it. Root anon_vma is never reused: ++ * it has self-parent reference and at least one child. ++ */ ++ if (!dst->anon_vma && anon_vma != src->anon_vma && ++ anon_vma->degree < 2) ++ dst->anon_vma = anon_vma; + } ++ if (dst->anon_vma) ++ dst->anon_vma->degree++; + unlock_anon_vma_root(root); + return 0; + +@@ -329,6 +355,9 @@ int anon_vma_fork(struct vm_area_struct + if (!pvma->anon_vma) + return 0; + ++ /* Drop inherited anon_vma, we'll reuse existing or allocate new. */ ++ vma->anon_vma = NULL; ++ + /* + * First, attach the new VMA to the parent VMA's anon_vmas, + * so rmap can find non-COWed pages in child processes. +@@ -336,6 +365,10 @@ int anon_vma_fork(struct vm_area_struct + if (anon_vma_clone(vma, pvma)) + return -ENOMEM; + ++ /* An existing anon_vma has been reused, all done then. */ ++ if (vma->anon_vma) ++ return 0; ++ + /* Then add our own anon_vma. */ + anon_vma = anon_vma_alloc(); + if (!anon_vma) +@@ -349,6 +382,7 @@ int anon_vma_fork(struct vm_area_struct + * lock any of the anon_vmas in this anon_vma tree. + */ + anon_vma->root = pvma->anon_vma->root; ++ anon_vma->parent = pvma->anon_vma; + /* + * With refcounts, an anon_vma can stay around longer than the + * process it belongs to. The root anon_vma needs to be pinned until +@@ -359,6 +393,7 @@ int anon_vma_fork(struct vm_area_struct + vma->anon_vma = anon_vma; + anon_vma_lock(anon_vma); + anon_vma_chain_link(vma, avc, anon_vma); ++ anon_vma->parent->degree++; + anon_vma_unlock(anon_vma); + + return 0; +@@ -389,12 +424,16 @@ void unlink_anon_vmas(struct vm_area_str + * Leave empty anon_vmas on the list - we'll need + * to free them outside the lock. + */ +- if (list_empty(&anon_vma->head)) ++ if (list_empty(&anon_vma->head)) { ++ anon_vma->parent->degree--; + continue; ++ } + + list_del(&avc->same_vma); + anon_vma_chain_free(avc); + } ++ if (vma->anon_vma) ++ vma->anon_vma->degree--; + unlock_anon_vma_root(root); + + /* +@@ -405,6 +444,7 @@ void unlink_anon_vmas(struct vm_area_str + list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma = avc->anon_vma; + ++ BUG_ON(anon_vma->degree); + put_anon_vma(anon_vma); + + list_del(&avc->same_vma); +--- a/include/linux/rmap.h ++++ b/include/linux/rmap.h +@@ -37,6 +37,16 @@ struct anon_vma { + atomic_t refcount; + + /* ++ * Count of child anon_vmas and VMAs which points to this anon_vma. ++ * ++ * This counter is used for making decision about reusing anon_vma ++ * instead of forking new one. See comments in function anon_vma_clone. ++ */ ++ unsigned degree; ++ ++ struct anon_vma *parent; /* Parent of this anon_vma */ ++ ++ /* + * NOTE: the LSB of the head.next is set by + * mm_take_all_locks() _after_ taking the above lock. So the + * head must only be read/written after taking the above lock diff --git a/patches/mm-propagate-error-from-stack-expansion-even-for-guard-page.patch b/patches/mm-propagate-error-from-stack-expansion-even-for-guard-page.patch new file mode 100644 index 0000000..3ba9b5f --- /dev/null +++ b/patches/mm-propagate-error-from-stack-expansion-even-for-guard-page.patch @@ -0,0 +1,67 @@ +From fee7e49d45149fba60156f5b59014f764d3e3728 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Tue, 6 Jan 2015 13:00:05 -0800 +Subject: mm: propagate error from stack expansion even for guard page + +commit fee7e49d45149fba60156f5b59014f764d3e3728 upstream. + +Jay Foad reports that the address sanitizer test (asan) sometimes gets +confused by a stack pointer that ends up being outside the stack vma +that is reported by /proc/maps. + +This happens due to an interaction between RLIMIT_STACK and the guard +page: when we do the guard page check, we ignore the potential error +from the stack expansion, which effectively results in a missing guard +page, since the expected stack expansion won't have been done. + +And since /proc/maps explicitly ignores the guard page (commit +d7824370e263: "mm: fix up some user-visible effects of the stack guard +page"), the stack pointer ends up being outside the reported stack area. + +This is the minimal patch: it just propagates the error. It also +effectively makes the guard page part of the stack limit, which in turn +measn that the actual real stack is one page less than the stack limit. + +Let's see if anybody notices. We could teach acct_stack_growth() to +allow an extra page for a grow-up/grow-down stack in the rlimit test, +but I don't want to add more complexity if it isn't needed. + +Reported-and-tested-by: Jay Foad <jay.foad@gmail.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + include/linux/mm.h | 2 +- + mm/memory.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1456,7 +1456,7 @@ extern int expand_downwards(struct vm_ar + #if VM_GROWSUP + extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); + #else +- #define expand_upwards(vma, address) do { } while (0) ++ #define expand_upwards(vma, address) (0) + #endif + + /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3137,7 +3137,7 @@ static inline int check_stack_guard_page + if (prev && prev->vm_end == address) + return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; + +- expand_downwards(vma, address - PAGE_SIZE); ++ return expand_downwards(vma, address - PAGE_SIZE); + } + if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { + struct vm_area_struct *next = vma->vm_next; +@@ -3146,7 +3146,7 @@ static inline int check_stack_guard_page + if (next && next->vm_start == address + PAGE_SIZE) + return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; + +- expand_upwards(vma, address + PAGE_SIZE); ++ return expand_upwards(vma, address + PAGE_SIZE); + } + return 0; + } diff --git a/patches/mm-protect-set_page_dirty-from-ongoing-truncation.patch b/patches/mm-protect-set_page_dirty-from-ongoing-truncation.patch new file mode 100644 index 0000000..52b6f9e --- /dev/null +++ b/patches/mm-protect-set_page_dirty-from-ongoing-truncation.patch @@ -0,0 +1,176 @@ +From 2d6d7f98284648c5ed113fe22a132148950b140f Mon Sep 17 00:00:00 2001 +From: Johannes Weiner <hannes@cmpxchg.org> +Date: Thu, 8 Jan 2015 14:32:18 -0800 +Subject: mm: protect set_page_dirty() from ongoing truncation + +commit 2d6d7f98284648c5ed113fe22a132148950b140f upstream. + +Tejun, while reviewing the code, spotted the following race condition +between the dirtying and truncation of a page: + +__set_page_dirty_nobuffers() __delete_from_page_cache() + if (TestSetPageDirty(page)) + page->mapping = NULL + if (PageDirty()) + dec_zone_page_state(page, NR_FILE_DIRTY); + dec_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); + if (page->mapping) + account_page_dirtied(page) + __inc_zone_page_state(page, NR_FILE_DIRTY); + __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); + +which results in an imbalance of NR_FILE_DIRTY and BDI_RECLAIMABLE. + +Dirtiers usually lock out truncation, either by holding the page lock +directly, or in case of zap_pte_range(), by pinning the mapcount with +the page table lock held. The notable exception to this rule, though, +is do_wp_page(), for which this race exists. However, do_wp_page() +already waits for a locked page to unlock before setting the dirty bit, +in order to prevent a race where clear_page_dirty() misses the page bit +in the presence of dirty ptes. Upgrade that wait to a fully locked +set_page_dirty() to also cover the situation explained above. + +Afterwards, the code in set_page_dirty() dealing with a truncation race +is no longer needed. Remove it. + +Reported-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[lizf: Backported to 3.4: + - adjust context + - use VM_BUG_ON() instead of VM_BUG_ON_PAGE()] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + include/linux/writeback.h | 1 - + mm/memory.c | 27 +++++++++++++++++---------- + mm/page-writeback.c | 43 ++++++++++++------------------------------- + 3 files changed, 29 insertions(+), 42 deletions(-) + +--- a/include/linux/writeback.h ++++ b/include/linux/writeback.h +@@ -186,7 +186,6 @@ int write_cache_pages(struct address_spa + struct writeback_control *wbc, writepage_t writepage, + void *data); + int do_writepages(struct address_space *mapping, struct writeback_control *wbc); +-void set_page_dirty_balance(struct page *page, int page_mkwrite); + void writeback_set_ratelimit(void); + void tag_pages_for_writeback(struct address_space *mapping, + pgoff_t start, pgoff_t end); +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2681,18 +2681,25 @@ reuse: + if (!dirty_page) + return ret; + +- /* +- * Yes, Virginia, this is actually required to prevent a race +- * with clear_page_dirty_for_io() from clearing the page dirty +- * bit after it clear all dirty ptes, but before a racing +- * do_wp_page installs a dirty pte. +- * +- * __do_fault is protected similarly. +- */ + if (!page_mkwrite) { +- wait_on_page_locked(dirty_page); +- set_page_dirty_balance(dirty_page, page_mkwrite); ++ struct address_space *mapping; ++ int dirtied; ++ ++ lock_page(dirty_page); ++ dirtied = set_page_dirty(dirty_page); ++ VM_BUG_ON(dirty_page); ++ mapping = dirty_page->mapping; ++ unlock_page(dirty_page); ++ ++ if (dirtied && mapping) { ++ /* ++ * Some device drivers do not set page.mapping ++ * but still dirty their pages ++ */ ++ balance_dirty_pages_ratelimited(mapping); ++ } + } ++ + put_page(dirty_page); + if (page_mkwrite) { + struct address_space *mapping = dirty_page->mapping; +--- a/mm/page-writeback.c ++++ b/mm/page-writeback.c +@@ -1394,16 +1394,6 @@ pause: + bdi_start_background_writeback(bdi); + } + +-void set_page_dirty_balance(struct page *page, int page_mkwrite) +-{ +- if (set_page_dirty(page) || page_mkwrite) { +- struct address_space *mapping = page_mapping(page); +- +- if (mapping) +- balance_dirty_pages_ratelimited(mapping); +- } +-} +- + static DEFINE_PER_CPU(int, bdp_ratelimits); + + /* +@@ -1981,32 +1971,25 @@ EXPORT_SYMBOL(account_page_writeback); + * page dirty in that case, but not all the buffers. This is a "bottom-up" + * dirtying, whereas __set_page_dirty_buffers() is a "top-down" dirtying. + * +- * Most callers have locked the page, which pins the address_space in memory. +- * But zap_pte_range() does not lock the page, however in that case the +- * mapping is pinned by the vma's ->vm_file reference. +- * +- * We take care to handle the case where the page was truncated from the +- * mapping by re-checking page_mapping() inside tree_lock. ++ * The caller must ensure this doesn't race with truncation. Most will simply ++ * hold the page lock, but e.g. zap_pte_range() calls with the page mapped and ++ * the pte lock held, which also locks out truncat + */ + int __set_page_dirty_nobuffers(struct page *page) + { + if (!TestSetPageDirty(page)) { + struct address_space *mapping = page_mapping(page); +- struct address_space *mapping2; + unsigned long flags; + + if (!mapping) + return 1; + + spin_lock_irqsave(&mapping->tree_lock, flags); +- mapping2 = page_mapping(page); +- if (mapping2) { /* Race with truncate? */ +- BUG_ON(mapping2 != mapping); +- WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page)); +- account_page_dirtied(page, mapping); +- radix_tree_tag_set(&mapping->page_tree, +- page_index(page), PAGECACHE_TAG_DIRTY); +- } ++ BUG_ON(page_mapping(page) != mapping); ++ WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page)); ++ account_page_dirtied(page, mapping); ++ radix_tree_tag_set(&mapping->page_tree, page_index(page), ++ PAGECACHE_TAG_DIRTY); + spin_unlock_irqrestore(&mapping->tree_lock, flags); + if (mapping->host) { + /* !PageAnon && !swapper_space */ +@@ -2163,12 +2146,10 @@ int clear_page_dirty_for_io(struct page + /* + * We carefully synchronise fault handlers against + * installing a dirty pte and marking the page dirty +- * at this point. We do this by having them hold the +- * page lock at some point after installing their +- * pte, but before marking the page dirty. +- * Pages are always locked coming in here, so we get +- * the desired exclusion. See mm/memory.c:do_wp_page() +- * for more comments. ++ * at this point. We do this by having them hold the ++ * page lock while dirtying the page, and pages are ++ * always locked coming in here, so we get the desired ++ * exclusion. + */ + if (TestClearPageDirty(page)) { + dec_zone_page_state(page, NR_FILE_DIRTY); diff --git a/patches/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch b/patches/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch new file mode 100644 index 0000000..e2006e8 --- /dev/null +++ b/patches/ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch @@ -0,0 +1,36 @@ +From a682e9c28cac152e6e54c39efcf046e0c8cfcf63 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Wed, 10 Dec 2014 15:52:22 -0800 +Subject: ncpfs: return proper error from NCP_IOC_SETROOT ioctl + +commit a682e9c28cac152e6e54c39efcf046e0c8cfcf63 upstream. + +If some error happens in NCP_IOC_SETROOT ioctl, the appropriate error +return value is then (in most cases) just overwritten before we return. +This can result in reporting success to userspace although error happened. + +This bug was introduced by commit 2e54eb96e2c8 ("BKL: Remove BKL from +ncpfs"). Propagate the errors correctly. + +Coverity id: 1226925. + +Fixes: 2e54eb96e2c80 ("BKL: Remove BKL from ncpfs") +Signed-off-by: Jan Kara <jack@suse.cz> +Cc: Petr Vandrovec <petr@vandrovec.name> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/ncpfs/ioctl.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/ncpfs/ioctl.c ++++ b/fs/ncpfs/ioctl.c +@@ -445,7 +445,6 @@ static long __ncp_ioctl(struct inode *in + result = -EIO; + } + } +- result = 0; + } + mutex_unlock(&server->root_setup_lock); + diff --git a/patches/net-fix-stacked-vlan-offload-features-computation.patch b/patches/net-fix-stacked-vlan-offload-features-computation.patch new file mode 100644 index 0000000..9727aa4 --- /dev/null +++ b/patches/net-fix-stacked-vlan-offload-features-computation.patch @@ -0,0 +1,43 @@ +From 796f2da81bead71ffc91ef70912cd8d1827bf756 Mon Sep 17 00:00:00 2001 +From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> +Date: Mon, 22 Dec 2014 19:04:14 +0900 +Subject: net: Fix stacked vlan offload features computation + +commit 796f2da81bead71ffc91ef70912cd8d1827bf756 upstream. + +When vlan tags are stacked, it is very likely that the outer tag is stored +in skb->vlan_tci and skb->protocol shows the inner tag's vlan_proto. +Currently netif_skb_features() first looks at skb->protocol even if there +is the outer tag in vlan_tci, thus it incorrectly retrieves the protocol +encapsulated by the inner vlan instead of the inner vlan protocol. +This allows GSO packets to be passed to HW and they end up being +corrupted. + +Fixes: 58e998c6d239 ("offloading: Force software GSO for multiple vlan tags.") +Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> +Signed-off-by: David S. Miller <davem@davemloft.net> +[lizf: Backported to 3.4: + - remove ETH_P_8021AD + - pass protocol to harmonize_features()] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + net/core/dev.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2149,6 +2149,14 @@ netdev_features_t netif_skb_features(str + } else if (!vlan_tx_tag_present(skb)) { + return harmonize_features(skb, protocol, features); + } ++ if (!vlan_tx_tag_present(skb)) { ++ if (unlikely(protocol == htons(ETH_P_8021Q))) { ++ struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; ++ protocol = veh->h_vlan_encapsulated_proto; ++ } else { ++ return harmonize_features(skb, protocol, features); ++ } ++ } + + features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_TX); + diff --git a/patches/net-sctp-fix-slab-corruption-from-use-after-free-on-init-collisions.patch b/patches/net-sctp-fix-slab-corruption-from-use-after-free-on-init-collisions.patch new file mode 100644 index 0000000..36d70b1 --- /dev/null +++ b/patches/net-sctp-fix-slab-corruption-from-use-after-free-on-init-collisions.patch @@ -0,0 +1,129 @@ +From 600ddd6825543962fb807884169e57b580dba208 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann <dborkman@redhat.com> +Date: Thu, 22 Jan 2015 18:26:54 +0100 +Subject: net: sctp: fix slab corruption from use after free on INIT collisions + +commit 600ddd6825543962fb807884169e57b580dba208 upstream. + +When hitting an INIT collision case during the 4WHS with AUTH enabled, as +already described in detail in commit 1be9a950c646 ("net: sctp: inherit +auth_capable on INIT collisions"), it can happen that we occasionally +still remotely trigger the following panic on server side which seems to +have been uncovered after the fix from commit 1be9a950c646 ... + +[ 533.876389] BUG: unable to handle kernel paging request at 00000000ffffffff +[ 533.913657] IP: [<ffffffff811ac385>] __kmalloc+0x95/0x230 +[ 533.940559] PGD 5030f2067 PUD 0 +[ 533.957104] Oops: 0000 [#1] SMP +[ 533.974283] Modules linked in: sctp mlx4_en [...] +[ 534.939704] Call Trace: +[ 534.951833] [<ffffffff81294e30>] ? crypto_init_shash_ops+0x60/0xf0 +[ 534.984213] [<ffffffff81294e30>] crypto_init_shash_ops+0x60/0xf0 +[ 535.015025] [<ffffffff8128c8ed>] __crypto_alloc_tfm+0x6d/0x170 +[ 535.045661] [<ffffffff8128d12c>] crypto_alloc_base+0x4c/0xb0 +[ 535.074593] [<ffffffff8160bd42>] ? _raw_spin_lock_bh+0x12/0x50 +[ 535.105239] [<ffffffffa0418c11>] sctp_inet_listen+0x161/0x1e0 [sctp] +[ 535.138606] [<ffffffff814e43bd>] SyS_listen+0x9d/0xb0 +[ 535.166848] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b + +... or depending on the the application, for example this one: + +[ 1370.026490] BUG: unable to handle kernel paging request at 00000000ffffffff +[ 1370.026506] IP: [<ffffffff811ab455>] kmem_cache_alloc+0x75/0x1d0 +[ 1370.054568] PGD 633c94067 PUD 0 +[ 1370.070446] Oops: 0000 [#1] SMP +[ 1370.085010] Modules linked in: sctp kvm_amd kvm [...] +[ 1370.963431] Call Trace: +[ 1370.974632] [<ffffffff8120f7cf>] ? SyS_epoll_ctl+0x53f/0x960 +[ 1371.000863] [<ffffffff8120f7cf>] SyS_epoll_ctl+0x53f/0x960 +[ 1371.027154] [<ffffffff812100d3>] ? anon_inode_getfile+0xd3/0x170 +[ 1371.054679] [<ffffffff811e3d67>] ? __alloc_fd+0xa7/0x130 +[ 1371.080183] [<ffffffff816149a9>] system_call_fastpath+0x16/0x1b + +With slab debugging enabled, we can see that the poison has been overwritten: + +[ 669.826368] BUG kmalloc-128 (Tainted: G W ): Poison overwritten +[ 669.826385] INFO: 0xffff880228b32e50-0xffff880228b32e50. First byte 0x6a instead of 0x6b +[ 669.826414] INFO: Allocated in sctp_auth_create_key+0x23/0x50 [sctp] age=3 cpu=0 pid=18494 +[ 669.826424] __slab_alloc+0x4bf/0x566 +[ 669.826433] __kmalloc+0x280/0x310 +[ 669.826453] sctp_auth_create_key+0x23/0x50 [sctp] +[ 669.826471] sctp_auth_asoc_create_secret+0xcb/0x1e0 [sctp] +[ 669.826488] sctp_auth_asoc_init_active_key+0x68/0xa0 [sctp] +[ 669.826505] sctp_do_sm+0x29d/0x17c0 [sctp] [...] +[ 669.826629] INFO: Freed in kzfree+0x31/0x40 age=1 cpu=0 pid=18494 +[ 669.826635] __slab_free+0x39/0x2a8 +[ 669.826643] kfree+0x1d6/0x230 +[ 669.826650] kzfree+0x31/0x40 +[ 669.826666] sctp_auth_key_put+0x19/0x20 [sctp] +[ 669.826681] sctp_assoc_update+0x1ee/0x2d0 [sctp] +[ 669.826695] sctp_do_sm+0x674/0x17c0 [sctp] + +Since this only triggers in some collision-cases with AUTH, the problem at +heart is that sctp_auth_key_put() on asoc->asoc_shared_key is called twice +when having refcnt 1, once directly in sctp_assoc_update() and yet again +from within sctp_auth_asoc_init_active_key() via sctp_assoc_update() on +the already kzfree'd memory, which is also consistent with the observation +of the poison decrease from 0x6b to 0x6a (note: the overwrite is detected +at a later point in time when poison is checked on new allocation). + +Reference counting of auth keys revisited: + +Shared keys for AUTH chunks are being stored in endpoints and associations +in endpoint_shared_keys list. On endpoint creation, a null key is being +added; on association creation, all endpoint shared keys are being cached +and thus cloned over to the association. struct sctp_shared_key only holds +a pointer to the actual key bytes, that is, struct sctp_auth_bytes which +keeps track of users internally through refcounting. Naturally, on assoc +or enpoint destruction, sctp_shared_key are being destroyed directly and +the reference on sctp_auth_bytes dropped. + +User space can add keys to either list via setsockopt(2) through struct +sctp_authkey and by passing that to sctp_auth_set_key() which replaces or +adds a new auth key. There, sctp_auth_create_key() creates a new sctp_auth_bytes +with refcount 1 and in case of replacement drops the reference on the old +sctp_auth_bytes. A key can be set active from user space through setsockopt() +on the id via sctp_auth_set_active_key(), which iterates through either +endpoint_shared_keys and in case of an assoc, invokes (one of various places) +sctp_auth_asoc_init_active_key(). + +sctp_auth_asoc_init_active_key() computes the actual secret from local's +and peer's random, hmac and shared key parameters and returns a new key +directly as sctp_auth_bytes, that is asoc->asoc_shared_key, plus drops +the reference if there was a previous one. The secret, which where we +eventually double drop the ref comes from sctp_auth_asoc_set_secret() with +intitial refcount of 1, which also stays unchanged eventually in +sctp_assoc_update(). This key is later being used for crypto layer to +set the key for the hash in crypto_hash_setkey() from sctp_auth_calculate_hmac(). + +To close the loop: asoc->asoc_shared_key is freshly allocated secret +material and independant of the sctp_shared_key management keeping track +of only shared keys in endpoints and assocs. Hence, also commit 4184b2a79a76 +("net: sctp: fix memory leak in auth key management") is independant of +this bug here since it concerns a different layer (though same structures +being used eventually). asoc->asoc_shared_key is reference dropped correctly +on assoc destruction in sctp_association_free() and when active keys are +being replaced in sctp_auth_asoc_init_active_key(), it always has a refcount +of 1. Hence, it's freed prematurely in sctp_assoc_update(). Simple fix is +to remove that sctp_auth_key_put() from there which fixes these panics. + +Fixes: 730fc3d05cd4 ("[SCTP]: Implete SCTP-AUTH parameter processing") +Signed-off-by: Daniel Borkmann <dborkman@redhat.com> +Acked-by: Vlad Yasevich <vyasevich@gmail.com> +Acked-by: Neil Horman <nhorman@tuxdriver.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + net/sctp/associola.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1272,7 +1272,6 @@ void sctp_assoc_update(struct sctp_assoc + asoc->peer.peer_hmacs = new->peer.peer_hmacs; + new->peer.peer_hmacs = NULL; + +- sctp_auth_key_put(asoc->asoc_shared_key); + sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); + } + diff --git a/patches/nl80211-fix-per-station-group-key-get-del-and-memory-leak.patch b/patches/nl80211-fix-per-station-group-key-get-del-and-memory-leak.patch new file mode 100644 index 0000000..60c7c5e --- /dev/null +++ b/patches/nl80211-fix-per-station-group-key-get-del-and-memory-leak.patch @@ -0,0 +1,57 @@ +From 0fa7b39131576dd1baa6ca17fca53c65d7f62249 Mon Sep 17 00:00:00 2001 +From: Johannes Berg <johannes.berg@intel.com> +Date: Fri, 23 Jan 2015 11:10:12 +0100 +Subject: nl80211: fix per-station group key get/del and memory leak + +commit 0fa7b39131576dd1baa6ca17fca53c65d7f62249 upstream. + +In case userspace attempts to obtain key information for or delete a +unicast key, this is currently erroneously rejected unless the driver +sets the WIPHY_FLAG_IBSS_RSN flag. Apparently enough drivers do so it +was never noticed. + +Fix that, and while at it fix a potential memory leak: the error path +in the get_key() function was placed after allocating a message but +didn't free it - move it to a better place. Luckily admin permissions +are needed to call this operation. + +Fixes: e31b82136d1ad ("cfg80211/mac80211: allow per-station GTKs") +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + net/wireless/nl80211.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -1868,6 +1868,9 @@ static int nl80211_get_key(struct sk_buf + if (!rdev->ops->get_key) + return -EOPNOTSUPP; + ++ if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) ++ return -ENOENT; ++ + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; +@@ -1885,10 +1888,6 @@ static int nl80211_get_key(struct sk_buf + if (mac_addr) + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + +- if (pairwise && mac_addr && +- !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) +- return -ENOENT; +- + err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, pairwise, + mac_addr, &cookie, get_key_callback); + +@@ -2060,7 +2059,7 @@ static int nl80211_del_key(struct sk_buf + wdev_lock(dev->ieee80211_ptr); + err = nl80211_key_allowed(dev->ieee80211_ptr); + +- if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && ++ if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && + !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) + err = -ENOENT; + diff --git a/patches/ocfs2-fix-journal-commit-deadlock.patch b/patches/ocfs2-fix-journal-commit-deadlock.patch new file mode 100644 index 0000000..ece83af --- /dev/null +++ b/patches/ocfs2-fix-journal-commit-deadlock.patch @@ -0,0 +1,81 @@ +From 136f49b9171074872f2a14ad0ab10486d1ba13ca Mon Sep 17 00:00:00 2001 +From: Junxiao Bi <junxiao.bi@oracle.com> +Date: Thu, 18 Dec 2014 16:17:37 -0800 +Subject: ocfs2: fix journal commit deadlock + +commit 136f49b9171074872f2a14ad0ab10486d1ba13ca upstream. + +For buffer write, page lock will be got in write_begin and released in +write_end, in ocfs2_write_end_nolock(), before it unlock the page in +ocfs2_free_write_ctxt(), it calls ocfs2_run_deallocs(), this will ask +for the read lock of journal->j_trans_barrier. Holding page lock and +ask for journal->j_trans_barrier breaks the locking order. + +This will cause a deadlock with journal commit threads, ocfs2cmt will +get write lock of journal->j_trans_barrier first, then it wakes up +kjournald2 to do the commit work, at last it waits until done. To +commit journal, kjournald2 needs flushing data first, it needs get the +cache page lock. + +Since some ocfs2 cluster locks are holding by write process, this +deadlock may hung the whole cluster. + +unlock pages before ocfs2_run_deallocs() can fix the locking order, also +put unlock before ocfs2_commit_trans() to make page lock is unlocked +before j_trans_barrier to preserve unlocking order. + +Signed-off-by: Junxiao Bi <junxiao.bi@oracle.com> +Reviewed-by: Wengang Wang <wen.gang.wang@oracle.com> +Reviewed-by: Mark Fasheh <mfasheh@suse.de> +Cc: Joel Becker <jlbec@evilplan.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/ocfs2/aops.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/fs/ocfs2/aops.c ++++ b/fs/ocfs2/aops.c +@@ -917,7 +917,7 @@ void ocfs2_unlock_and_free_pages(struct + } + } + +-static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++static void ocfs2_unlock_pages(struct ocfs2_write_ctxt *wc) + { + int i; + +@@ -938,7 +938,11 @@ static void ocfs2_free_write_ctxt(struct + page_cache_release(wc->w_target_page); + } + ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages); ++} + ++static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc) ++{ ++ ocfs2_unlock_pages(wc); + brelse(wc->w_di_bh); + kfree(wc); + } +@@ -2059,11 +2063,19 @@ out_write_size: + di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + ocfs2_journal_dirty(handle, wc->w_di_bh); + ++ /* unlock pages before dealloc since it needs acquiring j_trans_barrier ++ * lock, or it will cause a deadlock since journal commit threads holds ++ * this lock and will ask for the page lock when flushing the data. ++ * put it here to preserve the unlock order. ++ */ ++ ocfs2_unlock_pages(wc); ++ + ocfs2_commit_trans(osb, handle); + + ocfs2_run_deallocs(osb, &wc->w_dealloc); + +- ocfs2_free_write_ctxt(wc); ++ brelse(wc->w_di_bh); ++ kfree(wc); + + return copied; + } diff --git a/patches/ohci-add-a-quirk-for-uli-m5237-blocking-on-reset.patch b/patches/ohci-add-a-quirk-for-uli-m5237-blocking-on-reset.patch new file mode 100644 index 0000000..79446bd --- /dev/null +++ b/patches/ohci-add-a-quirk-for-uli-m5237-blocking-on-reset.patch @@ -0,0 +1,78 @@ +From 56abcab833fafcfaeb2f5b25e0364c1dec45f53e Mon Sep 17 00:00:00 2001 +From: Arseny Solokha <asolokha@kb.kras.ru> +Date: Sat, 6 Dec 2014 09:54:06 +0700 +Subject: OHCI: add a quirk for ULi M5237 blocking on reset + +commit 56abcab833fafcfaeb2f5b25e0364c1dec45f53e upstream. + +Commit 8dccddbc2368 ("OHCI: final fix for NVIDIA problems (I hope)") +introduced into 3.1.9 broke boot on e.g. Freescale P2020DS development +board. The code path that was previously specific to NVIDIA controllers +had then become taken for all chips. + +However, the M5237 installed on the board wedges solid when accessing +its base+OHCI_FMINTERVAL register, making it impossible to boot any +kernel newer than 3.1.8 on this particular and apparently other similar +machines. + +Don't readl() and writel() base+OHCI_FMINTERVAL on PCI ID 10b9:5237. + +The patch is suitable for the -next tree as well as all maintained +kernels up to 3.2 inclusive. + +Signed-off-by: Arseny Solokha <asolokha@kb.kras.ru> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/host/pci-quirks.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/pci-quirks.c ++++ b/drivers/usb/host/pci-quirks.c +@@ -470,7 +470,8 @@ static void __devinit quirk_usb_handoff_ + { + void __iomem *base; + u32 control; +- u32 fminterval; ++ u32 fminterval = 0; ++ bool no_fminterval = false; + int cnt; + + if (!mmio_resource_enabled(pdev, 0)) +@@ -480,6 +481,13 @@ static void __devinit quirk_usb_handoff_ + if (base == NULL) + return; + ++ /* ++ * ULi M5237 OHCI controller locks the whole system when accessing ++ * the OHCI_FMINTERVAL offset. ++ */ ++ if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237) ++ no_fminterval = true; ++ + control = readl(base + OHCI_CONTROL); + + /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ +@@ -518,7 +526,9 @@ static void __devinit quirk_usb_handoff_ + } + + /* software reset of the controller, preserving HcFmInterval */ +- fminterval = readl(base + OHCI_FMINTERVAL); ++ if (!no_fminterval) ++ fminterval = readl(base + OHCI_FMINTERVAL); ++ + writel(OHCI_HCR, base + OHCI_CMDSTATUS); + + /* reset requires max 10 us delay */ +@@ -527,7 +537,9 @@ static void __devinit quirk_usb_handoff_ + break; + udelay(1); + } +- writel(fminterval, base + OHCI_FMINTERVAL); ++ ++ if (!no_fminterval) ++ writel(fminterval, base + OHCI_FMINTERVAL); + + /* Now the controller is safely in SUSPEND and nothing can wake it up */ + iounmap(base); diff --git a/patches/pci-restore-detection-of-read-only-bars.patch b/patches/pci-restore-detection-of-read-only-bars.patch new file mode 100644 index 0000000..6edaf20 --- /dev/null +++ b/patches/pci-restore-detection-of-read-only-bars.patch @@ -0,0 +1,61 @@ +From 36e8164882ca6d3c41cb91e6f09a3ed236841f80 Mon Sep 17 00:00:00 2001 +From: Myron Stowe <myron.stowe@redhat.com> +Date: Thu, 30 Oct 2014 11:54:37 -0600 +Subject: PCI: Restore detection of read-only BARs + +commit 36e8164882ca6d3c41cb91e6f09a3ed236841f80 upstream. + +Commit 6ac665c63dca ("PCI: rewrite PCI BAR reading code") masked off +low-order bits from 'l', but not from 'sz'. Both are passed to pci_size(), +which compares 'base == maxbase' to check for read-only BARs. The masking +of 'l' means that comparison will never be 'true', so the check for +read-only BARs no longer works. + +Resolve this by also masking off the low-order bits of 'sz' before passing +it into pci_size() as 'maxbase'. With this change, pci_size() will once +again catch the problems that have been encountered to date: + + - AGP aperture BAR of AMD-7xx host bridges: if the AGP window is + disabled, this BAR is read-only and read as 0x00000008 [1] + + - BARs 0-4 of ALi IDE controllers can be non-zero and read-only [1] + + - Intel Sandy Bridge - Thermal Management Controller [8086:0103]; + BAR 0 returning 0xfed98004 [2] + + - Intel Xeon E5 v3/Core i7 Power Control Unit [8086:2fc0]; + Bar 0 returning 0x00001a [3] + +Link: [1] https://git.kernel.org/cgit/linux/kernel/git/tglx/history.git/commit/drivers/pci/probe.c?id=1307ef6621991f1c4bc3cec1b5a4ebd6fd3d66b9 ("PCI: probing read-only BARs" (pre-git)) +Link: [2] https://bugzilla.kernel.org/show_bug.cgi?id=43331 +Link: [3] https://bugzilla.kernel.org/show_bug.cgi?id=85991 +Reported-by: William Unruh <unruh@physics.ubc.ca> +Reported-by: Martin Lucina <martin@lucina.net> +Signed-off-by: Myron Stowe <myron.stowe@redhat.com> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +CC: Matthew Wilcox <willy@linux.intel.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/pci/probe.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -254,14 +254,17 @@ int __pci_read_base(struct pci_dev *dev, + res->flags |= IORESOURCE_SIZEALIGN; + if (res->flags & IORESOURCE_IO) { + l &= PCI_BASE_ADDRESS_IO_MASK; ++ sz &= PCI_BASE_ADDRESS_IO_MASK; + mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT; + } else { + l &= PCI_BASE_ADDRESS_MEM_MASK; ++ sz &= PCI_BASE_ADDRESS_MEM_MASK; + mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; + } + } else { + res->flags |= (l & IORESOURCE_ROM_ENABLE); + l &= PCI_ROM_ADDRESS_MASK; ++ sz &= PCI_ROM_ADDRESS_MASK; + mask = (u32)PCI_ROM_ADDRESS_MASK; + } + diff --git a/patches/powerpc-xmon-fix-another-endiannes-issue-in-rtas-call-from-xmon.patch b/patches/powerpc-xmon-fix-another-endiannes-issue-in-rtas-call-from-xmon.patch new file mode 100644 index 0000000..166228a --- /dev/null +++ b/patches/powerpc-xmon-fix-another-endiannes-issue-in-rtas-call-from-xmon.patch @@ -0,0 +1,36 @@ +From e6eb2eba494d6f99e69ca3c3748cd37a2544ab38 Mon Sep 17 00:00:00 2001 +From: Laurent Dufour <ldufour@linux.vnet.ibm.com> +Date: Thu, 15 Jan 2015 18:23:47 +0100 +Subject: powerpc/xmon: Fix another endiannes issue in RTAS call from xmon + +commit e6eb2eba494d6f99e69ca3c3748cd37a2544ab38 upstream. + +The commit 3b8a3c010969 ("powerpc/pseries: Fix endiannes issue in RTAS +call from xmon") was fixing an endianness issue in the call made from +xmon to RTAS. + +However, as Michael Ellerman noticed, this fix was not complete, the +token value was not byte swapped. This lead to call an unexpected and +most of the time unexisting RTAS function, which is silently ignored by +RTAS. + +This fix addresses this hole. + +Reported-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/powerpc/xmon/xmon.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -285,6 +285,7 @@ static inline void disable_surveillance( + args.token = rtas_token("set-indicator"); + if (args.token == RTAS_UNKNOWN_SERVICE) + return; ++ args.token = cpu_to_be32(args.token); + args.nargs = cpu_to_be32(3); + args.nret = cpu_to_be32(1); + args.rets = &args.args[3]; diff --git a/patches/regulator-core-fix-race-condition-in-regulator_put.patch b/patches/regulator-core-fix-race-condition-in-regulator_put.patch new file mode 100644 index 0000000..149982a --- /dev/null +++ b/patches/regulator-core-fix-race-condition-in-regulator_put.patch @@ -0,0 +1,46 @@ +From 83b0302d347a49f951e904184afe57ac3723476e Mon Sep 17 00:00:00 2001 +From: Ashay Jaiswal <ashayj@codeaurora.org> +Date: Thu, 8 Jan 2015 18:54:25 +0530 +Subject: regulator: core: fix race condition in regulator_put() + +commit 83b0302d347a49f951e904184afe57ac3723476e upstream. + +The regulator framework maintains a list of consumer regulators +for a regulator device and protects it from concurrent access using +the regulator device's mutex lock. + +In the case of regulator_put() the consumer is removed and regulator +device's parameters are updated without holding the regulator device's +mutex. This would lead to a race condition between the regulator_put() +and any function which traverses the consumer list or modifies regulator +device's parameters. +Fix this race condition by holding the regulator device's mutex in case +of regulator_put. + +Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org> +Signed-off-by: Mark Brown <broonie@kernel.org> +[lizf: Backported to 3.4: + - adjust context + - no need to change the comment] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/regulator/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1395,12 +1395,14 @@ void regulator_put(struct regulator *reg + device_remove_file(regulator->dev, ®ulator->dev_attr); + kfree(regulator->dev_attr.attr.name); + } ++ mutex_lock(&rdev->mutex); + kfree(regulator->supply_name); + list_del(®ulator->list); + kfree(regulator); + + rdev->open_count--; + rdev->exclusive = 0; ++ mutex_unlock(&rdev->mutex); + + module_put(rdev->owner); + mutex_unlock(®ulator_list_mutex); diff --git a/patches/sata_dwc_460ex-fix-resource-leak-on-error-path.patch b/patches/sata_dwc_460ex-fix-resource-leak-on-error-path.patch new file mode 100644 index 0000000..86b750f --- /dev/null +++ b/patches/sata_dwc_460ex-fix-resource-leak-on-error-path.patch @@ -0,0 +1,108 @@ +From 4aaa71873ddb9faf4b0c4826579e2f6d18ff9ab4 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Date: Wed, 7 Jan 2015 15:24:19 +0200 +Subject: sata_dwc_460ex: fix resource leak on error path + +commit 4aaa71873ddb9faf4b0c4826579e2f6d18ff9ab4 upstream. + +DMA mapped IO should be unmapped on the error path in probe() and +unconditionally on remove(). + +Fixes: 62936009f35a ([libata] Add 460EX on-chip SATA driver, sata_dwc_460ex) +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/ata/sata_dwc_460ex.c | 26 ++++++++++++-------------- + 1 file changed, 12 insertions(+), 14 deletions(-) + +--- a/drivers/ata/sata_dwc_460ex.c ++++ b/drivers/ata/sata_dwc_460ex.c +@@ -791,7 +791,7 @@ static int dma_dwc_init(struct sata_dwc_ + if (err) { + dev_err(host_pvt.dwc_dev, "%s: dma_request_interrupts returns" + " %d\n", __func__, err); +- goto error_out; ++ return err; + } + + /* Enabe DMA */ +@@ -802,11 +802,6 @@ static int dma_dwc_init(struct sata_dwc_ + sata_dma_regs); + + return 0; +- +-error_out: +- dma_dwc_exit(hsdev); +- +- return err; + } + + static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +@@ -1634,7 +1629,7 @@ static int sata_dwc_probe(struct platfor + char *ver = (char *)&versionr; + u8 *base = NULL; + int err = 0; +- int irq, rc; ++ int irq; + struct ata_host *host; + struct ata_port_info pi = sata_dwc_port_info[0]; + const struct ata_port_info *ppi[] = { &pi, NULL }; +@@ -1688,7 +1683,7 @@ static int sata_dwc_probe(struct platfor + if (irq == NO_IRQ) { + dev_err(&ofdev->dev, "no SATA DMA irq\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Get physical SATA DMA register base address */ +@@ -1697,14 +1692,16 @@ static int sata_dwc_probe(struct platfor + dev_err(&ofdev->dev, "ioremap failed for AHBDMA register" + " address\n"); + err = -ENODEV; +- goto error_out; ++ goto error_iomap; + } + + /* Save dev for later use in dev_xxx() routines */ + host_pvt.dwc_dev = &ofdev->dev; + + /* Initialize AHB DMAC */ +- dma_dwc_init(hsdev, irq); ++ err = dma_dwc_init(hsdev, irq); ++ if (err) ++ goto error_dma_iomap; + + /* Enable SATA Interrupts */ + sata_dwc_enable_interrupts(hsdev); +@@ -1722,9 +1719,8 @@ static int sata_dwc_probe(struct platfor + * device discovery process, invoking our port_start() handler & + * error_handler() to execute a dummy Softreset EH session + */ +- rc = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); +- +- if (rc != 0) ++ err = ata_host_activate(host, irq, sata_dwc_isr, 0, &sata_dwc_sht); ++ if (err) + dev_err(&ofdev->dev, "failed to activate host"); + + dev_set_drvdata(&ofdev->dev, host); +@@ -1733,7 +1729,8 @@ static int sata_dwc_probe(struct platfor + error_out: + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); +- ++error_dma_iomap: ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + error_iomap: + iounmap(base); + error_kmalloc: +@@ -1754,6 +1751,7 @@ static int sata_dwc_remove(struct platfo + /* Free SATA DMA resources */ + dma_dwc_exit(hsdev); + ++ iounmap((void __iomem *)host_pvt.sata_dma_regs); + iounmap(hsdev->reg_base); + kfree(hsdev); + kfree(host); diff --git a/patches/scripts-recordmcount.pl-there-is-no-m32-gcc-option-on-super-h-anymore.patch b/patches/scripts-recordmcount.pl-there-is-no-m32-gcc-option-on-super-h-anymore.patch new file mode 100644 index 0000000..366aea9 --- /dev/null +++ b/patches/scripts-recordmcount.pl-there-is-no-m32-gcc-option-on-super-h-anymore.patch @@ -0,0 +1,42 @@ +From 1caf6aaaa47471831d77c75f094d4e00ad1ec808 Mon Sep 17 00:00:00 2001 +From: Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de> +Date: Sun, 18 Jan 2015 00:36:15 +0100 +Subject: scripts/recordmcount.pl: There is no -m32 gcc option on Super-H + anymore + +commit 1caf6aaaa47471831d77c75f094d4e00ad1ec808 upstream. + +Compiling SH with gcc-4.8 fails due to the -m32 option not being +supported. + +From http://buildd.debian-ports.org/status/fetch.php?pkg=linux&arch=sh4&ver=3.16.7-ckt4-1&stamp=1421425783 + + CC init/main.o + gcc-4.8: error: unrecognized command line option '-m32' + ld: cannot find init/.tmp_mc_main.o: No such file or directory + objcopy: 'init/.tmp_mx_main.o': No such file + rm: cannot remove 'init/.tmp_mx_main.o': No such file or directory + rm: cannot remove 'init/.tmp_mc_main.o': No such file or directory + +Link: http://lkml.kernel.org/r/1421537778-29001-1-git-send-email-kernel@mkarcher.dialup.fu-berlin.de +Link: http://lkml.kernel.org/r/54BCBDD4.10102@physik.fu-berlin.de + +Cc: Matt Fleming <matt@console-pimps.org> +Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> +Signed-off-by: Michael Karcher <kernel@mkarcher.dialup.fu-berlin.de> +Signed-off-by: Steven Rostedt <rostedt@goodmis.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + scripts/recordmcount.pl | 1 - + 1 file changed, 1 deletion(-) + +--- a/scripts/recordmcount.pl ++++ b/scripts/recordmcount.pl +@@ -262,7 +262,6 @@ if ($arch eq "x86_64") { + # force flags for this arch + $ld .= " -m shlelf_linux"; + $objcopy .= " -O elf32-sh-linux"; +- $cc .= " -m32"; + + } elsif ($arch eq "powerpc") { + $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; diff --git a/patches/scsi-correct-return-values-for-.eh_abort_handler-implementations.patch b/patches/scsi-correct-return-values-for-.eh_abort_handler-implementations.patch new file mode 100644 index 0000000..d73a4a9 --- /dev/null +++ b/patches/scsi-correct-return-values-for-.eh_abort_handler-implementations.patch @@ -0,0 +1,134 @@ +From b6c92b7e0af575e2b8b05bdf33633cf9e1661cbf Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke <hare@suse.de> +Date: Thu, 30 Oct 2014 09:44:36 +0100 +Subject: scsi: correct return values for .eh_abort_handler implementations + +commit b6c92b7e0af575e2b8b05bdf33633cf9e1661cbf upstream. + +The .eh_abort_handler needs to return SUCCESS, FAILED, or +FAST_IO_FAIL. So fixup all callers to adhere to this requirement. + +Reviewed-by: Robert Elliott <elliott@hp.com> +Signed-off-by: Hannes Reinecke <hare@suse.de> +Signed-off-by: Christoph Hellwig <hch@lst.de> +[lizf: Backported to 3.4: drop changes to esas2r_main.c] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/scsi/NCR5380.c | 12 ++++++------ + drivers/scsi/aha1740.c | 2 +- + drivers/scsi/atari_NCR5380.c | 2 +- + drivers/scsi/megaraid.c | 8 ++++---- + drivers/scsi/sun3_NCR5380.c | 10 +++++----- + 5 files changed, 17 insertions(+), 17 deletions(-) + +--- a/drivers/scsi/NCR5380.c ++++ b/drivers/scsi/NCR5380.c +@@ -2662,14 +2662,14 @@ static void NCR5380_dma_complete(NCR5380 + * + * Purpose : abort a command + * +- * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() + * called where the loop started in NCR5380_main(). + * +@@ -2719,7 +2719,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd + * aborted flag and get back into our main loop. + */ + +- return 0; ++ return SUCCESS; + } + #endif + +--- a/drivers/scsi/aha1740.c ++++ b/drivers/scsi/aha1740.c +@@ -550,7 +550,7 @@ static int aha1740_eh_abort_handler (Scs + * quiet as possible... + */ + +- return 0; ++ return SUCCESS; + } + + static struct scsi_host_template aha1740_template = { +--- a/drivers/scsi/atari_NCR5380.c ++++ b/drivers/scsi/atari_NCR5380.c +@@ -2638,7 +2638,7 @@ static void NCR5380_reselect(struct Scsi + * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * + * XXX - there is no way to abort the command that is currently + * connected, you have to wait for it to complete. If this is +--- a/drivers/scsi/megaraid.c ++++ b/drivers/scsi/megaraid.c +@@ -1967,7 +1967,7 @@ megaraid_abort_and_reset(adapter_t *adap + cmd->device->id, cmd->device->lun); + + if(list_empty(&adapter->pending_list)) +- return FALSE; ++ return FAILED; + + list_for_each_safe(pos, next, &adapter->pending_list) { + +@@ -1990,7 +1990,7 @@ megaraid_abort_and_reset(adapter_t *adap + (aor==SCB_ABORT) ? "ABORTING":"RESET", + scb->idx); + +- return FALSE; ++ return FAILED; + } + else { + +@@ -2015,12 +2015,12 @@ megaraid_abort_and_reset(adapter_t *adap + list_add_tail(SCSI_LIST(cmd), + &adapter->completed_list); + +- return TRUE; ++ return SUCCESS; + } + } + } + +- return FALSE; ++ return FAILED; + } + + static inline int +--- a/drivers/scsi/sun3_NCR5380.c ++++ b/drivers/scsi/sun3_NCR5380.c +@@ -2624,15 +2624,15 @@ static void NCR5380_reselect (struct Scs + * Purpose : abort a command + * + * Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the +- * host byte of the result field to, if zero DID_ABORTED is ++ * host byte of the result field to, if zero DID_ABORTED is + * used. + * +- * Returns : 0 - success, -1 on failure. ++ * Returns : SUCCESS - success, FAILED on failure. + * +- * XXX - there is no way to abort the command that is currently +- * connected, you have to wait for it to complete. If this is ++ * XXX - there is no way to abort the command that is currently ++ * connected, you have to wait for it to complete. If this is + * a problem, we could implement longjmp() / setjmp(), setjmp() +- * called where the loop started in NCR5380_main(). ++ * called where the loop started in NCR5380_main(). + */ + + static int NCR5380_abort(struct scsi_cmnd *cmd) diff --git a/patches/serial-samsung-wait-for-transfer-completion-before-clock-disable.patch b/patches/serial-samsung-wait-for-transfer-completion-before-clock-disable.patch new file mode 100644 index 0000000..043547e --- /dev/null +++ b/patches/serial-samsung-wait-for-transfer-completion-before-clock-disable.patch @@ -0,0 +1,40 @@ +From 1ff383a4c3eda8893ec61b02831826e1b1f46b41 Mon Sep 17 00:00:00 2001 +From: Robert Baldyga <r.baldyga@samsung.com> +Date: Mon, 24 Nov 2014 07:56:21 +0100 +Subject: serial: samsung: wait for transfer completion before clock disable + +commit 1ff383a4c3eda8893ec61b02831826e1b1f46b41 upstream. + +This patch adds waiting until transmit buffer and shifter will be empty +before clock disabling. + +Without this fix it's possible to have clock disabled while data was +not transmited yet, which causes unproper state of TX line and problems +in following data transfers. + +Signed-off-by: Robert Baldyga <r.baldyga@samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/tty/serial/samsung.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/serial/samsung.c ++++ b/drivers/tty/serial/samsung.c +@@ -524,11 +524,15 @@ static void s3c24xx_serial_pm(struct uar + unsigned int old) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); ++ int timeout = 10000; + + ourport->pm_level = level; + + switch (level) { + case 3: ++ while (--timeout && !s3c24xx_serial_txempty_nofifo(port)) ++ udelay(100); ++ + if (!IS_ERR(ourport->baudclk) && ourport->baudclk != NULL) + clk_disable(ourport->baudclk); + diff --git a/patches/series b/patches/series index d9b8f8f..cf3c49f 100644 --- a/patches/series +++ b/patches/series @@ -26,3 +26,105 @@ ahci-disable-ncq-on-samsung-pci-e-ssds-on-macbooks.patch ahci-disable-msi-instead-of-ncq-on-samsung-pci-e-ssds-on-macbooks.patch ahci-disable-msi-on-samsung-0xa800-ssd.patch i2c-davinci-generate-stp-always-when-nack-is-received.patch +ecryptfs-force-ro-mount-when-encrypted-view-is-enabled.patch +writeback-move-i_dirty_pages-handling.patch +writeback-fix-a-subtle-race-condition-in-i_dirty-clearing.patch +usb-renesas_usbhs-gadget-fix-null-pointer-dereference-in-ep_disable.patch +kvm-s390-flush-cpu-on-load-control.patch +ubi-fix-invalid-vfree.patch +driver-core-fix-unbalanced-device-reference-in-drivers_probe.patch +drbd-merge_bvec_fn-properly-remap-bvm-bi_bdev.patch +pci-restore-detection-of-read-only-bars.patch +scsi-correct-return-values-for-.eh_abort_handler-implementations.patch +genhd-check-for-int-overflow-in-disk_expand_part_tbl.patch +asoc-sigmadsp-refuse-to-load-firmware-files-with-a-non-supported-version.patch +megaraid_sas-corrected-return-of-wait_event-from-abort-frame-path.patch +cdc-acm-memory-leak-in-error-case.patch +usb-cdc-acm-check-for-valid-interfaces.patch +mfd-tc6393xb-fail-ohci-suspend-if-full-state-restore-is-required.patch +serial-samsung-wait-for-transfer-completion-before-clock-disable.patch +ecryptfs-remove-buggy-and-unnecessary-write-in-file-name-decode-routine.patch +ath9k_hw-fix-hardware-queue-allocation.patch +ath9k-fix-be-bk-queue-order.patch +ath5k-fix-hardware-queue-index-assignment.patch +iommu-vt-d-fix-an-off-by-one-bug-in-__domain_mapping.patch +drm-vmwgfx-don-t-use-memory-accounting-for-kernel-side-fence-objects.patch +drm-vmwgfx-fix-fence-event-code.patch +hp_accel-add-support-for-hp-zbook-15.patch +drm-radeon-check-the-right-ring-in-radeon_evict_flags.patch +can-peak_usb-fix-memset-usage.patch +can-peak_usb-fix-cleanup-sequence-order-in-case-of-error-during-init.patch +alsa-usb-audio-don-t-resubmit-pending-urbs-at-midi-error-recovery.patch +keys-fix-stale-key-registration-at-error-path.patch +btrfs-fix-fs-corruption-on-transaction-abort-if-device-supports-discard.patch +ncpfs-return-proper-error-from-ncp_ioc_setroot-ioctl.patch +x86_64-switch_to-load-tls-descriptors-before-switching-ds-and-es.patch +genirq-prevent-proc-race-against-freeing-of-irq-descriptors.patch +x86-tls-disallow-unusual-tls-segments.patch +x86-tls-don-t-validate-lm-in-set_thread_area-after-all.patch +storvsc-ring-buffer-failures-may-result-in-i-o-freeze.patch +isofs-fix-infinite-looping-over-ce-entries.patch +iscsi-target-fail-connection-on-short-sendmsg-writes.patch +alsa-usb-audio-extend-kef-x300a-fu-10-tweak-to-arcam-rpac.patch +ocfs2-fix-journal-commit-deadlock.patch +isofs-fix-unchecked-printing-of-er-records.patch +udf-verify-i_size-when-loading-inode.patch +udf-verify-symlink-size-before-loading-it.patch +udf-check-path-length-when-reading-symlink.patch +x86_64-vdso-fix-the-vdso-address-randomization-algorithm.patch +udf-check-component-length-before-reading-it.patch +crypto-af_alg-fix-backlog-handling.patch +net-fix-stacked-vlan-offload-features-computation.patch +video-logo-prevent-use-of-logos-after-they-have-been-freed.patch +usb-cp210x-fix-id-for-production-cel-meshconnect-usb-stick.patch +x86-um-actually-mark-system-call-tables-readonly.patch +alsa-hda-fix-wrong-gpio_dir-gpio_mask-hint-setups-for-idt-stac-codecs.patch +virtio-use-dev_to_virtio-wrapper-in-virtio.patch +virtio_pci-defer-kfree-until-release-callback.patch +virtio_pci-document-why-we-defer-kfree.patch +usb-cp210x-add-ids-for-cel-usb-sticks-and-meshworks-devices.patch +mm-propagate-error-from-stack-expansion-even-for-guard-page.patch +sata_dwc_460ex-fix-resource-leak-on-error-path.patch +time-settimeofday-validate-the-values-of-tv-from-user.patch +time-adjtimex-validate-the-adj_frequency-values.patch +input-i8042-reset-keyboard-to-fix-elantech-touchpad-detection.patch +input-i8042-add-acer-aspire-7738-to-the-nomux-list.patch +mac80211-fix-multicast-led-blinking-and-counter.patch +mm-prevent-endless-growth-of-anon_vma-hierarchy.patch +mm-protect-set_page_dirty-from-ongoing-truncation.patch +hid-roccat-potential-out-of-bounds-in-pyra_sysfs_write_settings.patch +ohci-add-a-quirk-for-uli-m5237-blocking-on-reset.patch +usb-console-fix-potential-use-after-free.patch +mm-don-t-count-the-stack-guard-page-towards-rlimit_stack.patch +mm-fix-corner-case-in-anon_vma-endless-growing-prevention.patch +gpio-fix-memory-and-reference-leaks-in-gpiochip_add-error-path.patch +usb-dwc3-gadget-stop-trb-preparation-after-limit-is-reached.patch +ftrace-jprobes-x86-fix-conflict-between-jprobes-and-function-graph-tracing.patch +can-dev-fix-crtlmode_supported-check.patch +sysfs.h-add-attribute_groups-macro.patch +driver-core-introduce-device_create_groups.patch +gpio-sysfs-fix-gpio-chip-device-attribute-leak.patch +gpiolib-refactor-gpio_export.patch +gpio-sysfs-fix-gpio-device-attribute-leak.patch +gpio-sysfs-fix-gpio-attribute-creation-race.patch +alsa-usb-audio-add-mic-volume-fix-quirk-for-logitech-webcam-c210.patch +libata-allow-sata_sil24-to-opt-out-of-tag-ordered-submission.patch +scripts-recordmcount.pl-there-is-no-m32-gcc-option-on-super-h-anymore.patch +libata-prevent-hsm-state-change-race-between-isr-and-pio.patch +x86-hyperv-mark-the-hyper-v-clocksource-as-being-continuous.patch +spi-dw-fix-detecting-fifo-depth.patch +spi-dw-mid-fix-fifo-size.patch +asoc-wm8960-fix-capture-sample-rate-from-11250-to-11025.patch +regulator-core-fix-race-condition-in-regulator_put.patch +powerpc-xmon-fix-another-endiannes-issue-in-rtas-call-from-xmon.patch +nl80211-fix-per-station-group-key-get-del-and-memory-leak.patch +usb-storage-scsi-add-broken_fua-blacklist-flag.patch +usb-storage-scsi-blacklist-fua-on-jmicron-152d-2566-usb-sata-controller.patch +usb-core-binterval-quirk.patch +usb-add-otg-pet-device-to-tpl.patch +drm-i915-only-fence-tiled-region-of-object.patch +alsa-seq-dummy-remove-deadlock-causing-events-on-close.patch +net-sctp-fix-slab-corruption-from-use-after-free-on-init-collisions.patch +ipv6-replacing-a-rt6_info-needs-to-purge-possible-propagated-rt6_infos-too.patch +vm-add-vm_fault_sigsegv-handling-support.patch +vm-make-stack-guard-page-errors-return-vm_fault_sigsegv-rather-than-sigbus.patch diff --git a/patches/spi-dw-fix-detecting-fifo-depth.patch b/patches/spi-dw-fix-detecting-fifo-depth.patch new file mode 100644 index 0000000..37f5eae --- /dev/null +++ b/patches/spi-dw-fix-detecting-fifo-depth.patch @@ -0,0 +1,44 @@ +From d297933cc7fcfbaaf2d37570baac73287bf0357d Mon Sep 17 00:00:00 2001 +From: Axel Lin <axel.lin@ingics.com> +Date: Mon, 5 Jan 2015 09:32:56 +0800 +Subject: spi: dw: Fix detecting FIFO depth + +commit d297933cc7fcfbaaf2d37570baac73287bf0357d upstream. + +Current code tries to find the highest valid fifo depth by checking the value +it wrote to DW_SPI_TXFLTR. There are a few problems in current code: +1) There is an off-by-one in dws->fifo_len setting because it assumes the latest + register write fails so the latest valid value should be fifo - 1. +2) We know the depth could be from 2 to 256 from HW spec, so it is not necessary + to test fifo == 257. In the case fifo is 257, it means the latest valid + setting is fifo = 256. So after the for loop iteration, we should check + fifo == 2 case instead of fifo == 257 if detecting the FIFO depth fails. +This patch fixes above issues. + +Signed-off-by: Axel Lin <axel.lin@ingics.com> +Reviewed-and-tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/spi/spi-dw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/spi/spi-dw.c ++++ b/drivers/spi/spi-dw.c +@@ -780,13 +780,13 @@ static void spi_hw_init(struct dw_spi *d + */ + if (!dws->fifo_len) { + u32 fifo; +- for (fifo = 2; fifo <= 257; fifo++) { ++ for (fifo = 2; fifo <= 256; fifo++) { + dw_writew(dws, DW_SPI_TXFLTR, fifo); + if (fifo != dw_readw(dws, DW_SPI_TXFLTR)) + break; + } + +- dws->fifo_len = (fifo == 257) ? 0 : fifo; ++ dws->fifo_len = (fifo == 2) ? 0 : fifo - 1; + dw_writew(dws, DW_SPI_TXFLTR, 0); + } + } diff --git a/patches/spi-dw-mid-fix-fifo-size.patch b/patches/spi-dw-mid-fix-fifo-size.patch new file mode 100644 index 0000000..1ed49a3 --- /dev/null +++ b/patches/spi-dw-mid-fix-fifo-size.patch @@ -0,0 +1,29 @@ +From 67bf9cda4b498b8cea4a40be67a470afe57d2e88 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Date: Fri, 2 Jan 2015 17:48:51 +0200 +Subject: spi: dw-mid: fix FIFO size + +commit 67bf9cda4b498b8cea4a40be67a470afe57d2e88 upstream. + +The FIFO size is 40 accordingly to the specifications, but this means 0x40, +i.e. 64 bytes. This patch fixes the typo and enables FIFO size autodetection +for Intel MID devices. + +Fixes: 7063c0d942a1 (spi/dw_spi: add DMA support) +Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/spi/spi-dw-mid.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/spi/spi-dw-mid.c ++++ b/drivers/spi/spi-dw-mid.c +@@ -219,7 +219,6 @@ int dw_spi_mid_init(struct dw_spi *dws) + iounmap(clk_reg); + + dws->num_cs = 16; +- dws->fifo_len = 40; /* FIFO has 40 words buffer */ + + #ifdef CONFIG_SPI_DW_MID_DMA + dws->dma_priv = kzalloc(sizeof(struct mid_dma), GFP_KERNEL); diff --git a/patches/storvsc-ring-buffer-failures-may-result-in-i-o-freeze.patch b/patches/storvsc-ring-buffer-failures-may-result-in-i-o-freeze.patch new file mode 100644 index 0000000..e7dea3d --- /dev/null +++ b/patches/storvsc-ring-buffer-failures-may-result-in-i-o-freeze.patch @@ -0,0 +1,39 @@ +From e86fb5e8ab95f10ec5f2e9430119d5d35020c951 Mon Sep 17 00:00:00 2001 +From: Long Li <longli@microsoft.com> +Date: Fri, 5 Dec 2014 19:38:18 -0800 +Subject: storvsc: ring buffer failures may result in I/O freeze + +commit e86fb5e8ab95f10ec5f2e9430119d5d35020c951 upstream. + +When ring buffer returns an error indicating retry, storvsc may not +return a proper error code to SCSI when bounce buffer is not used. +This has introduced I/O freeze on RAID running atop storvsc devices. +This patch fixes it by always returning a proper error code. + +Signed-off-by: Long Li <longli@microsoft.com> +Reviewed-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Christoph Hellwig <hch@lst.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/scsi/storvsc_drv.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -1359,13 +1359,12 @@ static int storvsc_queuecommand(struct S + if (ret == -EAGAIN) { + /* no more space */ + +- if (cmd_request->bounce_sgl_count) { ++ if (cmd_request->bounce_sgl_count) + destroy_bounce_buffer(cmd_request->bounce_sgl, + cmd_request->bounce_sgl_count); + +- ret = SCSI_MLQUEUE_DEVICE_BUSY; +- goto queue_error; +- } ++ ret = SCSI_MLQUEUE_DEVICE_BUSY; ++ goto queue_error; + } + + return 0; diff --git a/patches/sysfs.h-add-attribute_groups-macro.patch b/patches/sysfs.h-add-attribute_groups-macro.patch new file mode 100644 index 0000000..ca421e9 --- /dev/null +++ b/patches/sysfs.h-add-attribute_groups-macro.patch @@ -0,0 +1,37 @@ +From f2f37f58b1b933b06d6d84e80a31a1b500fb0db2 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 14 Jul 2013 16:05:52 -0700 +Subject: sysfs.h: add ATTRIBUTE_GROUPS() macro + +commit f2f37f58b1b933b06d6d84e80a31a1b500fb0db2 upstream. + +To make it easier for driver subsystems to work with attribute groups, +create the ATTRIBUTE_GROUPS macro to remove some of the repetitive +typing for the most common use for attribute groups. + +Reviewed-by: Guenter Roeck <linux@roeck-us.net> +Tested-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + include/linux/sysfs.h | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/include/linux/sysfs.h ++++ b/include/linux/sysfs.h +@@ -80,6 +80,15 @@ struct attribute_group { + + #define __ATTR_NULL { .attr = { .name = NULL } } + ++#define ATTRIBUTE_GROUPS(name) \ ++static const struct attribute_group name##_group = { \ ++ .attrs = name##_attrs, \ ++}; \ ++static const struct attribute_group *name##_groups[] = { \ ++ &name##_group, \ ++ NULL, \ ++} ++ + #define attr_name(_attr) (_attr).attr.name + + struct file; diff --git a/patches/time-adjtimex-validate-the-adj_frequency-values.patch b/patches/time-adjtimex-validate-the-adj_frequency-values.patch new file mode 100644 index 0000000..a1cbbfa --- /dev/null +++ b/patches/time-adjtimex-validate-the-adj_frequency-values.patch @@ -0,0 +1,38 @@ +From 5e5aeb4367b450a28f447f6d5ab57d8f2ab16a5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sasha.levin@oracle.com> +Date: Wed, 3 Dec 2014 19:25:05 -0500 +Subject: time: adjtimex: Validate the ADJ_FREQUENCY values + +commit 5e5aeb4367b450a28f447f6d5ab57d8f2ab16a5f upstream. + +Verify that the frequency value from userspace is valid and makes sense. + +Unverified values can cause overflows later on. + +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Sasha Levin <sasha.levin@oracle.com> +[jstultz: Fix up bug for negative values and drop redunent cap check] +Signed-off-by: John Stultz <john.stultz@linaro.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + kernel/time/ntp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/kernel/time/ntp.c ++++ b/kernel/time/ntp.c +@@ -660,6 +660,13 @@ int do_adjtimex(struct timex *txc) + return result; + } + ++ if (txc->modes & ADJ_FREQUENCY) { ++ if (LONG_MIN / PPM_SCALE > txc->freq) ++ return -EINVAL; ++ if (LONG_MAX / PPM_SCALE < txc->freq) ++ return -EINVAL; ++ } ++ + getnstimeofday(&ts); + + spin_lock_irq(&ntp_lock); diff --git a/patches/time-settimeofday-validate-the-values-of-tv-from-user.patch b/patches/time-settimeofday-validate-the-values-of-tv-from-user.patch new file mode 100644 index 0000000..19a46ca --- /dev/null +++ b/patches/time-settimeofday-validate-the-values-of-tv-from-user.patch @@ -0,0 +1,59 @@ +From 6ada1fc0e1c4775de0e043e1bd3ae9d065491aa5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sasha.levin@oracle.com> +Date: Wed, 3 Dec 2014 19:22:48 -0500 +Subject: time: settimeofday: Validate the values of tv from user + +commit 6ada1fc0e1c4775de0e043e1bd3ae9d065491aa5 upstream. + +An unvalidated user input is multiplied by a constant, which can result in +an undefined behaviour for large values. While this is validated later, +we should avoid triggering undefined behaviour. + +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Sasha Levin <sasha.levin@oracle.com> +[jstultz: include trivial milisecond->microsecond correction noticed +by Andy] +Signed-off-by: John Stultz <john.stultz@linaro.org> +[lizf: Backported to 3.4: adjust filename] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + include/linux/time.h | 13 +++++++++++++ + kernel/time.c | 4 ++++ + 2 files changed, 17 insertions(+) + +--- a/include/linux/time.h ++++ b/include/linux/time.h +@@ -189,6 +189,19 @@ extern void getboottime(struct timespec + extern void monotonic_to_bootbased(struct timespec *ts); + extern void get_monotonic_boottime(struct timespec *ts); + ++static inline bool timeval_valid(const struct timeval *tv) ++{ ++ /* Dates before 1970 are bogus */ ++ if (tv->tv_sec < 0) ++ return false; ++ ++ /* Can't have more microseconds then a second */ ++ if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) ++ return false; ++ ++ return true; ++} ++ + extern struct timespec timespec_trunc(struct timespec t, unsigned gran); + extern int timekeeping_valid_for_hres(void); + extern u64 timekeeping_max_deferment(void); +--- a/kernel/time.c ++++ b/kernel/time.c +@@ -186,6 +186,10 @@ SYSCALL_DEFINE2(settimeofday, struct tim + if (tv) { + if (copy_from_user(&user_tv, tv, sizeof(*tv))) + return -EFAULT; ++ ++ if (!timeval_valid(&user_tv)) ++ return -EINVAL; ++ + new_ts.tv_sec = user_tv.tv_sec; + new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; + } diff --git a/patches/ubi-fix-invalid-vfree.patch b/patches/ubi-fix-invalid-vfree.patch new file mode 100644 index 0000000..5fb0d1c --- /dev/null +++ b/patches/ubi-fix-invalid-vfree.patch @@ -0,0 +1,69 @@ +From f38aed975c0c3645bbdfc5ebe35726e64caaf588 Mon Sep 17 00:00:00 2001 +From: Richard Weinberger <richard@nod.at> +Date: Mon, 27 Oct 2014 00:46:11 +0100 +Subject: UBI: Fix invalid vfree() + +commit f38aed975c0c3645bbdfc5ebe35726e64caaf588 upstream. + +The logic of vfree()'ing vol->upd_buf is tied to vol->updating. +In ubi_start_update() vol->updating is set long before vmalloc()'ing +vol->upd_buf. If we encounter a write failure in ubi_start_update() +before vmalloc() the UBI device release function will try to vfree() +vol->upd_buf because vol->updating is set. +Fix this by allocating vol->upd_buf directly after setting vol->updating. + +Fixes: +[ 31.559338] UBI warning: vol_cdev_release: update of volume 2 not finished, volume is damaged +[ 31.559340] ------------[ cut here ]------------ +[ 31.559343] WARNING: CPU: 1 PID: 2747 at mm/vmalloc.c:1446 __vunmap+0xe3/0x110() +[ 31.559344] Trying to vfree() nonexistent vm area (ffffc90001f2b000) +[ 31.559345] Modules linked in: +[ 31.565620] 0000000000000bba ffff88002a0cbdb0 ffffffff818f0497 ffff88003b9ba148 +[ 31.566347] ffff88002a0cbde0 ffffffff8156f515 ffff88003b9ba148 0000000000000bba +[ 31.567073] 0000000000000000 0000000000000000 ffff88002a0cbe88 ffffffff8156c10a +[ 31.567793] Call Trace: +[ 31.568034] [<ffffffff818f0497>] dump_stack+0x4e/0x7a +[ 31.568510] [<ffffffff8156f515>] ubi_io_write_vid_hdr+0x155/0x160 +[ 31.569084] [<ffffffff8156c10a>] ubi_eba_write_leb+0x23a/0x870 +[ 31.569628] [<ffffffff81569b36>] vol_cdev_write+0x226/0x380 +[ 31.570155] [<ffffffff81179265>] vfs_write+0xb5/0x1f0 +[ 31.570627] [<ffffffff81179f8a>] SyS_pwrite64+0x6a/0xa0 +[ 31.571123] [<ffffffff818fde12>] system_call_fastpath+0x16/0x1b + +Signed-off-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/mtd/ubi/upd.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/mtd/ubi/upd.c ++++ b/drivers/mtd/ubi/upd.c +@@ -135,6 +135,10 @@ int ubi_start_update(struct ubi_device * + ubi_assert(!vol->updating && !vol->changing_leb); + vol->updating = 1; + ++ vol->upd_buf = vmalloc(ubi->leb_size); ++ if (!vol->upd_buf) ++ return -ENOMEM; ++ + err = set_update_marker(ubi, vol); + if (err) + return err; +@@ -154,14 +158,12 @@ int ubi_start_update(struct ubi_device * + err = clear_update_marker(ubi, vol, 0); + if (err) + return err; ++ ++ vfree(vol->upd_buf); + vol->updating = 0; + return 0; + } + +- vol->upd_buf = vmalloc(ubi->leb_size); +- if (!vol->upd_buf) +- return -ENOMEM; +- + vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1, + vol->usable_leb_size); + vol->upd_bytes = bytes; diff --git a/patches/udf-check-component-length-before-reading-it.patch b/patches/udf-check-component-length-before-reading-it.patch new file mode 100644 index 0000000..877bb78 --- /dev/null +++ b/patches/udf-check-component-length-before-reading-it.patch @@ -0,0 +1,58 @@ +From e237ec37ec154564f8690c5bd1795339955eeef9 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Fri, 19 Dec 2014 14:27:55 +0100 +Subject: udf: Check component length before reading it + +commit e237ec37ec154564f8690c5bd1795339955eeef9 upstream. + +Check that length specified in a component of a symlink fits in the +input buffer we are reading. Also properly ignore component length for +component types that do not use it. Otherwise we read memory after end +of buffer for corrupted udf image. + +Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/udf/symlink.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -42,14 +42,17 @@ static int udf_pc_to_char(struct super_b + tolen--; + while (elen < fromlen) { + pc = (struct pathComponent *)(from + elen); ++ elen += sizeof(struct pathComponent); + switch (pc->componentType) { + case 1: + /* + * Symlink points to some place which should be agreed + * upon between originator and receiver of the media. Ignore. + */ +- if (pc->lengthComponentIdent > 0) ++ if (pc->lengthComponentIdent > 0) { ++ elen += pc->lengthComponentIdent; + break; ++ } + /* Fall through */ + case 2: + if (tolen == 0) +@@ -74,6 +77,9 @@ static int udf_pc_to_char(struct super_b + /* that would be . - just ignore */ + break; + case 5: ++ elen += pc->lengthComponentIdent; ++ if (elen > fromlen) ++ return -EIO; + comp_len = udf_get_filename(sb, pc->componentIdent, + pc->lengthComponentIdent, + p, tolen); +@@ -85,7 +91,6 @@ static int udf_pc_to_char(struct super_b + tolen--; + break; + } +- elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; + } + if (p > to + 1) + p[-1] = '\0'; diff --git a/patches/udf-check-path-length-when-reading-symlink.patch b/patches/udf-check-path-length-when-reading-symlink.patch new file mode 100644 index 0000000..d7f641e --- /dev/null +++ b/patches/udf-check-path-length-when-reading-symlink.patch @@ -0,0 +1,226 @@ +From 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Thu, 18 Dec 2014 22:37:50 +0100 +Subject: udf: Check path length when reading symlink + +commit 0e5cc9a40ada6046e6bc3bdfcd0c0d7e4b706b14 upstream. + +Symlink reading code does not check whether the resulting path fits into +the page provided by the generic code. This isn't as easy as just +checking the symlink size because of various encoding conversions we +perform on path. So we have to check whether there is still enough space +in the buffer on the fly. + +Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no> +Signed-off-by: Jan Kara <jack@suse.cz> +[lizf: Backported to 3.4: udf_get_filename() is called in do_udf_readdir()] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/udf/dir.c | 3 ++- + fs/udf/namei.c | 3 ++- + fs/udf/symlink.c | 31 ++++++++++++++++++++++++++----- + fs/udf/udfdecl.h | 3 ++- + fs/udf/unicode.c | 28 ++++++++++++++++------------ + 5 files changed, 48 insertions(+), 20 deletions(-) + +--- a/fs/udf/dir.c ++++ b/fs/udf/dir.c +@@ -163,7 +163,8 @@ static int do_udf_readdir(struct inode * + struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); + + iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + dt_type = DT_UNKNOWN; + } + +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -233,7 +233,8 @@ static struct fileIdentDesc *udf_find_en + if (!lfi) + continue; + +- flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); ++ flen = udf_get_filename(dir->i_sb, nameptr, lfi, fname, ++ UDF_NAME_LEN); + if (flen && udf_match(flen, fname, child->len, child->name)) + goto out_ok; + } +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -30,13 +30,16 @@ + #include <linux/buffer_head.h> + #include "udf_i.h" + +-static void udf_pc_to_char(struct super_block *sb, unsigned char *from, +- int fromlen, unsigned char *to) ++static int udf_pc_to_char(struct super_block *sb, unsigned char *from, ++ int fromlen, unsigned char *to, int tolen) + { + struct pathComponent *pc; + int elen = 0; ++ int comp_len; + unsigned char *p = to; + ++ /* Reserve one byte for terminating \0 */ ++ tolen--; + while (elen < fromlen) { + pc = (struct pathComponent *)(from + elen); + switch (pc->componentType) { +@@ -49,22 +52,37 @@ static void udf_pc_to_char(struct super_ + break; + /* Fall through */ + case 2: ++ if (tolen == 0) ++ return -ENAMETOOLONG; + p = to; + *p++ = '/'; ++ tolen--; + break; + case 3: ++ if (tolen < 3) ++ return -ENAMETOOLONG; + memcpy(p, "../", 3); + p += 3; ++ tolen -= 3; + break; + case 4: ++ if (tolen < 2) ++ return -ENAMETOOLONG; + memcpy(p, "./", 2); + p += 2; ++ tolen -= 2; + /* that would be . - just ignore */ + break; + case 5: +- p += udf_get_filename(sb, pc->componentIdent, p, +- pc->lengthComponentIdent); ++ comp_len = udf_get_filename(sb, pc->componentIdent, ++ pc->lengthComponentIdent, ++ p, tolen); ++ p += comp_len; ++ tolen -= comp_len; ++ if (tolen == 0) ++ return -ENAMETOOLONG; + *p++ = '/'; ++ tolen--; + break; + } + elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; +@@ -73,6 +91,7 @@ static void udf_pc_to_char(struct super_ + p[-1] = '\0'; + else + p[0] = '\0'; ++ return 0; + } + + static int udf_symlink_filler(struct file *file, struct page *page) +@@ -108,8 +127,10 @@ static int udf_symlink_filler(struct fil + symlink = bh->b_data; + } + +- udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p); ++ err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); + brelse(bh); ++ if (err) ++ goto out_unlock_inode; + + up_read(&iinfo->i_data_sem); + SetPageUptodate(page); +--- a/fs/udf/udfdecl.h ++++ b/fs/udf/udfdecl.h +@@ -207,7 +207,8 @@ udf_get_lb_pblock(struct super_block *sb + } + + /* unicode.c */ +-extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); ++extern int udf_get_filename(struct super_block *, uint8_t *, int, uint8_t *, ++ int); + extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, + int); + extern int udf_build_ustr(struct ustr *, dstring *, int); +--- a/fs/udf/unicode.c ++++ b/fs/udf/unicode.c +@@ -28,7 +28,8 @@ + + #include "udf_sb.h" + +-static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int); ++static int udf_translate_to_linux(uint8_t *, int, uint8_t *, int, uint8_t *, ++ int); + + static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) + { +@@ -333,8 +334,8 @@ try_again: + return u_len + 1; + } + +-int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, +- int flen) ++int udf_get_filename(struct super_block *sb, uint8_t *sname, int slen, ++ uint8_t *dname, int dlen) + { + struct ustr *filename, *unifilename; + int len = 0; +@@ -347,7 +348,7 @@ int udf_get_filename(struct super_block + if (!unifilename) + goto out1; + +- if (udf_build_ustr_exact(unifilename, sname, flen)) ++ if (udf_build_ustr_exact(unifilename, sname, slen)) + goto out2; + + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { +@@ -366,7 +367,8 @@ int udf_get_filename(struct super_block + } else + goto out2; + +- len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, ++ len = udf_translate_to_linux(dname, dlen, ++ filename->u_name, filename->u_len, + unifilename->u_name, unifilename->u_len); + out2: + kfree(unifilename); +@@ -403,10 +405,12 @@ int udf_put_filename(struct super_block + #define EXT_MARK '.' + #define CRC_MARK '#' + #define EXT_SIZE 5 ++/* Number of chars we need to store generated CRC to make filename unique */ ++#define CRC_LEN 5 + +-static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, +- int udfLen, uint8_t *fidName, +- int fidNameLen) ++static int udf_translate_to_linux(uint8_t *newName, int newLen, ++ uint8_t *udfName, int udfLen, ++ uint8_t *fidName, int fidNameLen) + { + int index, newIndex = 0, needsCRC = 0; + int extIndex = 0, newExtIndex = 0, hasExt = 0; +@@ -440,7 +444,7 @@ static int udf_translate_to_linux(uint8_ + newExtIndex = newIndex; + } + } +- if (newIndex < 256) ++ if (newIndex < newLen) + newName[newIndex++] = curr; + else + needsCRC = 1; +@@ -468,13 +472,13 @@ static int udf_translate_to_linux(uint8_ + } + ext[localExtIndex++] = curr; + } +- maxFilenameLen = 250 - localExtIndex; ++ maxFilenameLen = newLen - CRC_LEN - localExtIndex; + if (newIndex > maxFilenameLen) + newIndex = maxFilenameLen; + else + newIndex = newExtIndex; +- } else if (newIndex > 250) +- newIndex = 250; ++ } else if (newIndex > newLen - CRC_LEN) ++ newIndex = newLen - CRC_LEN; + newName[newIndex++] = CRC_MARK; + valueCRC = crc_itu_t(0, fidName, fidNameLen); + newName[newIndex++] = hexChar[(valueCRC & 0xf000) >> 12]; diff --git a/patches/udf-verify-i_size-when-loading-inode.patch b/patches/udf-verify-i_size-when-loading-inode.patch new file mode 100644 index 0000000..c5d276d --- /dev/null +++ b/patches/udf-verify-i_size-when-loading-inode.patch @@ -0,0 +1,42 @@ +From e159332b9af4b04d882dbcfe1bb0117f0a6d4b58 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Fri, 19 Dec 2014 12:03:53 +0100 +Subject: udf: Verify i_size when loading inode + +commit e159332b9af4b04d882dbcfe1bb0117f0a6d4b58 upstream. + +Verify that inode size is sane when loading inode with data stored in +ICB. Otherwise we may get confused later when working with the inode and +inode size is too big. + +Reported-by: Carl Henrik Lunde <chlunde@ping.uio.no> +Signed-off-by: Jan Kara <jack@suse.cz> +[lizf: Backported to 3.4: just return on error, as there's no "out" label] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/udf/inode.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -1392,6 +1392,20 @@ static void udf_fill_inode(struct inode + iinfo->i_lenEAttr; + } + ++ /* Sanity checks for files in ICB so that we don't get confused later */ ++ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { ++ /* ++ * For file in ICB data is stored in allocation descriptor ++ * so sizes should match ++ */ ++ if (iinfo->i_lenAlloc != inode->i_size) ++ return; ++ /* File in ICB has to fit in there... */ ++ if (inode->i_size > inode->i_sb->s_blocksize - ++ udf_file_entry_alloc_offset(inode)) ++ return; ++ } ++ + switch (fe->icbTag.fileType) { + case ICBTAG_FILE_TYPE_DIRECTORY: + inode->i_op = &udf_dir_inode_operations; diff --git a/patches/udf-verify-symlink-size-before-loading-it.patch b/patches/udf-verify-symlink-size-before-loading-it.patch new file mode 100644 index 0000000..e1da5fb --- /dev/null +++ b/patches/udf-verify-symlink-size-before-loading-it.patch @@ -0,0 +1,64 @@ +From a1d47b262952a45aae62bd49cfaf33dd76c11a2c Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Fri, 19 Dec 2014 12:21:47 +0100 +Subject: udf: Verify symlink size before loading it + +commit a1d47b262952a45aae62bd49cfaf33dd76c11a2c upstream. + +UDF specification allows arbitrarily large symlinks. However we support +only symlinks at most one block large. Check the length of the symlink +so that we don't access memory beyond end of the symlink block. + +Reported-by: Carl Henrik Lunde <chlunde@gmail.com> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/udf/symlink.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/fs/udf/symlink.c ++++ b/fs/udf/symlink.c +@@ -80,11 +80,17 @@ static int udf_symlink_filler(struct fil + struct inode *inode = page->mapping->host; + struct buffer_head *bh = NULL; + unsigned char *symlink; +- int err = -EIO; ++ int err; + unsigned char *p = kmap(page); + struct udf_inode_info *iinfo; + uint32_t pos; + ++ /* We don't support symlinks longer than one block */ ++ if (inode->i_size > inode->i_sb->s_blocksize) { ++ err = -ENAMETOOLONG; ++ goto out_unmap; ++ } ++ + iinfo = UDF_I(inode); + pos = udf_block_map(inode, 0); + +@@ -94,8 +100,10 @@ static int udf_symlink_filler(struct fil + } else { + bh = sb_bread(inode->i_sb, pos); + +- if (!bh) +- goto out; ++ if (!bh) { ++ err = -EIO; ++ goto out_unlock_inode; ++ } + + symlink = bh->b_data; + } +@@ -109,9 +117,10 @@ static int udf_symlink_filler(struct fil + unlock_page(page); + return 0; + +-out: ++out_unlock_inode: + up_read(&iinfo->i_data_sem); + SetPageError(page); ++out_unmap: + kunmap(page); + unlock_page(page); + return err; diff --git a/patches/usb-add-otg-pet-device-to-tpl.patch b/patches/usb-add-otg-pet-device-to-tpl.patch new file mode 100644 index 0000000..52de43e --- /dev/null +++ b/patches/usb-add-otg-pet-device-to-tpl.patch @@ -0,0 +1,47 @@ +From e5dff0e80463cc3fa236e898ef1491b40be70b19 Mon Sep 17 00:00:00 2001 +From: Macpaul Lin <macpaul@gmail.com> +Date: Fri, 23 Jan 2015 14:39:02 +0800 +Subject: USB: Add OTG PET device to TPL + +commit e5dff0e80463cc3fa236e898ef1491b40be70b19 upstream. + +OTG device shall support this device for allowing compliance automated testing. +The modification is derived from Pavankumar and Vijayavardhans' previous work. + +Signed-off-by: Macpaul Lin <macpaul@gmail.com> +Cc: Pavankumar Kondeti <pkondeti@codeaurora.org> +Cc: Vijayavardhan Vennapusa <vvreddy@codeaurora.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/core/otg_whitelist.h | 5 +++++ + drivers/usb/core/quirks.c | 4 ++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/usb/core/otg_whitelist.h ++++ b/drivers/usb/core/otg_whitelist.h +@@ -59,6 +59,11 @@ static int is_targeted(struct usb_device + le16_to_cpu(dev->descriptor.idProduct) == 0xbadd)) + return 0; + ++ /* OTG PET device is always targeted (see OTG 2.0 ECN 6.4.2) */ ++ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && ++ le16_to_cpu(dev->descriptor.idProduct) == 0x0200)) ++ return 1; ++ + /* NOTE: can't use usb_match_id() since interface caches + * aren't set up yet. this is cut/paste from that code. + */ +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -175,6 +175,10 @@ static const struct usb_device_id usb_in + { USB_DEVICE(0x0b05, 0x17e0), .driver_info = + USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + ++ /* Protocol and OTG Electrical Test Device */ ++ { USB_DEVICE(0x1a0a, 0x0200), .driver_info = ++ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, ++ + { } /* terminating entry must be last */ + }; + diff --git a/patches/usb-cdc-acm-check-for-valid-interfaces.patch b/patches/usb-cdc-acm-check-for-valid-interfaces.patch new file mode 100644 index 0000000..d2baf18 --- /dev/null +++ b/patches/usb-cdc-acm-check-for-valid-interfaces.patch @@ -0,0 +1,36 @@ +From 403dff4e2c94f275e24fd85f40b2732ffec268a1 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Fri, 7 Nov 2014 08:48:15 -0800 +Subject: USB: cdc-acm: check for valid interfaces + +commit 403dff4e2c94f275e24fd85f40b2732ffec268a1 upstream. + +We need to check that we have both a valid data and control inteface for both +types of headers (union and not union.) + +References: https://bugzilla.kernel.org/show_bug.cgi?id=83551 +Reported-by: Simon Schubert <2+kernel@0x2c.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/class/cdc-acm.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1108,10 +1108,11 @@ next_desc: + } else { + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); +- if (!control_interface || !data_interface) { +- dev_dbg(&intf->dev, "no interfaces\n"); +- return -ENODEV; +- } ++ } ++ ++ if (!control_interface || !data_interface) { ++ dev_dbg(&intf->dev, "no interfaces\n"); ++ return -ENODEV; + } + + if (data_interface_num != call_interface_num) diff --git a/patches/usb-console-fix-potential-use-after-free.patch b/patches/usb-console-fix-potential-use-after-free.patch new file mode 100644 index 0000000..9064616 --- /dev/null +++ b/patches/usb-console-fix-potential-use-after-free.patch @@ -0,0 +1,72 @@ +From 32a4bf2e81ec378e5925d4e069e0677a6c86a6ad Mon Sep 17 00:00:00 2001 +From: Johan Hovold <johan@kernel.org> +Date: Mon, 5 Jan 2015 16:04:13 +0100 +Subject: USB: console: fix potential use after free + +commit 32a4bf2e81ec378e5925d4e069e0677a6c86a6ad upstream. + +Use tty kref to release the fake tty in usb_console_setup to avoid use +after free if the underlying serial driver has acquired a reference. + +Note that using the tty destructor release_one_tty requires some more +state to be initialised. + +Fixes: 4a90f09b20f4 ("tty: usb-serial krefs") +Signed-off-by: Johan Hovold <johan@kernel.org> +[lizf: Backported to 3.4: adjust context] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/serial/console.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/usb/serial/console.c ++++ b/drivers/usb/serial/console.c +@@ -47,6 +47,8 @@ static struct console usbcons; + * ------------------------------------------------------------ + */ + ++static const struct tty_operations usb_console_fake_tty_ops = { ++}; + + /* + * The parsing of the command line works exactly like the +@@ -141,14 +143,17 @@ static int usb_console_setup(struct cons + goto reset_open_count; + } + kref_init(&tty->kref); +- tty_port_tty_set(&port->port, tty); + tty->driver = usb_serial_tty_driver; + tty->index = co->index; ++ INIT_LIST_HEAD(&tty->tty_files); ++ kref_get(&tty->driver->kref); ++ tty->ops = &usb_console_fake_tty_ops + if (tty_init_termios(tty)) { + retval = -ENOMEM; + err("no more memory"); +- goto free_tty; ++ goto put_tty; + } ++ tty_port_tty_set(&port->port, tty); + } + + /* only call the device specific open if this +@@ -170,7 +175,7 @@ static int usb_console_setup(struct cons + serial->type->set_termios(tty, port, &dummy); + + tty_port_tty_set(&port->port, NULL); +- kfree(tty); ++ tty_kref_put(tty); + } + set_bit(ASYNCB_INITIALIZED, &port->port.flags); + } +@@ -186,8 +191,8 @@ static int usb_console_setup(struct cons + + fail: + tty_port_tty_set(&port->port, NULL); +- free_tty: +- kfree(tty); ++ put_tty: ++ tty_kref_put(tty); + reset_open_count: + port->port.count = 0; + usb_autopm_put_interface(serial->interface); diff --git a/patches/usb-core-binterval-quirk.patch b/patches/usb-core-binterval-quirk.patch new file mode 100644 index 0000000..f17848f --- /dev/null +++ b/patches/usb-core-binterval-quirk.patch @@ -0,0 +1,81 @@ +From cd83ce9e6195aa3ea15ab4db92892802c20df5d0 Mon Sep 17 00:00:00 2001 +From: James P Michels III <james.p.michels@gmail.com> +Date: Sun, 27 Jul 2014 13:28:04 -0400 +Subject: usb-core bInterval quirk + +commit cd83ce9e6195aa3ea15ab4db92892802c20df5d0 upstream. + +This patch adds a usb quirk to support devices with interupt endpoints +and bInterval values expressed as microframes. The quirk causes the +parse endpoint function to modify the reported bInterval to a standards +conforming value. + +There is currently code in the endpoint parser that checks for +bIntervals that are outside of the valid range (1-16 for USB 2+ high +speed and super speed interupt endpoints). In this case, the code assumes +the bInterval is being reported in 1ms frames. As well, the correction +is only applied if the original bInterval value is out of the 1-16 range. + +With this quirk applied to the device, the bInterval will be +accurately adjusted from microframes to an exponent. + +Signed-off-by: James P Michels III <james.p.michels@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/core/config.c | 11 +++++++++++ + drivers/usb/core/quirks.c | 4 ++++ + include/linux/usb/quirks.h | 11 +++++++++++ + 3 files changed, 26 insertions(+) + +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -201,6 +201,17 @@ static int usb_parse_endpoint(struct dev + if (n == 0) + n = 9; /* 32 ms = 2^(9-1) uframes */ + j = 16; ++ ++ /* ++ * Adjust bInterval for quirked devices. ++ * This quirk fixes bIntervals reported in ++ * linear microframes. ++ */ ++ if (to_usb_device(ddev)->quirks & ++ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) { ++ n = clamp(fls(d->bInterval), i, j); ++ i = j = n; ++ } + break; + default: /* USB_SPEED_FULL or _LOW */ + /* For low-speed, 10 ms is the official minimum. +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -152,6 +152,10 @@ static const struct usb_device_id usb_qu + /* SKYMEDI USB_DRIVE */ + { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Razer - Razer Blade Keyboard */ ++ { USB_DEVICE(0x1532, 0x0116), .driver_info = ++ USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, ++ + /* BUILDWIN Photo Frame */ + { USB_DEVICE(0x1908, 0x1315), .driver_info = + USB_QUIRK_HONOR_BNUMINTERFACES }, +--- a/include/linux/usb/quirks.h ++++ b/include/linux/usb/quirks.h +@@ -36,4 +36,15 @@ + /* device can't handle device_qualifier descriptor requests */ + #define USB_QUIRK_DEVICE_QUALIFIER 0x00000100 + ++/* ++ * For high speed and super speed interupt endpoints, the USB 2.0 and ++ * USB 3.0 spec require the interval in microframes ++ * (1 microframe = 125 microseconds) to be calculated as ++ * interval = 2 ^ (bInterval-1). ++ * ++ * Devices with this quirk report their bInterval as the result of this ++ * calculation instead of the exponent variable used in the calculation. ++ */ ++#define USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL 0x00000080 ++ + #endif /* __LINUX_USB_QUIRKS_H */ diff --git a/patches/usb-cp210x-add-ids-for-cel-usb-sticks-and-meshworks-devices.patch b/patches/usb-cp210x-add-ids-for-cel-usb-sticks-and-meshworks-devices.patch new file mode 100644 index 0000000..f8e257d --- /dev/null +++ b/patches/usb-cp210x-add-ids-for-cel-usb-sticks-and-meshworks-devices.patch @@ -0,0 +1,33 @@ +From 1ae78a4870989a354028cb17dabf819b595e70e3 Mon Sep 17 00:00:00 2001 +From: David Peterson <david.peterson@cel.com> +Date: Tue, 6 Jan 2015 15:00:52 +0000 +Subject: USB: cp210x: add IDs for CEL USB sticks and MeshWorks devices + +commit 1ae78a4870989a354028cb17dabf819b595e70e3 upstream. + +Added virtual com port VID/PID entries for CEL USB sticks and MeshWorks +devices. + +Signed-off-by: David Peterson <david.peterson@cel.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/serial/cp210x.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -126,10 +126,12 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ +- { USB_DEVICE(0x10C4, 0x8857) }, /* CEL MeshConnect USB Stick */ ++ { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ ++ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ ++ { USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ diff --git a/patches/usb-cp210x-fix-id-for-production-cel-meshconnect-usb-stick.patch b/patches/usb-cp210x-fix-id-for-production-cel-meshconnect-usb-stick.patch new file mode 100644 index 0000000..1ca4615 --- /dev/null +++ b/patches/usb-cp210x-fix-id-for-production-cel-meshconnect-usb-stick.patch @@ -0,0 +1,29 @@ +From 90441b4dbe90ba0c38111ea89fa093a8c9627801 Mon Sep 17 00:00:00 2001 +From: Preston Fick <pffick@gmail.com> +Date: Sat, 27 Dec 2014 01:32:41 -0600 +Subject: USB: cp210x: fix ID for production CEL MeshConnect USB Stick + +commit 90441b4dbe90ba0c38111ea89fa093a8c9627801 upstream. + +Fixing typo for MeshConnect IDs. The original PID (0x8875) is not in +production and is not needed. Instead it has been changed to the +official production PID (0x8857). + +Signed-off-by: Preston Fick <pffick@gmail.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/serial/cp210x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -126,7 +126,7 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ + { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ + { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ +- { USB_DEVICE(0x10C4, 0x8875) }, /* CEL MeshConnect USB Stick */ ++ { USB_DEVICE(0x10C4, 0x8857) }, /* CEL MeshConnect USB Stick */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ diff --git a/patches/usb-dwc3-gadget-stop-trb-preparation-after-limit-is-reached.patch b/patches/usb-dwc3-gadget-stop-trb-preparation-after-limit-is-reached.patch new file mode 100644 index 0000000..735ab97 --- /dev/null +++ b/patches/usb-dwc3-gadget-stop-trb-preparation-after-limit-is-reached.patch @@ -0,0 +1,41 @@ +From 39e60635a01520e8c8ed3946a28c2b98e6a46f79 Mon Sep 17 00:00:00 2001 +From: Amit Virdi <amit.virdi@st.com> +Date: Tue, 13 Jan 2015 14:27:21 +0530 +Subject: usb: dwc3: gadget: Stop TRB preparation after limit is reached + +commit 39e60635a01520e8c8ed3946a28c2b98e6a46f79 upstream. + +DWC3 gadget sets up a pool of 32 TRBs for each EP during initialization. This +means, the max TRBs that can be submitted for an EP is fixed to 32. Since the +request queue for an EP is a linked list, any number of requests can be queued +to it by the gadget layer. However, the dwc3 driver must not submit TRBs more +than the pool it has created for. This limit wasn't respected when SG was used +resulting in submitting more than the max TRBs, eventually leading to +non-transfer of the TRBs submitted over the max limit. + +Root cause: +When SG is used, there are two loops iterating to prepare TRBs: + - Outer loop over the request_list + - Inner loop over the SG list +The code was missing break to get out of the outer loop. + +Fixes: eeb720fb21d6 (usb: dwc3: gadget: add support for SG lists) +Signed-off-by: Amit Virdi <amit.virdi@st.com> +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/dwc3/gadget.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -851,6 +851,9 @@ static void dwc3_prepare_trbs(struct dwc + if (last_one) + break; + } ++ ++ if (last_one) ++ break; + } else { + dma = req->request.dma; + length = req->request.length; diff --git a/patches/usb-renesas_usbhs-gadget-fix-null-pointer-dereference-in-ep_disable.patch b/patches/usb-renesas_usbhs-gadget-fix-null-pointer-dereference-in-ep_disable.patch new file mode 100644 index 0000000..e2ebdcd --- /dev/null +++ b/patches/usb-renesas_usbhs-gadget-fix-null-pointer-dereference-in-ep_disable.patch @@ -0,0 +1,36 @@ +From 11432050f070810ba139d0226344eef120c3a559 Mon Sep 17 00:00:00 2001 +From: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com> +Date: Tue, 4 Nov 2014 10:05:42 +0900 +Subject: usb: renesas_usbhs: gadget: fix NULL pointer dereference in + ep_disable() + +commit 11432050f070810ba139d0226344eef120c3a559 upstream. + +This patch fixes an issue that the NULL pointer dereference happens +when we uses g_audio driver. Since the g_audio driver will call +usb_ep_disable() in afunc_set_alt() before it calls usb_ep_enable(), +the uep->pipe of renesas usbhs driver will be NULL. So, this patch +adds a condition to avoid the oops. + +Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com> +Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com> +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Fixes: 2f98382dc (usb: renesas_usbhs: Add Renesas USBHS Gadget) +Signed-off-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/renesas_usbhs/mod_gadget.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/renesas_usbhs/mod_gadget.c ++++ b/drivers/usb/renesas_usbhs/mod_gadget.c +@@ -672,6 +672,9 @@ static int __usbhsg_ep_set_halt_wedge(st + struct device *dev = usbhsg_gpriv_to_dev(gpriv); + unsigned long flags; + ++ if (!pipe) ++ return -EINVAL; ++ + usbhsg_pipe_disable(uep); + + dev_dbg(dev, "set halt %d (pipe %d)\n", diff --git a/patches/usb-storage-scsi-add-broken_fua-blacklist-flag.patch b/patches/usb-storage-scsi-add-broken_fua-blacklist-flag.patch new file mode 100644 index 0000000..756ab75 --- /dev/null +++ b/patches/usb-storage-scsi-add-broken_fua-blacklist-flag.patch @@ -0,0 +1,95 @@ +From b14bf2d0c0358140041d1c1805a674376964d0e0 Mon Sep 17 00:00:00 2001 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Mon, 30 Jun 2014 11:04:21 -0400 +Subject: usb-storage/SCSI: Add broken_fua blacklist flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit b14bf2d0c0358140041d1c1805a674376964d0e0 upstream. + +Some buggy JMicron USB-ATA bridges don't know how to translate the FUA +bit in READs or WRITEs. This patch adds an entry in unusual_devs.h +and a blacklist flag to tell the sd driver not to use FUA. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Reported-by: Michael Büsch <m@bues.ch> +Tested-by: Michael Büsch <m@bues.ch> +Acked-by: James Bottomley <James.Bottomley@HansenPartnership.com> +CC: Matthew Dharm <mdharm-usb@one-eyed-alien.net> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/scsi/sd.c | 5 ++++- + drivers/usb/storage/scsiglue.c | 4 ++++ + drivers/usb/storage/unusual_devs.h | 7 +++++++ + include/linux/usb_usual.h | 4 +++- + include/scsi/scsi_device.h | 1 + + 5 files changed, 19 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -2238,7 +2238,10 @@ sd_read_cache_type(struct scsi_disk *sdk + } + + sdkp->DPOFUA = (data.device_specific & 0x10) != 0; +- if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { ++ if (sdp->broken_fua) { ++ sd_printk(KERN_NOTICE, sdkp, "Disabling FUA\n"); ++ sdkp->DPOFUA = 0; ++ } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { + sd_printk(KERN_NOTICE, sdkp, + "Uses READ/WRITE(6), disabling FUA\n"); + sdkp->DPOFUA = 0; +--- a/drivers/usb/storage/scsiglue.c ++++ b/drivers/usb/storage/scsiglue.c +@@ -242,6 +242,10 @@ static int slave_configure(struct scsi_d + US_FL_SCM_MULT_TARG)) && + us->protocol == USB_PR_BULK) + us->use_last_sector_hacks = 1; ++ ++ /* A few buggy USB-ATA bridges don't understand FUA */ ++ if (us->fflags & US_FL_BROKEN_FUA) ++ sdev->broken_fua = 1; + } else { + + /* Non-disk-type devices don't need to blacklist any pages +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -1940,6 +1940,13 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + ++/* Reported by Michael Büsch <m@bues.ch> */ ++UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0114, ++ "JMicron", ++ "USB to ATA/ATAPI Bridge", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_BROKEN_FUA ), ++ + /* Reported by Alexandre Oliva <oliva@lsd.ic.unicamp.br> + * JMicron responds to USN and several other SCSI ioctls with a + * residue that causes subsequent I/O requests to fail. */ +--- a/include/linux/usb_usual.h ++++ b/include/linux/usb_usual.h +@@ -64,7 +64,9 @@ + US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \ + /* cannot handle READ_CAPACITY_16 */ \ + US_FLAG(INITIAL_READ10, 0x00100000) \ +- /* Initial READ(10) (and others) must be retried */ ++ /* Initial READ(10) (and others) must be retried */ \ ++ US_FLAG(BROKEN_FUA, 0x01000000) \ ++ /* Cannot handle FUA in WRITE or READ CDBs */ \ + + #define US_FLAG(name, value) US_FL_##name = value , + enum { US_DO_ALL_FLAGS }; +--- a/include/scsi/scsi_device.h ++++ b/include/scsi/scsi_device.h +@@ -153,6 +153,7 @@ struct scsi_device { + unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ + unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ + unsigned is_visible:1; /* is the device visible in sysfs */ ++ unsigned broken_fua:1; /* Don't set FUA bit */ + + DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ + struct list_head event_list; /* asserted events */ diff --git a/patches/usb-storage-scsi-blacklist-fua-on-jmicron-152d-2566-usb-sata-controller.patch b/patches/usb-storage-scsi-blacklist-fua-on-jmicron-152d-2566-usb-sata-controller.patch new file mode 100644 index 0000000..c4e4121 --- /dev/null +++ b/patches/usb-storage-scsi-blacklist-fua-on-jmicron-152d-2566-usb-sata-controller.patch @@ -0,0 +1,51 @@ +From bf5c4136fa5ce471bdbf4cf59a813e32755fd014 Mon Sep 17 00:00:00 2001 +From: Dmitry Nezhevenko <dion@dion.org.ua> +Date: Mon, 12 Jan 2015 19:13:01 +0200 +Subject: usb-storage/SCSI: blacklist FUA on JMicron 152d:2566 USB-SATA + controller + +commit bf5c4136fa5ce471bdbf4cf59a813e32755fd014 upstream. + +It looks like FUA support is broken on JMicron 152d:2566 bridge: + +[223159.885704] sd 7:0:0:0: [sdc] Write Protect is off +[223159.885706] sd 7:0:0:0: [sdc] Mode Sense: 47 00 10 08 +[223159.885942] sd 7:0:0:0: [sdc] Write cache: enabled, read cache: enabled, supports DPO and FUA + +[223283.691677] sd 7:0:0:0: [sdc] +[223283.691680] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE +[223283.691681] sd 7:0:0:0: [sdc] +[223283.691682] Sense Key : Illegal Request [current] +[223283.691684] sd 7:0:0:0: [sdc] +[223283.691685] Add. Sense: Invalid field in cdb +[223283.691686] sd 7:0:0:0: [sdc] CDB: +[223283.691687] Write(10): 2a 08 15 d0 83 0d 00 00 01 00 +[223283.691690] blk_update_request: critical target error, dev sdc, sector 2927892584 + +This patch adds blacklist flag so that sd will not use FUA + +Signed-off-by: Dmitry Nezhevenko <dion@dion.org.ua> +Cc: Phil Dibowitz <phil@ipom.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/usb/storage/unusual_devs.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -1956,6 +1956,13 @@ UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + ++/* Reported by Dmitry Nezhevenko <dion@dion.org.ua> */ ++UNUSUAL_DEV( 0x152d, 0x2566, 0x0114, 0x0114, ++ "JMicron", ++ "USB to ATA/ATAPI Bridge", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_BROKEN_FUA ), ++ + /* Entrega Technologies U1-SC25 (later Xircom PortGear PGSCSI) + * and Mac USB Dock USB-SCSI */ + UNUSUAL_DEV( 0x1645, 0x0007, 0x0100, 0x0133, diff --git a/patches/video-logo-prevent-use-of-logos-after-they-have-been-freed.patch b/patches/video-logo-prevent-use-of-logos-after-they-have-been-freed.patch new file mode 100644 index 0000000..4b3b2d9 --- /dev/null +++ b/patches/video-logo-prevent-use-of-logos-after-they-have-been-freed.patch @@ -0,0 +1,61 @@ +From 92b004d1aa9f367c372511ca0330f58216b25703 Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen <tomi.valkeinen@ti.com> +Date: Thu, 18 Dec 2014 13:40:06 +0200 +Subject: video/logo: prevent use of logos after they have been freed + +commit 92b004d1aa9f367c372511ca0330f58216b25703 upstream. + +If the probe of an fb driver has been deferred due to missing +dependencies, and the probe is later ran when a module is loaded, the +fbdev framework will try to find a logo to use. + +However, the logos are __initdata, and have already been freed. This +causes sometimes page faults, if the logo memory is not mapped, +sometimes other random crashes as the logo data is invalid, and +sometimes nothing, if the fbdev decides to reject the logo (e.g. the +random value depicting the logo's height is too big). + +This patch adds a late_initcall function to mark the logos as freed. In +reality the logos are freed later, and fbdev probe may be ran between +this late_initcall and the freeing of the logos. In that case we will +miss drawing the logo, even if it would be possible. + +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/video/logo/logo.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/drivers/video/logo/logo.c ++++ b/drivers/video/logo/logo.c +@@ -25,6 +25,21 @@ static bool nologo; + module_param(nologo, bool, 0); + MODULE_PARM_DESC(nologo, "Disables startup logo"); + ++/* ++ * Logos are located in the initdata, and will be freed in kernel_init. ++ * Use late_init to mark the logos as freed to prevent any further use. ++ */ ++ ++static bool logos_freed; ++ ++static int __init fb_logo_late_init(void) ++{ ++ logos_freed = true; ++ return 0; ++} ++ ++late_initcall(fb_logo_late_init); ++ + /* logo's are marked __initdata. Use __init_refok to tell + * modpost that it is intended that this function uses data + * marked __initdata. +@@ -33,7 +48,7 @@ const struct linux_logo * __init_refok f + { + const struct linux_logo *logo = NULL; + +- if (nologo) ++ if (nologo || logos_freed) + return NULL; + + if (depth >= 1) { diff --git a/patches/virtio-use-dev_to_virtio-wrapper-in-virtio.patch b/patches/virtio-use-dev_to_virtio-wrapper-in-virtio.patch new file mode 100644 index 0000000..e83f2ea --- /dev/null +++ b/patches/virtio-use-dev_to_virtio-wrapper-in-virtio.patch @@ -0,0 +1,111 @@ +From 9bffdca8c64a72ac54c47a552734ab457bc720d4 Mon Sep 17 00:00:00 2001 +From: Wanlong Gao <gaowanlong@cn.fujitsu.com> +Date: Tue, 11 Dec 2012 11:04:50 +1030 +Subject: virtio: use dev_to_virtio wrapper in virtio + +commit 9bffdca8c64a72ac54c47a552734ab457bc720d4 upstream. + +Use dev_to_virtio wrapper in virtio to make code clearly. + +Cc: Rusty Russell <rusty@rustcorp.com.au> +Cc: "Michael S. Tsirkin" <mst@redhat.com> +Signed-off-by: Wanlong Gao <gaowanlong@cn.fujitsu.com> +Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/virtio/virtio.c | 19 +++++++++---------- + include/linux/virtio.h | 6 +++++- + 2 files changed, 14 insertions(+), 11 deletions(-) + +--- a/drivers/virtio/virtio.c ++++ b/drivers/virtio/virtio.c +@@ -9,33 +9,32 @@ static unsigned int dev_index; + static ssize_t device_show(struct device *_d, + struct device_attribute *attr, char *buf) + { +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + return sprintf(buf, "0x%04x\n", dev->id.device); + } + static ssize_t vendor_show(struct device *_d, + struct device_attribute *attr, char *buf) + { +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + return sprintf(buf, "0x%04x\n", dev->id.vendor); + } + static ssize_t status_show(struct device *_d, + struct device_attribute *attr, char *buf) + { +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); + } + static ssize_t modalias_show(struct device *_d, + struct device_attribute *attr, char *buf) + { +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); +- ++ struct virtio_device *dev = dev_to_virtio(_d); + return sprintf(buf, "virtio:d%08Xv%08X\n", + dev->id.device, dev->id.vendor); + } + static ssize_t features_show(struct device *_d, + struct device_attribute *attr, char *buf) + { +- struct virtio_device *dev = container_of(_d, struct virtio_device, dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + unsigned int i; + ssize_t len = 0; + +@@ -70,7 +69,7 @@ static inline int virtio_id_match(const + static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) + { + unsigned int i; +- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_dv); + const struct virtio_device_id *ids; + + ids = container_of(_dr, struct virtio_driver, driver)->id_table; +@@ -82,7 +81,7 @@ static int virtio_dev_match(struct devic + + static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) + { +- struct virtio_device *dev = container_of(_dv,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_dv); + + return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", + dev->id.device, dev->id.vendor); +@@ -110,7 +109,7 @@ EXPORT_SYMBOL_GPL(virtio_check_driver_of + static int virtio_dev_probe(struct device *_d) + { + int err, i; +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + struct virtio_driver *drv = container_of(dev->dev.driver, + struct virtio_driver, driver); + u32 device_features; +@@ -148,7 +147,7 @@ static int virtio_dev_probe(struct devic + + static int virtio_dev_remove(struct device *_d) + { +- struct virtio_device *dev = container_of(_d,struct virtio_device,dev); ++ struct virtio_device *dev = dev_to_virtio(_d); + struct virtio_driver *drv = container_of(dev->dev.driver, + struct virtio_driver, driver); + +--- a/include/linux/virtio.h ++++ b/include/linux/virtio.h +@@ -75,7 +75,11 @@ struct virtio_device { + void *priv; + }; + +-#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev) ++static inline struct virtio_device *dev_to_virtio(struct device *_dev) ++{ ++ return container_of(_dev, struct virtio_device, dev); ++} ++ + int register_virtio_device(struct virtio_device *dev); + void unregister_virtio_device(struct virtio_device *dev); + diff --git a/patches/virtio_pci-defer-kfree-until-release-callback.patch b/patches/virtio_pci-defer-kfree-until-release-callback.patch new file mode 100644 index 0000000..5630aa1 --- /dev/null +++ b/patches/virtio_pci-defer-kfree-until-release-callback.patch @@ -0,0 +1,59 @@ +From 63bd62a08ca45a0c804c3c89777edc7f76a2d6da Mon Sep 17 00:00:00 2001 +From: Sasha Levin <sasha.levin@oracle.com> +Date: Fri, 2 Jan 2015 14:47:40 -0500 +Subject: virtio_pci: defer kfree until release callback + +commit 63bd62a08ca45a0c804c3c89777edc7f76a2d6da upstream. + +A struct device which has just been unregistered can live on past the +point at which a driver decides to drop it's initial reference to the +kobject gained on allocation. + +This implies that when releasing a virtio device, we can't free a struct +virtio_device until the underlying struct device has been released, +which might not happen immediately on device_unregister(). + +Unfortunately, this is exactly what virtio pci does: +it has an empty release callback, and frees memory immediately +after unregistering the device. + +This causes an easy to reproduce crash if CONFIG_DEBUG_KOBJECT_RELEASE +it enabled. + +To fix, free the memory only once we know the device is gone in the release +callback. + +Signed-off-by: Sasha Levin <sasha.levin@oracle.com> +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +[lizf: Backported to 3.4: adjust filename] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/virtio/virtio_pci.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/virtio/virtio_pci.c ++++ b/drivers/virtio/virtio_pci.c +@@ -624,11 +624,10 @@ static struct virtio_config_ops virtio_p + + static void virtio_pci_release_dev(struct device *_d) + { +- /* +- * No need for a release method as we allocate/free +- * all devices together with the pci devices. +- * Provide an empty one to avoid getting a warning from core. +- */ ++ struct virtio_device *vdev = dev_to_virtio(_d); ++ struct virtio_pci_device *vp_dev = to_vp_device(vdev); ++ ++ kfree(vp_dev); + } + + /* the PCI probing function */ +@@ -716,7 +715,6 @@ static void __devexit virtio_pci_remove( + pci_iounmap(pci_dev, vp_dev->ioaddr); + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); +- kfree(vp_dev); + } + + #ifdef CONFIG_PM diff --git a/patches/virtio_pci-document-why-we-defer-kfree.patch b/patches/virtio_pci-document-why-we-defer-kfree.patch new file mode 100644 index 0000000..ea7825f --- /dev/null +++ b/patches/virtio_pci-document-why-we-defer-kfree.patch @@ -0,0 +1,32 @@ +From a1eb03f546d651a8f39c7d0692b1f7f5b4e7e3cd Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Sun, 4 Jan 2015 17:28:27 +0200 +Subject: virtio_pci: document why we defer kfree + +commit a1eb03f546d651a8f39c7d0692b1f7f5b4e7e3cd upstream. + +The reason we defer kfree until release function is because it's a +general rule for kobjects: kfree of the reference counter itself is only +legal in the release function. + +Previous patch didn't make this clear, document this in code. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +[lizf: Backported to 3.4: adjust filename] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + drivers/virtio/virtio_pci.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/virtio/virtio_pci.c ++++ b/drivers/virtio/virtio_pci.c +@@ -627,6 +627,9 @@ static void virtio_pci_release_dev(struc + struct virtio_device *vdev = dev_to_virtio(_d); + struct virtio_pci_device *vp_dev = to_vp_device(vdev); + ++ /* As struct device is a kobject, it's not safe to ++ * free the memory (including the reference counter itself) ++ * until it's release callback. */ + kfree(vp_dev); + } + diff --git a/patches/vm-add-vm_fault_sigsegv-handling-support.patch b/patches/vm-add-vm_fault_sigsegv-handling-support.patch new file mode 100644 index 0000000..fe81958 --- /dev/null +++ b/patches/vm-add-vm_fault_sigsegv-handling-support.patch @@ -0,0 +1,413 @@ +From 219a047eb9a3cde86b5a341f9f8d4f6cf7e8cd56 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Thu, 29 Jan 2015 10:51:32 -0800 +Subject: vm: add VM_FAULT_SIGSEGV handling support + +commit 33692f27597fcab536d7cbbcc8f52905133e4aa7 upstream. + +The core VM already knows about VM_FAULT_SIGBUS, but cannot return a +"you should SIGSEGV" error, because the SIGSEGV case was generally +handled by the caller - usually the architecture fault handler. + +That results in lots of duplication - all the architecture fault +handlers end up doing very similar "look up vma, check permissions, do +retries etc" - but it generally works. However, there are cases where +the VM actually wants to SIGSEGV, and applications _expect_ SIGSEGV. + +In particular, when accessing the stack guard page, libsigsegv expects a +SIGSEGV. And it usually got one, because the stack growth is handled by +that duplicated architecture fault handler. + +However, when the generic VM layer started propagating the error return +from the stack expansion in commit fee7e49d4514 ("mm: propagate error +from stack expansion even for guard page"), that now exposed the +existing VM_FAULT_SIGBUS result to user space. And user space really +expected SIGSEGV, not SIGBUS. + +To fix that case, we need to add a VM_FAULT_SIGSEGV, and teach all those +duplicate architecture fault handlers about it. They all already have +the code to handle SIGSEGV, so it's about just tying that new return +value to the existing code, but it's all a bit annoying. + +This is the mindless minimal patch to do this. A more extensive patch +would be to try to gather up the mostly shared fault handling logic into +one generic helper routine, and long-term we really should do that +cleanup. + +Just from this patch, you can generally see that most architectures just +copied (directly or indirectly) the old x86 way of doing things, but in +the meantime that original x86 model has been improved to hold the VM +semaphore for shorter times etc and to handle VM_FAULT_RETRY and other +"newer" things, so it would be a good idea to bring all those +improvements to the generic case and teach other architectures about +them too. + +Reported-and-tested-by: Takashi Iwai <tiwai@suse.de> +Tested-by: Jan Engelhardt <jengelh@inai.de> +Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots" +Cc: linux-arch@vger.kernel.org +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[bwh: Backported to 3.2: + - Adjust filenames, context + - Drop arc, metag, nios2 and lustre changes + - For sh, patch both 32-bit and 64-bit implementations to use goto bad_area + - For s390, pass int_code and trans_exc_code as arguments to do_no_context() + and do_sigsegv()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +[lizf: Backported to 3.4: adjust context in arch/power/mm/fault.c] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/alpha/mm/fault.c | 2 ++ + arch/avr32/mm/fault.c | 2 ++ + arch/cris/mm/fault.c | 2 ++ + arch/frv/mm/fault.c | 2 ++ + arch/ia64/mm/fault.c | 2 ++ + arch/m32r/mm/fault.c | 2 ++ + arch/m68k/mm/fault.c | 2 ++ + arch/microblaze/mm/fault.c | 2 ++ + arch/mips/mm/fault.c | 2 ++ + arch/mn10300/mm/fault.c | 2 ++ + arch/openrisc/mm/fault.c | 2 ++ + arch/parisc/mm/fault.c | 2 ++ + arch/powerpc/mm/fault.c | 6 +++++- + arch/powerpc/platforms/cell/spu_fault.c | 2 +- + arch/s390/mm/fault.c | 7 +++++++ + arch/score/mm/fault.c | 2 ++ + arch/sh/mm/fault_32.c | 2 ++ + arch/sh/mm/tlbflush_64.c | 2 ++ + arch/sparc/mm/fault_32.c | 2 ++ + arch/sparc/mm/fault_64.c | 2 ++ + arch/tile/mm/fault.c | 2 ++ + arch/um/kernel/trap.c | 2 ++ + arch/x86/mm/fault.c | 2 ++ + arch/xtensa/mm/fault.c | 2 ++ + include/linux/mm.h | 5 +++-- + mm/ksm.c | 2 +- + mm/memory.c | 4 ++-- + 27 files changed, 61 insertions(+), 7 deletions(-) + +--- a/arch/alpha/mm/fault.c ++++ b/arch/alpha/mm/fault.c +@@ -149,6 +149,8 @@ do_page_fault(unsigned long address, uns + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/avr32/mm/fault.c ++++ b/arch/avr32/mm/fault.c +@@ -136,6 +136,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/cris/mm/fault.c ++++ b/arch/cris/mm/fault.c +@@ -167,6 +167,8 @@ do_page_fault(unsigned long address, str + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/frv/mm/fault.c ++++ b/arch/frv/mm/fault.c +@@ -166,6 +166,8 @@ asmlinkage void do_page_fault(int datamm + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/ia64/mm/fault.c ++++ b/arch/ia64/mm/fault.c +@@ -162,6 +162,8 @@ ia64_do_page_fault (unsigned long addres + */ + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto bad_area; + } else if (fault & VM_FAULT_SIGBUS) { + signal = SIGBUS; + goto bad_area; +--- a/arch/m32r/mm/fault.c ++++ b/arch/m32r/mm/fault.c +@@ -198,6 +198,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/m68k/mm/fault.c ++++ b/arch/m68k/mm/fault.c +@@ -146,6 +146,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto map_err; + else if (fault & VM_FAULT_SIGBUS) + goto bus_err; + BUG(); +--- a/arch/microblaze/mm/fault.c ++++ b/arch/microblaze/mm/fault.c +@@ -214,6 +214,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/mips/mm/fault.c ++++ b/arch/mips/mm/fault.c +@@ -155,6 +155,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/mn10300/mm/fault.c ++++ b/arch/mn10300/mm/fault.c +@@ -255,6 +255,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/openrisc/mm/fault.c ++++ b/arch/openrisc/mm/fault.c +@@ -163,6 +163,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/parisc/mm/fault.c ++++ b/arch/parisc/mm/fault.c +@@ -210,6 +210,8 @@ good_area: + */ + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto bad_area; + BUG(); +--- a/arch/powerpc/mm/fault.c ++++ b/arch/powerpc/mm/fault.c +@@ -419,7 +419,11 @@ good_area: + */ + fault = handle_mm_fault(mm, vma, address, flags); + if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) { +- int rc = mm_fault_error(regs, address, fault); ++ int rc; ++ ++ if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; ++ rc = mm_fault_error(regs, address, fault); + if (rc >= MM_FAULT_RETURN) + return rc; + } +--- a/arch/powerpc/platforms/cell/spu_fault.c ++++ b/arch/powerpc/platforms/cell/spu_fault.c +@@ -75,7 +75,7 @@ int spu_handle_mm_fault(struct mm_struct + if (*flt & VM_FAULT_OOM) { + ret = -ENOMEM; + goto out_unlock; +- } else if (*flt & VM_FAULT_SIGBUS) { ++ } else if (*flt & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) { + ret = -EFAULT; + goto out_unlock; + } +--- a/arch/s390/mm/fault.c ++++ b/arch/s390/mm/fault.c +@@ -237,6 +237,13 @@ static noinline void do_fault_error(stru + do_no_context(regs); + else + pagefault_out_of_memory(); ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ /* Kernel mode? Handle exceptions or die */ ++ if (!user_mode(regs)) ++ do_no_context(regs, int_code, trans_exc_code); ++ else ++ do_sigsegv(regs, int_code, SEGV_MAPERR, ++ trans_exc_code); + } else if (fault & VM_FAULT_SIGBUS) { + /* Kernel mode? Handle exceptions or die */ + if (!(regs->psw.mask & PSW_MASK_PSTATE)) +--- a/arch/score/mm/fault.c ++++ b/arch/score/mm/fault.c +@@ -110,6 +110,8 @@ survive: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/sh/mm/fault_32.c ++++ b/arch/sh/mm/fault_32.c +@@ -206,6 +206,8 @@ good_area: + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + BUG(); + } + if (fault & VM_FAULT_MAJOR) { +--- a/arch/sh/mm/tlbflush_64.c ++++ b/arch/sh/mm/tlbflush_64.c +@@ -194,6 +194,8 @@ good_area: + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + BUG(); + } + +--- a/arch/sparc/mm/fault_32.c ++++ b/arch/sparc/mm/fault_32.c +@@ -300,6 +300,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/sparc/mm/fault_64.c ++++ b/arch/sparc/mm/fault_64.c +@@ -443,6 +443,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/tile/mm/fault.c ++++ b/arch/tile/mm/fault.c +@@ -433,6 +433,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/arch/um/kernel/trap.c ++++ b/arch/um/kernel/trap.c +@@ -69,6 +69,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) { + goto out_of_memory; ++ } else if (fault & VM_FAULT_SIGSEGV) { ++ goto out; + } else if (fault & VM_FAULT_SIGBUS) { + err = -EACCES; + goto out; +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -887,6 +887,8 @@ mm_fault_error(struct pt_regs *regs, uns + if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| + VM_FAULT_HWPOISON_LARGE)) + do_sigbus(regs, error_code, address, fault); ++ else if (fault & VM_FAULT_SIGSEGV) ++ bad_area_nosemaphore(regs, error_code, address); + else + BUG(); + } +--- a/arch/xtensa/mm/fault.c ++++ b/arch/xtensa/mm/fault.c +@@ -108,6 +108,8 @@ good_area: + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; ++ else if (fault & VM_FAULT_SIGSEGV) ++ goto bad_area; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -841,6 +841,7 @@ static inline int page_mapped(struct pag + #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */ + #define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned small page */ + #define VM_FAULT_HWPOISON_LARGE 0x0020 /* Hit poisoned large page. Index encoded in upper bits */ ++#define VM_FAULT_SIGSEGV 0x0040 + + #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */ + #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */ +@@ -848,8 +849,8 @@ static inline int page_mapped(struct pag + + #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */ + +-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \ +- VM_FAULT_HWPOISON_LARGE) ++#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ ++ VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE) + + /* Encode hstate index for a hwpoisoned large page */ + #define VM_FAULT_SET_HINDEX(x) ((x) << 12) +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -342,7 +342,7 @@ static int break_ksm(struct vm_area_stru + else + ret = VM_FAULT_WRITE; + put_page(page); +- } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_OOM))); ++ } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM))); + /* + * We must loop because handle_mm_fault() may back out if there's + * any difficulty e.g. if pte accessed bit gets updated concurrently. +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1787,7 +1787,7 @@ int __get_user_pages(struct task_struct + else + return -EFAULT; + } +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) + return i ? i : -EFAULT; + BUG(); + } +@@ -1891,7 +1891,7 @@ int fixup_user_fault(struct task_struct + return -ENOMEM; + if (ret & (VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE)) + return -EHWPOISON; +- if (ret & VM_FAULT_SIGBUS) ++ if (ret & (VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV)) + return -EFAULT; + BUG(); + } diff --git a/patches/vm-make-stack-guard-page-errors-return-vm_fault_sigsegv-rather-than-sigbus.patch b/patches/vm-make-stack-guard-page-errors-return-vm_fault_sigsegv-rather-than-sigbus.patch new file mode 100644 index 0000000..f87c629 --- /dev/null +++ b/patches/vm-make-stack-guard-page-errors-return-vm_fault_sigsegv-rather-than-sigbus.patch @@ -0,0 +1,40 @@ +From 9c145c56d0c8a0b62e48c8d71e055ad0fb2012ba Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Thu, 29 Jan 2015 11:15:17 -0800 +Subject: vm: make stack guard page errors return VM_FAULT_SIGSEGV rather than + SIGBUS + +commit 9c145c56d0c8a0b62e48c8d71e055ad0fb2012ba upstream. + +The stack guard page error case has long incorrectly caused a SIGBUS +rather than a SIGSEGV, but nobody actually noticed until commit +fee7e49d4514 ("mm: propagate error from stack expansion even for guard +page") because that error case was never actually triggered in any +normal situations. + +Now that we actually report the error, people noticed the wrong signal +that resulted. So far, only the test suite of libsigsegv seems to have +actually cared, but there are real applications that use libsigsegv, so +let's not wait for any of those to break. + +Reported-and-tested-by: Takashi Iwai <tiwai@suse.de> +Tested-by: Jan Engelhardt <jengelh@inai.de> +Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> # "s390 still compiles and boots" +Cc: linux-arch@vger.kernel.org +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + mm/memory.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -3175,7 +3175,7 @@ static int do_anonymous_page(struct mm_s + + /* Check if we need to add a guard page to the stack */ + if (check_stack_guard_page(vma, address) < 0) +- return VM_FAULT_SIGBUS; ++ return VM_FAULT_SIGSEGV; + + /* Use the zero-page for reads */ + if (!(flags & FAULT_FLAG_WRITE)) { diff --git a/patches/writeback-fix-a-subtle-race-condition-in-i_dirty-clearing.patch b/patches/writeback-fix-a-subtle-race-condition-in-i_dirty-clearing.patch new file mode 100644 index 0000000..6e38b4f --- /dev/null +++ b/patches/writeback-fix-a-subtle-race-condition-in-i_dirty-clearing.patch @@ -0,0 +1,123 @@ +From 9c6ac78eb3521c5937b2dd8a7d1b300f41092f45 Mon Sep 17 00:00:00 2001 +From: Tejun Heo <tj@kernel.org> +Date: Fri, 24 Oct 2014 15:38:21 -0400 +Subject: writeback: fix a subtle race condition in I_DIRTY clearing + +commit 9c6ac78eb3521c5937b2dd8a7d1b300f41092f45 upstream. + +After invoking ->dirty_inode(), __mark_inode_dirty() does smp_mb() and +tests inode->i_state locklessly to see whether it already has all the +necessary I_DIRTY bits set. The comment above the barrier doesn't +contain any useful information - memory barriers can't ensure "changes +are seen by all cpus" by itself. + +And it sure enough was broken. Please consider the following +scenario. + + CPU 0 CPU 1 + ------------------------------------------------------------------------------- + + enters __writeback_single_inode() + grabs inode->i_lock + tests PAGECACHE_TAG_DIRTY which is clear + enters __set_page_dirty() + grabs mapping->tree_lock + sets PAGECACHE_TAG_DIRTY + releases mapping->tree_lock + leaves __set_page_dirty() + + enters __mark_inode_dirty() + smp_mb() + sees I_DIRTY_PAGES set + leaves __mark_inode_dirty() + clears I_DIRTY_PAGES + releases inode->i_lock + +Now @inode has dirty pages w/ I_DIRTY_PAGES clear. This doesn't seem +to lead to an immediately critical problem because requeue_inode() +later checks PAGECACHE_TAG_DIRTY instead of I_DIRTY_PAGES when +deciding whether the inode needs to be requeued for IO and there are +enough unintentional memory barriers inbetween, so while the inode +ends up with inconsistent I_DIRTY_PAGES flag, it doesn't fall off the +IO list. + +The lack of explicit barrier may also theoretically affect the other +I_DIRTY bits which deal with metadata dirtiness. There is no +guarantee that a strong enough barrier exists between +I_DIRTY_[DATA]SYNC clearing and write_inode() writing out the dirtied +inode. Filesystem inode writeout path likely has enough stuff which +can behave as full barrier but it's theoretically possible that the +writeout may not see all the updates from ->dirty_inode(). + +Fix it by adding an explicit smp_mb() after I_DIRTY clearing. Note +that I_DIRTY_PAGES needs a special treatment as it always needs to be +cleared to be interlocked with the lockless test on +__mark_inode_dirty() side. It's cleared unconditionally and +reinstated after smp_mb() if the mapping still has dirty pages. + +Also add comments explaining how and why the barriers are paired. + +Lightly tested. + +Signed-off-by: Tejun Heo <tj@kernel.org> +Cc: Jan Kara <jack@suse.cz> +Cc: Mikulas Patocka <mpatocka@redhat.com> +Cc: Jens Axboe <axboe@kernel.dk> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Reviewed-by: Jan Kara <jack@suse.cz> +Signed-off-by: Jens Axboe <axboe@fb.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/fs-writeback.c | 29 ++++++++++++++++++++++------- + 1 file changed, 22 insertions(+), 7 deletions(-) + +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -424,12 +424,28 @@ writeback_single_inode(struct inode *ino + * write_inode() + */ + spin_lock(&inode->i_lock); +- /* Clear I_DIRTY_PAGES if we've written out all dirty pages */ +- if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) +- inode->i_state &= ~I_DIRTY_PAGES; ++ + dirty = inode->i_state & I_DIRTY; +- inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); ++ inode->i_state &= ~I_DIRTY; ++ ++ /* ++ * Paired with smp_mb() in __mark_inode_dirty(). This allows ++ * __mark_inode_dirty() to test i_state without grabbing i_lock - ++ * either they see the I_DIRTY bits cleared or we see the dirtied ++ * inode. ++ * ++ * I_DIRTY_PAGES is always cleared together above even if @mapping ++ * still has dirty pages. The flag is reinstated after smp_mb() if ++ * necessary. This guarantees that either __mark_inode_dirty() ++ * sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY. ++ */ ++ smp_mb(); ++ ++ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) ++ inode->i_state |= I_DIRTY_PAGES; ++ + spin_unlock(&inode->i_lock); ++ + /* Don't write the inode if only I_DIRTY_PAGES was set */ + if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { + int err = write_inode(inode, wbc); +@@ -1075,12 +1091,11 @@ void __mark_inode_dirty(struct inode *in + } + + /* +- * make sure that changes are seen by all cpus before we test i_state +- * -- mikulas ++ * Paired with smp_mb() in __writeback_single_inode() for the ++ * following lockless i_state test. See there for details. + */ + smp_mb(); + +- /* avoid the locking if we can */ + if ((inode->i_state & flags) == flags) + return; + diff --git a/patches/writeback-move-i_dirty_pages-handling.patch b/patches/writeback-move-i_dirty_pages-handling.patch new file mode 100644 index 0000000..8c1ab43 --- /dev/null +++ b/patches/writeback-move-i_dirty_pages-handling.patch @@ -0,0 +1,51 @@ +From 6290be1c1dc6589eeda213aa40946b27fa4faac8 Mon Sep 17 00:00:00 2001 +From: Jan Kara <jack@suse.cz> +Date: Thu, 3 May 2012 14:47:57 +0200 +Subject: writeback: Move I_DIRTY_PAGES handling + +commit 6290be1c1dc6589eeda213aa40946b27fa4faac8 upstream. + +Instead of clearing I_DIRTY_PAGES and resetting it when we didn't succeed in +writing them all, just clear the bit only when we succeeded writing all the +pages. We also move the clearing of the bit close to other i_state handling to +separate it from writeback list handling. This is desirable because list +handling will differ for flusher thread and other writeback_single_inode() +callers in future. No filesystem plays any tricks with I_DIRTY_PAGES (like +checking it in ->writepages or ->write_inode implementation) so this movement +is safe. + +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + fs/fs-writeback.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -402,7 +402,6 @@ writeback_single_inode(struct inode *ino + + /* Set I_SYNC, reset I_DIRTY_PAGES */ + inode->i_state |= I_SYNC; +- inode->i_state &= ~I_DIRTY_PAGES; + spin_unlock(&inode->i_lock); + spin_unlock(&wb->list_lock); + +@@ -425,6 +424,9 @@ writeback_single_inode(struct inode *ino + * write_inode() + */ + spin_lock(&inode->i_lock); ++ /* Clear I_DIRTY_PAGES if we've written out all dirty pages */ ++ if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) ++ inode->i_state &= ~I_DIRTY_PAGES; + dirty = inode->i_state & I_DIRTY; + inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); + spin_unlock(&inode->i_lock); +@@ -453,7 +455,6 @@ writeback_single_inode(struct inode *ino + * We didn't write back all the pages. nfs_writepages() + * sometimes bales out without doing anything. + */ +- inode->i_state |= I_DIRTY_PAGES; + if (wbc->nr_to_write <= 0) { + /* + * slice used up: queue for next turn diff --git a/patches/x86-hyperv-mark-the-hyper-v-clocksource-as-being-continuous.patch b/patches/x86-hyperv-mark-the-hyper-v-clocksource-as-being-continuous.patch new file mode 100644 index 0000000..eef6daf --- /dev/null +++ b/patches/x86-hyperv-mark-the-hyper-v-clocksource-as-being-continuous.patch @@ -0,0 +1,32 @@ +From 32c6590d126836a062b3140ed52d898507987017 Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Mon, 12 Jan 2015 16:26:02 -0800 +Subject: x86, hyperv: Mark the Hyper-V clocksource as being continuous + +commit 32c6590d126836a062b3140ed52d898507987017 upstream. + +The Hyper-V clocksource is continuous; mark it accordingly. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Acked-by: jasowang@redhat.com +Cc: gregkh@linuxfoundation.org +Cc: devel@linuxdriverproject.org +Cc: olaf@aepfle.de +Cc: apw@canonical.com +Link: http://lkml.kernel.org/r/1421108762-3331-1-git-send-email-kys@microsoft.com +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/kernel/cpu/mshyperv.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/kernel/cpu/mshyperv.c ++++ b/arch/x86/kernel/cpu/mshyperv.c +@@ -55,6 +55,7 @@ static struct clocksource hyperv_cs = { + .rating = 400, /* use this when running on Hyperv*/ + .read = read_hv_clock, + .mask = CLOCKSOURCE_MASK(64), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, + }; + + static void __init ms_hyperv_init_platform(void) diff --git a/patches/x86-tls-disallow-unusual-tls-segments.patch b/patches/x86-tls-disallow-unusual-tls-segments.patch new file mode 100644 index 0000000..cb3a728 --- /dev/null +++ b/patches/x86-tls-disallow-unusual-tls-segments.patch @@ -0,0 +1,64 @@ +From 0e58af4e1d2166e9e33375a0f121e4867010d4f8 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski <luto@amacapital.net> +Date: Thu, 4 Dec 2014 16:48:17 -0800 +Subject: x86/tls: Disallow unusual TLS segments + +commit 0e58af4e1d2166e9e33375a0f121e4867010d4f8 upstream. + +Users have no business installing custom code segments into the +GDT, and segments that are not present but are otherwise valid +are a historical source of interesting attacks. + +For completeness, block attempts to set the L bit. (Prior to +this patch, the L bit would have been silently dropped.) + +This is an ABI break. I've checked glibc, musl, and Wine, and +none of them look like they'll have any trouble. + +Note to stable maintainers: this is a hardening patch that fixes +no known bugs. Given the possibility of ABI issues, this +probably shouldn't be backported quickly. + +Signed-off-by: Andy Lutomirski <luto@amacapital.net> +Acked-by: H. Peter Anvin <hpa@zytor.com> +Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: security@kernel.org <security@kernel.org> +Cc: Willy Tarreau <w@1wt.eu> +Signed-off-by: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/kernel/tls.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/arch/x86/kernel/tls.c ++++ b/arch/x86/kernel/tls.c +@@ -60,6 +60,28 @@ static bool tls_desc_okay(const struct u + if (!info->seg_32bit) + return false; + ++ /* Only allow data segments in the TLS array. */ ++ if (info->contents > 1) ++ return false; ++ ++ /* ++ * Non-present segments with DPL 3 present an interesting attack ++ * surface. The kernel should handle such segments correctly, ++ * but TLS is very difficult to protect in a sandbox, so prevent ++ * such segments from being created. ++ * ++ * If userspace needs to remove a TLS entry, it can still delete ++ * it outright. ++ */ ++ if (info->seg_not_present) ++ return false; ++ ++#ifdef CONFIG_X86_64 ++ /* The L bit makes no sense for data. */ ++ if (info->lm) ++ return false; ++#endif ++ + return true; + } + diff --git a/patches/x86-tls-don-t-validate-lm-in-set_thread_area-after-all.patch b/patches/x86-tls-don-t-validate-lm-in-set_thread_area-after-all.patch new file mode 100644 index 0000000..f9f025b --- /dev/null +++ b/patches/x86-tls-don-t-validate-lm-in-set_thread_area-after-all.patch @@ -0,0 +1,72 @@ +From 3fb2f4237bb452eb4e98f6a5dbd5a445b4fed9d0 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski <luto@amacapital.net> +Date: Wed, 17 Dec 2014 14:48:30 -0800 +Subject: x86/tls: Don't validate lm in set_thread_area() after all + +commit 3fb2f4237bb452eb4e98f6a5dbd5a445b4fed9d0 upstream. + +It turns out that there's a lurking ABI issue. GCC, when +compiling this in a 32-bit program: + +struct user_desc desc = { + .entry_number = idx, + .base_addr = base, + .limit = 0xfffff, + .seg_32bit = 1, + .contents = 0, /* Data, grow-up */ + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 0, +}; + +will leave .lm uninitialized. This means that anything in the +kernel that reads user_desc.lm for 32-bit tasks is unreliable. + +Revert the .lm check in set_thread_area(). The value never did +anything in the first place. + +Fixes: 0e58af4e1d21 ("x86/tls: Disallow unusual TLS segments") +Signed-off-by: Andy Lutomirski <luto@amacapital.net> +Acked-by: Thomas Gleixner <tglx@linutronix.de> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Link: http://lkml.kernel.org/r/d7875b60e28c512f6a6fc0baf5714d58e7eaadbb.1418856405.git.luto@amacapital.net +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[lizf: Backported to 3.4: adjust filename] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/include/asm/ldt.h | 7 +++++++ + arch/x86/kernel/tls.c | 6 ------ + 2 files changed, 7 insertions(+), 6 deletions(-) + +--- a/arch/x86/include/asm/ldt.h ++++ b/arch/x86/include/asm/ldt.h +@@ -28,6 +28,13 @@ struct user_desc { + unsigned int seg_not_present:1; + unsigned int useable:1; + #ifdef __x86_64__ ++ /* ++ * Because this bit is not present in 32-bit user code, user ++ * programs can pass uninitialized values here. Therefore, in ++ * any context in which a user_desc comes from a 32-bit program, ++ * the kernel must act as though lm == 0, regardless of the ++ * actual value. ++ */ + unsigned int lm:1; + #endif + }; +--- a/arch/x86/kernel/tls.c ++++ b/arch/x86/kernel/tls.c +@@ -76,12 +76,6 @@ static bool tls_desc_okay(const struct u + if (info->seg_not_present) + return false; + +-#ifdef CONFIG_X86_64 +- /* The L bit makes no sense for data. */ +- if (info->lm) +- return false; +-#endif +- + return true; + } + diff --git a/patches/x86-um-actually-mark-system-call-tables-readonly.patch b/patches/x86-um-actually-mark-system-call-tables-readonly.patch new file mode 100644 index 0000000..e6bea37 --- /dev/null +++ b/patches/x86-um-actually-mark-system-call-tables-readonly.patch @@ -0,0 +1,61 @@ +From b485342bd79af363c77ef1a421c4a0aef2de9812 Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann <dborkman@redhat.com> +Date: Sat, 3 Jan 2015 13:11:10 +0100 +Subject: x86, um: actually mark system call tables readonly + +commit b485342bd79af363c77ef1a421c4a0aef2de9812 upstream. + +Commit a074335a370e ("x86, um: Mark system call tables readonly") was +supposed to mark the sys_call_table in UML as RO by adding the const, +but it doesn't have the desired effect as it's nevertheless being placed +into the data section since __cacheline_aligned enforces sys_call_table +being placed into .data..cacheline_aligned instead. We need to use +the ____cacheline_aligned version instead to fix this issue. + +Before: + +$ nm -v arch/x86/um/sys_call_table_64.o | grep -1 "sys_call_table" + U sys_writev +0000000000000000 D sys_call_table +0000000000000000 D syscall_table_size + +After: + +$ nm -v arch/x86/um/sys_call_table_64.o | grep -1 "sys_call_table" + U sys_writev +0000000000000000 R sys_call_table +0000000000000000 D syscall_table_size + +Fixes: a074335a370e ("x86, um: Mark system call tables readonly") +Cc: H. Peter Anvin <hpa@zytor.com> +Cc: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Daniel Borkmann <dborkman@redhat.com> +Signed-off-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/um/sys_call_table_32.c | 2 +- + arch/x86/um/sys_call_table_64.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/um/sys_call_table_32.c ++++ b/arch/x86/um/sys_call_table_32.c +@@ -43,7 +43,7 @@ typedef asmlinkage void (*sys_call_ptr_t + + extern asmlinkage void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. +--- a/arch/x86/um/sys_call_table_64.c ++++ b/arch/x86/um/sys_call_table_64.c +@@ -48,7 +48,7 @@ typedef void (*sys_call_ptr_t)(void); + + extern void sys_ni_syscall(void); + +-const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { ++const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = { + /* + * Smells like a compiler bug -- it doesn't work + * when the & below is removed. diff --git a/patches/x86_64-switch_to-load-tls-descriptors-before-switching-ds-and-es.patch b/patches/x86_64-switch_to-load-tls-descriptors-before-switching-ds-and-es.patch new file mode 100644 index 0000000..9d26dc9 --- /dev/null +++ b/patches/x86_64-switch_to-load-tls-descriptors-before-switching-ds-and-es.patch @@ -0,0 +1,306 @@ +From f647d7c155f069c1a068030255c300663516420e Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski <luto@amacapital.net> +Date: Mon, 8 Dec 2014 13:55:20 -0800 +Subject: x86_64, switch_to(): Load TLS descriptors before switching DS and ES + +commit f647d7c155f069c1a068030255c300663516420e upstream. + +Otherwise, if buggy user code points DS or ES into the TLS +array, they would be corrupted after a context switch. + +This also significantly improves the comments and documents some +gotchas in the code. + +Before this patch, the both tests below failed. With this +patch, the es test passes, although the gsbase test still fails. + + ----- begin es test ----- + +/* + * Copyright (c) 2014 Andy Lutomirski + * GPL v2 + */ + +static unsigned short GDT3(int idx) +{ + return (idx << 3) | 3; +} + +static int create_tls(int idx, unsigned int base) +{ + struct user_desc desc = { + .entry_number = idx, + .base_addr = base, + .limit = 0xfffff, + .seg_32bit = 1, + .contents = 0, /* Data, grow-up */ + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 0, + }; + + if (syscall(SYS_set_thread_area, &desc) != 0) + err(1, "set_thread_area"); + + return desc.entry_number; +} + +int main() +{ + int idx = create_tls(-1, 0); + printf("Allocated GDT index %d\n", idx); + + unsigned short orig_es; + asm volatile ("mov %%es,%0" : "=rm" (orig_es)); + + int errors = 0; + int total = 1000; + for (int i = 0; i < total; i++) { + asm volatile ("mov %0,%%es" : : "rm" (GDT3(idx))); + usleep(100); + + unsigned short es; + asm volatile ("mov %%es,%0" : "=rm" (es)); + asm volatile ("mov %0,%%es" : : "rm" (orig_es)); + if (es != GDT3(idx)) { + if (errors == 0) + printf("[FAIL]\tES changed from 0x%hx to 0x%hx\n", + GDT3(idx), es); + errors++; + } + } + + if (errors) { + printf("[FAIL]\tES was corrupted %d/%d times\n", errors, total); + return 1; + } else { + printf("[OK]\tES was preserved\n"); + return 0; + } +} + + ----- end es test ----- + + ----- begin gsbase test ----- + +/* + * gsbase.c, a gsbase test + * Copyright (c) 2014 Andy Lutomirski + * GPL v2 + */ + +static unsigned char *testptr, *testptr2; + +static unsigned char read_gs_testvals(void) +{ + unsigned char ret; + asm volatile ("movb %%gs:%1, %0" : "=r" (ret) : "m" (*testptr)); + return ret; +} + +int main() +{ + int errors = 0; + + testptr = mmap((void *)0x200000000UL, 1, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + if (testptr == MAP_FAILED) + err(1, "mmap"); + + testptr2 = mmap((void *)0x300000000UL, 1, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + if (testptr2 == MAP_FAILED) + err(1, "mmap"); + + *testptr = 0; + *testptr2 = 1; + + if (syscall(SYS_arch_prctl, ARCH_SET_GS, + (unsigned long)testptr2 - (unsigned long)testptr) != 0) + err(1, "ARCH_SET_GS"); + + usleep(100); + + if (read_gs_testvals() == 1) { + printf("[OK]\tARCH_SET_GS worked\n"); + } else { + printf("[FAIL]\tARCH_SET_GS failed\n"); + errors++; + } + + asm volatile ("mov %0,%%gs" : : "r" (0)); + + if (read_gs_testvals() == 0) { + printf("[OK]\tWriting 0 to gs worked\n"); + } else { + printf("[FAIL]\tWriting 0 to gs failed\n"); + errors++; + } + + usleep(100); + + if (read_gs_testvals() == 0) { + printf("[OK]\tgsbase is still zero\n"); + } else { + printf("[FAIL]\tgsbase was corrupted\n"); + errors++; + } + + return errors == 0 ? 0 : 1; +} + + ----- end gsbase test ----- + +Signed-off-by: Andy Lutomirski <luto@amacapital.net> +Cc: Andi Kleen <andi@firstfloor.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Link: http://lkml.kernel.org/r/509d27c9fec78217691c3dad91cec87e1006b34a.1418075657.git.luto@amacapital.net +Signed-off-by: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/kernel/process_64.c | 101 +++++++++++++++++++++++++++++++------------ + 1 file changed, 73 insertions(+), 28 deletions(-) + +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -286,24 +286,9 @@ __switch_to(struct task_struct *prev_p, + + fpu = switch_fpu_prepare(prev_p, next_p, cpu); + +- /* +- * Reload esp0, LDT and the page table pointer: +- */ ++ /* Reload esp0 and ss1. */ + load_sp0(tss, next); + +- /* +- * Switch DS and ES. +- * This won't pick up thread selector changes, but I guess that is ok. +- */ +- savesegment(es, prev->es); +- if (unlikely(next->es | prev->es)) +- loadsegment(es, next->es); +- +- savesegment(ds, prev->ds); +- if (unlikely(next->ds | prev->ds)) +- loadsegment(ds, next->ds); +- +- + /* We must save %fs and %gs before load_TLS() because + * %fs and %gs may be cleared by load_TLS(). + * +@@ -312,41 +297,101 @@ __switch_to(struct task_struct *prev_p, + savesegment(fs, fsindex); + savesegment(gs, gsindex); + ++ /* ++ * Load TLS before restoring any segments so that segment loads ++ * reference the correct GDT entries. ++ */ + load_TLS(next, cpu); + + /* +- * Leave lazy mode, flushing any hypercalls made here. +- * This must be done before restoring TLS segments so +- * the GDT and LDT are properly updated, and must be +- * done before math_state_restore, so the TS bit is up +- * to date. ++ * Leave lazy mode, flushing any hypercalls made here. This ++ * must be done after loading TLS entries in the GDT but before ++ * loading segments that might reference them, and and it must ++ * be done before math_state_restore, so the TS bit is up to ++ * date. + */ + arch_end_context_switch(next_p); + ++ /* Switch DS and ES. ++ * ++ * Reading them only returns the selectors, but writing them (if ++ * nonzero) loads the full descriptor from the GDT or LDT. The ++ * LDT for next is loaded in switch_mm, and the GDT is loaded ++ * above. ++ * ++ * We therefore need to write new values to the segment ++ * registers on every context switch unless both the new and old ++ * values are zero. ++ * ++ * Note that we don't need to do anything for CS and SS, as ++ * those are saved and restored as part of pt_regs. ++ */ ++ savesegment(es, prev->es); ++ if (unlikely(next->es | prev->es)) ++ loadsegment(es, next->es); ++ ++ savesegment(ds, prev->ds); ++ if (unlikely(next->ds | prev->ds)) ++ loadsegment(ds, next->ds); ++ + /* + * Switch FS and GS. + * +- * Segment register != 0 always requires a reload. Also +- * reload when it has changed. When prev process used 64bit +- * base always reload to avoid an information leak. ++ * These are even more complicated than FS and GS: they have ++ * 64-bit bases are that controlled by arch_prctl. Those bases ++ * only differ from the values in the GDT or LDT if the selector ++ * is 0. ++ * ++ * Loading the segment register resets the hidden base part of ++ * the register to 0 or the value from the GDT / LDT. If the ++ * next base address zero, writing 0 to the segment register is ++ * much faster than using wrmsr to explicitly zero the base. ++ * ++ * The thread_struct.fs and thread_struct.gs values are 0 ++ * if the fs and gs bases respectively are not overridden ++ * from the values implied by fsindex and gsindex. They ++ * are nonzero, and store the nonzero base addresses, if ++ * the bases are overridden. ++ * ++ * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should ++ * be impossible. ++ * ++ * Therefore we need to reload the segment registers if either ++ * the old or new selector is nonzero, and we need to override ++ * the base address if next thread expects it to be overridden. ++ * ++ * This code is unnecessarily slow in the case where the old and ++ * new indexes are zero and the new base is nonzero -- it will ++ * unnecessarily write 0 to the selector before writing the new ++ * base address. ++ * ++ * Note: This all depends on arch_prctl being the only way that ++ * user code can override the segment base. Once wrfsbase and ++ * wrgsbase are enabled, most of this code will need to change. + */ + if (unlikely(fsindex | next->fsindex | prev->fs)) { + loadsegment(fs, next->fsindex); ++ + /* +- * Check if the user used a selector != 0; if yes +- * clear 64bit base, since overloaded base is always +- * mapped to the Null selector ++ * If user code wrote a nonzero value to FS, then it also ++ * cleared the overridden base address. ++ * ++ * XXX: if user code wrote 0 to FS and cleared the base ++ * address itself, we won't notice and we'll incorrectly ++ * restore the prior base address next time we reschdule ++ * the process. + */ + if (fsindex) + prev->fs = 0; + } +- /* when next process has a 64bit base use it */ + if (next->fs) + wrmsrl(MSR_FS_BASE, next->fs); + prev->fsindex = fsindex; + + if (unlikely(gsindex | next->gsindex | prev->gs)) { + load_gs_index(next->gsindex); ++ ++ /* This works (and fails) the same way as fsindex above. */ + if (gsindex) + prev->gs = 0; + } diff --git a/patches/x86_64-vdso-fix-the-vdso-address-randomization-algorithm.patch b/patches/x86_64-vdso-fix-the-vdso-address-randomization-algorithm.patch new file mode 100644 index 0000000..bab6f52 --- /dev/null +++ b/patches/x86_64-vdso-fix-the-vdso-address-randomization-algorithm.patch @@ -0,0 +1,114 @@ +From 394f56fe480140877304d342dec46d50dc823d46 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski <luto@amacapital.net> +Date: Fri, 19 Dec 2014 16:04:11 -0800 +Subject: x86_64, vdso: Fix the vdso address randomization algorithm + +commit 394f56fe480140877304d342dec46d50dc823d46 upstream. + +The theory behind vdso randomization is that it's mapped at a random +offset above the top of the stack. To avoid wasting a page of +memory for an extra page table, the vdso isn't supposed to extend +past the lowest PMD into which it can fit. Other than that, the +address should be a uniformly distributed address that meets all of +the alignment requirements. + +The current algorithm is buggy: the vdso has about a 50% probability +of being at the very end of a PMD. The current algorithm also has a +decent chance of failing outright due to incorrect handling of the +case where the top of the stack is near the top of its PMD. + +This fixes the implementation. The paxtest estimate of vdso +"randomisation" improves from 11 bits to 18 bits. (Disclaimer: I +don't know what the paxtest code is actually calculating.) + +It's worth noting that this algorithm is inherently biased: the vdso +is more likely to end up near the end of its PMD than near the +beginning. Ideally we would either nix the PMD sharing requirement +or jointly randomize the vdso and the stack to reduce the bias. + +In the mean time, this is a considerable improvement with basically +no risk of compatibility issues, since the allowed outputs of the +algorithm are unchanged. + +As an easy test, doing this: + +for i in `seq 10000` + do grep -P vdso /proc/self/maps |cut -d- -f1 +done |sort |uniq -d + +used to produce lots of output (1445 lines on my most recent run). +A tiny subset looks like this: + +7fffdfffe000 +7fffe01fe000 +7fffe05fe000 +7fffe07fe000 +7fffe09fe000 +7fffe0bfe000 +7fffe0dfe000 + +Note the suspicious fe000 endings. With the fix, I get a much more +palatable 76 repeated addresses. + +Reviewed-by: Kees Cook <keescook@chromium.org> +Signed-off-by: Andy Lutomirski <luto@amacapital.net> +[lizf: Backported to 3.4: + - adjust context + - adjust comment] +Signed-off-by: Zefan Li <lizefan@huawei.com> +--- + arch/x86/vdso/vma.c | 36 ++++++++++++++++++++++++++---------- + 1 file changed, 26 insertions(+), 10 deletions(-) + +--- a/arch/x86/vdso/vma.c ++++ b/arch/x86/vdso/vma.c +@@ -117,23 +117,39 @@ subsys_initcall(init_vdso); + + struct linux_binprm; + +-/* Put the vdso above the (randomized) stack with another randomized offset. +- This way there is no hole in the middle of address space. +- To save memory make sure it is still in the same PTE as the stack top. +- This doesn't give that many random bits */ ++/* ++ * Put the vdso above the (randomized) stack with another randomized ++ * offset. This way there is no hole in the middle of address space. ++ * To save memory make sure it is still in the same PTE as the stack ++ * top. This doesn't give that many random bits. ++ * ++ * Note that this algorithm is imperfect: the distribution of the vdso ++ * start address within a PMD is biased toward the end. ++ * ++ */ + static unsigned long vdso_addr(unsigned long start, unsigned len) + { + unsigned long addr, end; + unsigned offset; +- end = (start + PMD_SIZE - 1) & PMD_MASK; ++ ++ /* ++ * Round up the start address. It can start out unaligned as a result ++ * of stack start randomization. ++ */ ++ start = PAGE_ALIGN(start); ++ ++ /* Round the lowest possible end address up to a PMD boundary. */ ++ end = (start + len + PMD_SIZE - 1) & PMD_MASK; + if (end >= TASK_SIZE_MAX) + end = TASK_SIZE_MAX; + end -= len; +- /* This loses some more bits than a modulo, but is cheaper */ +- offset = get_random_int() & (PTRS_PER_PTE - 1); +- addr = start + (offset << PAGE_SHIFT); +- if (addr >= end) +- addr = end; ++ ++ if (end > start) { ++ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1); ++ addr = start + (offset << PAGE_SHIFT); ++ } else { ++ addr = start; ++ } + + /* + * page-align it here so that get_unmapped_area doesn't |