From: Greg Kroah-Hartman Date: Mon, 19 Mar 2018 10:03:53 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.15.12~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b67f77967055fd00041364bb244824261e72b78;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: alsa-hda-revert-power_save-option-default-value.patch alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch drm-amdgpu-dce-don-t-turn-off-dp-sink-when-disconnected.patch fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch fs-aio-use-rcu-accessors-for-kioctx_table-table.patch fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch selftests-x86-add-tests-for-the-str-and-sldt-instructions.patch selftests-x86-add-tests-for-user-mode-instruction-prevention.patch selftests-x86-entry_from_vm86-add-test-cases-for-popf.patch selftests-x86-entry_from_vm86-exit-with-1-if-we-fail.patch x86-mm-fix-vmalloc_fault-to-use-pxd_large.patch x86-vm86-32-fix-popf-emulation.patch --- diff --git a/queue-4.4/alsa-hda-revert-power_save-option-default-value.patch b/queue-4.4/alsa-hda-revert-power_save-option-default-value.patch new file mode 100644 index 00000000000..8d198749744 --- /dev/null +++ b/queue-4.4/alsa-hda-revert-power_save-option-default-value.patch @@ -0,0 +1,66 @@ +From 40088dc4e1ead7df31728c73f5b51d71da18831d Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Mon, 12 Mar 2018 13:55:48 +0100 +Subject: ALSA: hda - Revert power_save option default value + +From: Takashi Iwai + +commit 40088dc4e1ead7df31728c73f5b51d71da18831d upstream. + +With the commit 1ba8f9d30817 ("ALSA: hda: Add a power_save +blacklist"), we changed the default value of power_save option to -1 +for processing the power-save blacklist. +Unfortunately, this seems breaking user-space applications that +actually read the power_save parameter value via sysfs and judge / +adjust the power-saving status. They see the value -1 as if the +power-save is turned off, although the actual value is taken from +CONFIG_SND_HDA_POWER_SAVE_DEFAULT and it can be a positive. + +So, overall, passing -1 there was no good idea. Let's partially +revert it -- at least for power_save option default value is restored +again to CONFIG_SND_HDA_POWER_SAVE_DEFAULT. Meanwhile, in this patch, +we keep the blacklist behavior and make is adjustable via the new +option, pm_blacklist. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199073 +Fixes: 1ba8f9d30817 ("ALSA: hda: Add a power_save blacklist") +Acked-by: Hans de Goede +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_intel.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -179,11 +179,15 @@ static const struct kernel_param_ops par + }; + #define param_check_xint param_check_int + +-static int power_save = -1; ++static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; + module_param(power_save, xint, 0644); + MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " + "(in second, 0 = disable)."); + ++static bool pm_blacklist = true; ++module_param(pm_blacklist, bool, 0644); ++MODULE_PARM_DESC(pm_blacklist, "Enable power-management blacklist"); ++ + /* reset the HD-audio controller in power save mode. + * this may give more power-saving, but will take longer time to + * wake up. +@@ -2164,10 +2168,9 @@ static int azx_probe_continue(struct azx + + val = power_save; + #ifdef CONFIG_PM +- if (val == -1) { ++ if (pm_blacklist) { + const struct snd_pci_quirk *q; + +- val = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; + q = snd_pci_quirk_lookup(chip->pci, power_save_blacklist); + if (q && val) { + dev_info(chip->card->dev, "device %04x:%04x is on the power_save blacklist, forcing power_save to 0\n", diff --git a/queue-4.4/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch b/queue-4.4/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch new file mode 100644 index 00000000000..854f5068315 --- /dev/null +++ b/queue-4.4/alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch @@ -0,0 +1,51 @@ +From 01c0b4265cc16bc1f43f475c5944c55c10d5768f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Sat, 10 Mar 2018 23:04:23 +0100 +Subject: ALSA: pcm: Fix UAF in snd_pcm_oss_get_formats() + +From: Takashi Iwai + +commit 01c0b4265cc16bc1f43f475c5944c55c10d5768f upstream. + +snd_pcm_oss_get_formats() has an obvious use-after-free around +snd_mask_test() calls, as spotted by syzbot. The passed format_mask +argument is a pointer to the hw_params object that is freed before the +loop. What a surprise that it has been present since the original +code of decades ago... + +Reported-by: syzbot+4090700a4f13fccaf648@syzkaller.appspotmail.com +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/oss/pcm_oss.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -1814,10 +1814,9 @@ static int snd_pcm_oss_get_formats(struc + return -ENOMEM; + _snd_pcm_hw_params_any(params); + err = snd_pcm_hw_refine(substream, params); +- format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); +- kfree(params); + if (err < 0) +- return err; ++ goto error; ++ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); + for (fmt = 0; fmt < 32; ++fmt) { + if (snd_mask_test(&format_mask, fmt)) { + int f = snd_pcm_oss_format_to(fmt); +@@ -1825,7 +1824,10 @@ static int snd_pcm_oss_get_formats(struc + formats |= f; + } + } +- return formats; ++ ++ error: ++ kfree(params); ++ return err < 0 ? err : formats; + } + + static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) diff --git a/queue-4.4/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch b/queue-4.4/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch new file mode 100644 index 00000000000..8db06394c7e --- /dev/null +++ b/queue-4.4/alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch @@ -0,0 +1,50 @@ +From a2ff19f7b70118ced291a28d5313469914de451b Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 9 Mar 2018 22:23:31 +0100 +Subject: ALSA: seq: Clear client entry before deleting else at closing + +From: Takashi Iwai + +commit a2ff19f7b70118ced291a28d5313469914de451b upstream. + +When releasing a client, we need to clear the clienttab[] entry at +first, then call snd_seq_queue_client_leave(). Otherwise, the +in-flight cell in the queue might be picked up by the timer interrupt +via snd_seq_check_queue() before calling snd_seq_queue_client_leave(), +and it's delivered to another queue while the client is clearing +queues. This may eventually result in an uncleared cell remaining in +a queue, and the later snd_seq_pool_delete() may need to wait for a +long time until the event gets really processed. + +By moving the clienttab[] clearance at the beginning of release, any +event delivery of a cell belonging to this client will fail at a later +point, since snd_seq_client_ptr() returns NULL. Thus the cell that +was picked up by the timer interrupt will be returned immediately +without further delivery, and the long stall of snd_seq_delete_pool() +can be avoided, too. + +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/seq/seq_clientmgr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/core/seq/seq_clientmgr.c ++++ b/sound/core/seq/seq_clientmgr.c +@@ -270,12 +270,12 @@ static int seq_free_client1(struct snd_s + + if (!client) + return 0; +- snd_seq_delete_all_ports(client); +- snd_seq_queue_client_leave(client->number); + spin_lock_irqsave(&clients_lock, flags); + clienttablock[client->number] = 1; + clienttab[client->number] = NULL; + spin_unlock_irqrestore(&clients_lock, flags); ++ snd_seq_delete_all_ports(client); ++ snd_seq_queue_client_leave(client->number); + snd_use_lock_sync(&client->use_lock); + snd_seq_queue_client_termination(client->number); + if (client->pool) diff --git a/queue-4.4/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch b/queue-4.4/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch new file mode 100644 index 00000000000..61fcb3a61c3 --- /dev/null +++ b/queue-4.4/alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch @@ -0,0 +1,170 @@ +From d0f833065221cbfcbadf19fd4102bcfa9330006a Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 9 Mar 2018 21:58:28 +0100 +Subject: ALSA: seq: Fix possible UAF in snd_seq_check_queue() + +From: Takashi Iwai + +commit d0f833065221cbfcbadf19fd4102bcfa9330006a upstream. + +Although we've covered the races between concurrent write() and +ioctl() in the previous patch series, there is still a possible UAF in +the following scenario: + +A: user client closed B: timer irq + -> snd_seq_release() -> snd_seq_timer_interrupt() + -> snd_seq_free_client() -> snd_seq_check_queue() + -> cell = snd_seq_prioq_cell_peek() + -> snd_seq_prioq_leave() + .... removing all cells + -> snd_seq_pool_done() + .... vfree() + -> snd_seq_compare_tick_time(cell) + ... Oops + +So the problem is that a cell is peeked and accessed without any +protection until it's retrieved from the queue again via +snd_seq_prioq_cell_out(). + +This patch tries to address it, also cleans up the code by a slight +refactoring. snd_seq_prioq_cell_out() now receives an extra pointer +argument. When it's non-NULL, the function checks the event timestamp +with the given pointer. The caller needs to pass the right reference +either to snd_seq_tick or snd_seq_realtime depending on the event +timestamp type. + +A good news is that the above change allows us to remove the +snd_seq_prioq_cell_peek(), too, thus the patch actually reduces the +code size. + +Reviewed-by: Nicolai Stange +Cc: +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/core/seq/seq_prioq.c | 28 ++++++++++++++-------------- + sound/core/seq/seq_prioq.h | 6 ++---- + sound/core/seq/seq_queue.c | 28 +++++++++------------------- + 3 files changed, 25 insertions(+), 37 deletions(-) + +--- a/sound/core/seq/seq_prioq.c ++++ b/sound/core/seq/seq_prioq.c +@@ -87,7 +87,7 @@ void snd_seq_prioq_delete(struct snd_seq + if (f->cells > 0) { + /* drain prioQ */ + while (f->cells > 0) +- snd_seq_cell_free(snd_seq_prioq_cell_out(f)); ++ snd_seq_cell_free(snd_seq_prioq_cell_out(f, NULL)); + } + + kfree(f); +@@ -214,8 +214,18 @@ int snd_seq_prioq_cell_in(struct snd_seq + return 0; + } + ++/* return 1 if the current time >= event timestamp */ ++static int event_is_ready(struct snd_seq_event *ev, void *current_time) ++{ ++ if ((ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) ++ return snd_seq_compare_tick_time(current_time, &ev->time.tick); ++ else ++ return snd_seq_compare_real_time(current_time, &ev->time.time); ++} ++ + /* dequeue cell from prioq */ +-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f) ++struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f, ++ void *current_time) + { + struct snd_seq_event_cell *cell; + unsigned long flags; +@@ -227,6 +237,8 @@ struct snd_seq_event_cell *snd_seq_prioq + spin_lock_irqsave(&f->lock, flags); + + cell = f->head; ++ if (cell && current_time && !event_is_ready(&cell->event, current_time)) ++ cell = NULL; + if (cell) { + f->head = cell->next; + +@@ -252,18 +264,6 @@ int snd_seq_prioq_avail(struct snd_seq_p + return f->cells; + } + +- +-/* peek at cell at the head of the prioq */ +-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f) +-{ +- if (f == NULL) { +- pr_debug("ALSA: seq: snd_seq_prioq_cell_in() called with NULL prioq\n"); +- return NULL; +- } +- return f->head; +-} +- +- + static inline int prioq_match(struct snd_seq_event_cell *cell, + int client, int timestamp) + { +--- a/sound/core/seq/seq_prioq.h ++++ b/sound/core/seq/seq_prioq.h +@@ -44,14 +44,12 @@ void snd_seq_prioq_delete(struct snd_seq + int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell); + + /* dequeue cell from prioq */ +-struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f); ++struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f, ++ void *current_time); + + /* return number of events available in prioq */ + int snd_seq_prioq_avail(struct snd_seq_prioq *f); + +-/* peek at cell at the head of the prioq */ +-struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f); +- + /* client left queue */ + void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp); + +--- a/sound/core/seq/seq_queue.c ++++ b/sound/core/seq/seq_queue.c +@@ -277,30 +277,20 @@ void snd_seq_check_queue(struct snd_seq_ + + __again: + /* Process tick queue... */ +- while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) { +- if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick, +- &cell->event.time.tick)) { +- cell = snd_seq_prioq_cell_out(q->tickq); +- if (cell) +- snd_seq_dispatch_event(cell, atomic, hop); +- } else { +- /* event remains in the queue */ ++ for (;;) { ++ cell = snd_seq_prioq_cell_out(q->tickq, ++ &q->timer->tick.cur_tick); ++ if (!cell) + break; +- } ++ snd_seq_dispatch_event(cell, atomic, hop); + } + +- + /* Process time queue... */ +- while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) { +- if (snd_seq_compare_real_time(&q->timer->cur_time, +- &cell->event.time.time)) { +- cell = snd_seq_prioq_cell_out(q->timeq); +- if (cell) +- snd_seq_dispatch_event(cell, atomic, hop); +- } else { +- /* event remains in the queue */ ++ for (;;) { ++ cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time); ++ if (!cell) + break; +- } ++ snd_seq_dispatch_event(cell, atomic, hop); + } + + /* free lock */ diff --git a/queue-4.4/drm-amdgpu-dce-don-t-turn-off-dp-sink-when-disconnected.patch b/queue-4.4/drm-amdgpu-dce-don-t-turn-off-dp-sink-when-disconnected.patch new file mode 100644 index 00000000000..92f75645d5f --- /dev/null +++ b/queue-4.4/drm-amdgpu-dce-don-t-turn-off-dp-sink-when-disconnected.patch @@ -0,0 +1,68 @@ +From 7d617264eb22b18d979eac6e85877a141253034e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michel=20D=C3=A4nzer?= +Date: Fri, 9 Mar 2018 18:26:18 +0100 +Subject: drm/amdgpu/dce: Don't turn off DP sink when disconnected +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michel Dänzer + +commit 7d617264eb22b18d979eac6e85877a141253034e upstream. + +Turning off the sink in this case causes various issues, because +userspace expects it to stay on until it turns it off explicitly. + +Instead, turn the sink off and back on when a display is connected +again. This dance seems necessary for link training to work correctly. + +Bugzilla: https://bugs.freedesktop.org/105308 +Cc: stable@vger.kernel.org +Reviewed-by: Alex Deucher +Signed-off-by: Michel Dänzer +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 29 +++++++++---------------- + 1 file changed, 11 insertions(+), 18 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +@@ -69,25 +69,18 @@ void amdgpu_connector_hotplug(struct drm + /* don't do anything if sink is not display port, i.e., + * passive dp->(dvi|hdmi) adaptor + */ +- if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { +- int saved_dpms = connector->dpms; +- /* Only turn off the display if it's physically disconnected */ +- if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) { +- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); +- } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { +- /* Don't try to start link training before we +- * have the dpcd */ +- if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) +- return; ++ if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT && ++ amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd) && ++ amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { ++ /* Don't start link training before we have the DPCD */ ++ if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) ++ return; + +- /* set it to OFF so that drm_helper_connector_dpms() +- * won't return immediately since the current state +- * is ON at this point. +- */ +- connector->dpms = DRM_MODE_DPMS_OFF; +- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); +- } +- connector->dpms = saved_dpms; ++ /* Turn the connector off and back on immediately, which ++ * will trigger link training ++ */ ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); ++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + } + } diff --git a/queue-4.4/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch b/queue-4.4/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch new file mode 100644 index 00000000000..91717ebe7bb --- /dev/null +++ b/queue-4.4/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch @@ -0,0 +1,92 @@ +From a6d7cff472eea87d96899a20fa718d2bab7109f3 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 14 Mar 2018 12:10:17 -0700 +Subject: fs/aio: Add explicit RCU grace period when freeing kioctx + +From: Tejun Heo + +commit a6d7cff472eea87d96899a20fa718d2bab7109f3 upstream. + +While fixing refcounting, e34ecee2ae79 ("aio: Fix a trinity splat") +incorrectly removed explicit RCU grace period before freeing kioctx. +The intention seems to be depending on the internal RCU grace periods +of percpu_ref; however, percpu_ref uses a different flavor of RCU, +sched-RCU. This can lead to kioctx being freed while RCU read +protected dereferences are still in progress. + +Fix it by updating free_ioctx() to go through call_rcu() explicitly. + +v2: Comment added to explain double bouncing. + +Signed-off-by: Tejun Heo +Reported-by: Jann Horn +Fixes: e34ecee2ae79 ("aio: Fix a trinity splat") +Cc: Kent Overstreet +Cc: Linus Torvalds +Cc: stable@vger.kernel.org # v3.13+ +Signed-off-by: Greg Kroah-Hartman + +--- + fs/aio.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -115,7 +115,8 @@ struct kioctx { + struct page **ring_pages; + long nr_pages; + +- struct work_struct free_work; ++ struct rcu_head free_rcu; ++ struct work_struct free_work; /* see free_ioctx() */ + + /* + * signals when all in-flight requests are done +@@ -573,6 +574,12 @@ static int kiocb_cancel(struct aio_kiocb + return cancel(&kiocb->common); + } + ++/* ++ * free_ioctx() should be RCU delayed to synchronize against the RCU ++ * protected lookup_ioctx() and also needs process context to call ++ * aio_free_ring(), so the double bouncing through kioctx->free_rcu and ++ * ->free_work. ++ */ + static void free_ioctx(struct work_struct *work) + { + struct kioctx *ctx = container_of(work, struct kioctx, free_work); +@@ -586,6 +593,14 @@ static void free_ioctx(struct work_struc + kmem_cache_free(kioctx_cachep, ctx); + } + ++static void free_ioctx_rcufn(struct rcu_head *head) ++{ ++ struct kioctx *ctx = container_of(head, struct kioctx, free_rcu); ++ ++ INIT_WORK(&ctx->free_work, free_ioctx); ++ schedule_work(&ctx->free_work); ++} ++ + static void free_ioctx_reqs(struct percpu_ref *ref) + { + struct kioctx *ctx = container_of(ref, struct kioctx, reqs); +@@ -594,8 +609,8 @@ static void free_ioctx_reqs(struct percp + if (ctx->rq_wait && atomic_dec_and_test(&ctx->rq_wait->count)) + complete(&ctx->rq_wait->comp); + +- INIT_WORK(&ctx->free_work, free_ioctx); +- schedule_work(&ctx->free_work); ++ /* Synchronize against RCU protected table->table[] dereferences */ ++ call_rcu(&ctx->free_rcu, free_ioctx_rcufn); + } + + /* +@@ -817,7 +832,7 @@ static int kill_ioctx(struct mm_struct * + table->table[ctx->id] = NULL; + spin_unlock(&mm->ioctx_lock); + +- /* percpu_ref_kill() will do the necessary call_rcu() */ ++ /* free_ioctx_reqs() will do the necessary RCU synchronization */ + wake_up_all(&ctx->wait); + + /* diff --git a/queue-4.4/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch b/queue-4.4/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch new file mode 100644 index 00000000000..ca9eb9b8d53 --- /dev/null +++ b/queue-4.4/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch @@ -0,0 +1,96 @@ +From d0264c01e7587001a8c4608a5d1818dba9a4c11a Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Wed, 14 Mar 2018 12:10:17 -0700 +Subject: fs/aio: Use RCU accessors for kioctx_table->table[] + +From: Tejun Heo + +commit d0264c01e7587001a8c4608a5d1818dba9a4c11a upstream. + +While converting ioctx index from a list to a table, db446a08c23d +("aio: convert the ioctx list to table lookup v3") missed tagging +kioctx_table->table[] as an array of RCU pointers and using the +appropriate RCU accessors. This introduces a small window in the +lookup path where init and access may race. + +Mark kioctx_table->table[] with __rcu and use the approriate RCU +accessors when using the field. + +Signed-off-by: Tejun Heo +Reported-by: Jann Horn +Fixes: db446a08c23d ("aio: convert the ioctx list to table lookup v3") +Cc: Benjamin LaHaise +Cc: Linus Torvalds +Cc: stable@vger.kernel.org # v3.12+ +Signed-off-by: Greg Kroah-Hartman + +--- + fs/aio.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -68,9 +68,9 @@ struct aio_ring { + #define AIO_RING_PAGES 8 + + struct kioctx_table { +- struct rcu_head rcu; +- unsigned nr; +- struct kioctx *table[]; ++ struct rcu_head rcu; ++ unsigned nr; ++ struct kioctx __rcu *table[]; + }; + + struct kioctx_cpu { +@@ -327,7 +327,7 @@ static int aio_ring_mremap(struct vm_are + for (i = 0; i < table->nr; i++) { + struct kioctx *ctx; + +- ctx = table->table[i]; ++ ctx = rcu_dereference(table->table[i]); + if (ctx && ctx->aio_ring_file == file) { + if (!atomic_read(&ctx->dead)) { + ctx->user_id = ctx->mmap_base = vma->vm_start; +@@ -651,9 +651,9 @@ static int ioctx_add_table(struct kioctx + while (1) { + if (table) + for (i = 0; i < table->nr; i++) +- if (!table->table[i]) { ++ if (!rcu_access_pointer(table->table[i])) { + ctx->id = i; +- table->table[i] = ctx; ++ rcu_assign_pointer(table->table[i], ctx); + spin_unlock(&mm->ioctx_lock); + + /* While kioctx setup is in progress, +@@ -828,8 +828,8 @@ static int kill_ioctx(struct mm_struct * + } + + table = rcu_dereference_raw(mm->ioctx_table); +- WARN_ON(ctx != table->table[ctx->id]); +- table->table[ctx->id] = NULL; ++ WARN_ON(ctx != rcu_access_pointer(table->table[ctx->id])); ++ RCU_INIT_POINTER(table->table[ctx->id], NULL); + spin_unlock(&mm->ioctx_lock); + + /* free_ioctx_reqs() will do the necessary RCU synchronization */ +@@ -874,7 +874,8 @@ void exit_aio(struct mm_struct *mm) + + skipped = 0; + for (i = 0; i < table->nr; ++i) { +- struct kioctx *ctx = table->table[i]; ++ struct kioctx *ctx = ++ rcu_dereference_protected(table->table[i], true); + + if (!ctx) { + skipped++; +@@ -1063,7 +1064,7 @@ static struct kioctx *lookup_ioctx(unsig + if (!table || id >= table->nr) + goto out; + +- ctx = table->table[id]; ++ ctx = rcu_dereference(table->table[id]); + if (ctx && ctx->user_id == ctx_id) { + percpu_ref_get(&ctx->users); + ret = ctx; diff --git a/queue-4.4/fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch b/queue-4.4/fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch new file mode 100644 index 00000000000..4d422c85fdf --- /dev/null +++ b/queue-4.4/fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch @@ -0,0 +1,104 @@ +From 95dd77580ccd66a0da96e6d4696945b8cea39431 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Wed, 14 Mar 2018 18:20:29 -0500 +Subject: fs: Teach path_connected to handle nfs filesystems with multiple roots. + +From: Eric W. Biederman + +commit 95dd77580ccd66a0da96e6d4696945b8cea39431 upstream. + +On nfsv2 and nfsv3 the nfs server can export subsets of the same +filesystem and report the same filesystem identifier, so that the nfs +client can know they are the same filesystem. The subsets can be from +disjoint directory trees. The nfsv2 and nfsv3 filesystems provides no +way to find the common root of all directory trees exported form the +server with the same filesystem identifier. + +The practical result is that in struct super s_root for nfs s_root is +not necessarily the root of the filesystem. The nfs mount code sets +s_root to the root of the first subset of the nfs filesystem that the +kernel mounts. + +This effects the dcache invalidation code in generic_shutdown_super +currently called shrunk_dcache_for_umount and that code for years +has gone through an additional list of dentries that might be dentry +trees that need to be freed to accomodate nfs. + +When I wrote path_connected I did not realize nfs was so special, and +it's hueristic for avoiding calling is_subdir can fail. + +The practical case where this fails is when there is a move of a +directory from the subtree exposed by one nfs mount to the subtree +exposed by another nfs mount. This move can happen either locally or +remotely. With the remote case requiring that the move directory be cached +before the move and that after the move someone walks the path +to where the move directory now exists and in so doing causes the +already cached directory to be moved in the dcache through the magic +of d_splice_alias. + +If someone whose working directory is in the move directory or a +subdirectory and now starts calling .. from the initial mount of nfs +(where s_root == mnt_root), then path_connected as a heuristic will +not bother with the is_subdir check. As s_root really is not the root +of the nfs filesystem this heuristic is wrong, and the path may +actually not be connected and path_connected can fail. + +The is_subdir function might be cheap enough that we can call it +unconditionally. Verifying that will take some benchmarking and +the result may not be the same on all kernels this fix needs +to be backported to. So I am avoiding that for now. + +Filesystems with snapshots such as nilfs and btrfs do something +similar. But as the directory tree of the snapshots are disjoint +from one another and from the main directory tree rename won't move +things between them and this problem will not occur. + +Cc: stable@vger.kernel.org +Reported-by: Al Viro +Fixes: 397d425dc26d ("vfs: Test for and handle paths that are unreachable from their mnt_root") +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namei.c | 5 +++-- + fs/nfs/super.c | 2 ++ + include/linux/fs.h | 1 + + 3 files changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -570,9 +570,10 @@ static int __nd_alloc_stack(struct namei + static bool path_connected(const struct path *path) + { + struct vfsmount *mnt = path->mnt; ++ struct super_block *sb = mnt->mnt_sb; + +- /* Only bind mounts can have disconnected paths */ +- if (mnt->mnt_root == mnt->mnt_sb->s_root) ++ /* Bind mounts and multi-root filesystems can have disconnected paths */ ++ if (!(sb->s_iflags & SB_I_MULTIROOT) && (mnt->mnt_root == sb->s_root)) + return true; + + return is_subdir(path->dentry, mnt->mnt_root); +--- a/fs/nfs/super.c ++++ b/fs/nfs/super.c +@@ -2581,6 +2581,8 @@ struct dentry *nfs_fs_mount_common(struc + /* initial superblock/root creation */ + mount_info->fill_super(s, mount_info); + nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned); ++ if (!(server->flags & NFS_MOUNT_UNSHARED)) ++ s->s_iflags |= SB_I_MULTIROOT; + } + + mntroot = nfs_get_root(s, mount_info->mntfh, dev_name); +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1295,6 +1295,7 @@ struct mm_struct; + /* sb->s_iflags */ + #define SB_I_CGROUPWB 0x00000001 /* cgroup-aware writeback enabled */ + #define SB_I_NOEXEC 0x00000002 /* Ignore executables on this fs */ ++#define SB_I_MULTIROOT 0x00000008 /* Multiple roots to the dentry tree */ + + /* Possible states of 'frozen' field */ + enum { diff --git a/queue-4.4/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch b/queue-4.4/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch new file mode 100644 index 00000000000..46187d16a02 --- /dev/null +++ b/queue-4.4/lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch @@ -0,0 +1,49 @@ +From 3b821409632ab778d46e807516b457dfa72736ed Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 23 Feb 2018 20:47:17 -0500 +Subject: lock_parent() needs to recheck if dentry got __dentry_kill'ed under it + +From: Al Viro + +commit 3b821409632ab778d46e807516b457dfa72736ed upstream. + +In case when dentry passed to lock_parent() is protected from freeing only +by the fact that it's on a shrink list and trylock of parent fails, we +could get hit by __dentry_kill() (and subsequent dentry_kill(parent)) +between unlocking dentry and locking presumed parent. We need to recheck +that dentry is alive once we lock both it and parent *and* postpone +rcu_read_unlock() until after that point. Otherwise we could return +a pointer to struct dentry that already is rcu-scheduled for freeing, with +->d_lock held on it; caller's subsequent attempt to unlock it can end +up with memory corruption. + +Cc: stable@vger.kernel.org # 3.12+, counting backports +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/dcache.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -634,11 +634,16 @@ again: + spin_unlock(&parent->d_lock); + goto again; + } +- rcu_read_unlock(); +- if (parent != dentry) ++ if (parent != dentry) { + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); +- else ++ if (unlikely(dentry->d_lockref.count < 0)) { ++ spin_unlock(&parent->d_lock); ++ parent = NULL; ++ } ++ } else { + parent = NULL; ++ } ++ rcu_read_unlock(); + return parent; + } + diff --git a/queue-4.4/selftests-x86-add-tests-for-the-str-and-sldt-instructions.patch b/queue-4.4/selftests-x86-add-tests-for-the-str-and-sldt-instructions.patch new file mode 100644 index 00000000000..56f6389c45c --- /dev/null +++ b/queue-4.4/selftests-x86-add-tests-for-the-str-and-sldt-instructions.patch @@ -0,0 +1,100 @@ +From a9e017d5619eb371460c8e516f4684def62bef3a Mon Sep 17 00:00:00 2001 +From: Ricardo Neri +Date: Sun, 5 Nov 2017 18:27:57 -0800 +Subject: selftests/x86: Add tests for the STR and SLDT instructions + +From: Ricardo Neri + +commit a9e017d5619eb371460c8e516f4684def62bef3a upstream. + +The STR and SLDT instructions are not valid when running on virtual-8086 +mode and generate an invalid operand exception. These two instructions are +protected by the Intel User-Mode Instruction Prevention (UMIP) security +feature. In protected mode, if UMIP is enabled, these instructions generate +a general protection fault if called from CPL > 0. Linux traps the general +protection fault and emulates the instructions sgdt, sidt and smsw; but not +str and sldt. + +These tests are added to verify that the emulation code does not emulate +these two instructions but the expected invalid operand exception is +seen. + +Tests fallback to exit with INT3 in case emulation does happen. + +Signed-off-by: Ricardo Neri +Reviewed-by: Thomas Gleixner +Cc: Andrew Morton +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Chen Yucong +Cc: Chris Metcalf +Cc: Dave Hansen +Cc: Denys Vlasenko +Cc: Fenghua Yu +Cc: H. Peter Anvin +Cc: Huang Rui +Cc: Jiri Slaby +Cc: Jonathan Corbet +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Masami Hiramatsu +Cc: Michael S. Tsirkin +Cc: Paolo Bonzini +Cc: Paul Gortmaker +Cc: Peter Zijlstra +Cc: Ravi V. Shankar +Cc: Shuah Khan +Cc: Tony Luck +Cc: Vlastimil Babka +Cc: ricardo.neri@intel.com +Link: http://lkml.kernel.org/r/1509935277-22138-13-git-send-email-ricardo.neri-calderon@linux.intel.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + tools/testing/selftests/x86/entry_from_vm86.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/tools/testing/selftests/x86/entry_from_vm86.c ++++ b/tools/testing/selftests/x86/entry_from_vm86.c +@@ -111,6 +111,11 @@ asm ( + "smsw %ax\n\t" + "mov %ax, (2080)\n\t" + "int3\n\t" ++ "vmcode_umip_str:\n\t" ++ "str %eax\n\t" ++ "vmcode_umip_sldt:\n\t" ++ "sldt %eax\n\t" ++ "int3\n\t" + ".size vmcode, . - vmcode\n\t" + "end_vmcode:\n\t" + ".code32\n\t" +@@ -119,7 +124,8 @@ asm ( + + extern unsigned char vmcode[], end_vmcode[]; + extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], +- vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[]; ++ vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[], ++ vmcode_umip_str[], vmcode_umip_sldt[]; + + /* Returns false if the test was skipped. */ + static bool do_test(struct vm86plus_struct *v86, unsigned long eip, +@@ -226,6 +232,16 @@ void do_umip_tests(struct vm86plus_struc + printf("[FAIL]\tAll the results of SIDT should be the same.\n"); + else + printf("[PASS]\tAll the results from SIDT are identical.\n"); ++ ++ sethandler(SIGILL, sighandler, 0); ++ do_test(vm86, vmcode_umip_str - vmcode, VM86_SIGNAL, 0, ++ "STR instruction"); ++ clearhandler(SIGILL); ++ ++ sethandler(SIGILL, sighandler, 0); ++ do_test(vm86, vmcode_umip_sldt - vmcode, VM86_SIGNAL, 0, ++ "SLDT instruction"); ++ clearhandler(SIGILL); + } + + int main(void) diff --git a/queue-4.4/selftests-x86-add-tests-for-user-mode-instruction-prevention.patch b/queue-4.4/selftests-x86-add-tests-for-user-mode-instruction-prevention.patch new file mode 100644 index 00000000000..96719a4bd89 --- /dev/null +++ b/queue-4.4/selftests-x86-add-tests-for-user-mode-instruction-prevention.patch @@ -0,0 +1,171 @@ +From 9390afebe1d3f5a0be18b1afdd0ce09d67cebf9e Mon Sep 17 00:00:00 2001 +From: Ricardo Neri +Date: Sun, 5 Nov 2017 18:27:56 -0800 +Subject: selftests/x86: Add tests for User-Mode Instruction Prevention + +From: Ricardo Neri + +commit 9390afebe1d3f5a0be18b1afdd0ce09d67cebf9e upstream. + +Certain user space programs that run on virtual-8086 mode may utilize +instructions protected by the User-Mode Instruction Prevention (UMIP) +security feature present in new Intel processors: SGDT, SIDT and SMSW. In +such a case, a general protection fault is issued if UMIP is enabled. When +such a fault happens, the kernel traps it and emulates the results of +these instructions with dummy values. The purpose of this new +test is to verify whether the impacted instructions can be executed +without causing such #GP. If no #GP exceptions occur, we expect to exit +virtual-8086 mode from INT3. + +The instructions protected by UMIP are executed in representative use +cases: + + a) displacement-only memory addressing + b) register-indirect memory addressing + c) results stored directly in operands + +Unfortunately, it is not possible to check the results against a set of +expected values because no emulation will occur in systems that do not +have the UMIP feature. Instead, results are printed for verification. A +simple verification is done to ensure that results of all tests are +identical. + +Signed-off-by: Ricardo Neri +Reviewed-by: Thomas Gleixner +Cc: Andrew Morton +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Chen Yucong +Cc: Chris Metcalf +Cc: Dave Hansen +Cc: Denys Vlasenko +Cc: Fenghua Yu +Cc: H. Peter Anvin +Cc: Huang Rui +Cc: Jiri Slaby +Cc: Jonathan Corbet +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Masami Hiramatsu +Cc: Michael S. Tsirkin +Cc: Paolo Bonzini +Cc: Paul Gortmaker +Cc: Peter Zijlstra +Cc: Ravi V. Shankar +Cc: Shuah Khan +Cc: Tony Luck +Cc: Vlastimil Babka +Cc: ricardo.neri@intel.com +Link: http://lkml.kernel.org/r/1509935277-22138-12-git-send-email-ricardo.neri-calderon@linux.intel.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + tools/testing/selftests/x86/entry_from_vm86.c | 73 +++++++++++++++++++++++++- + 1 file changed, 72 insertions(+), 1 deletion(-) + +--- a/tools/testing/selftests/x86/entry_from_vm86.c ++++ b/tools/testing/selftests/x86/entry_from_vm86.c +@@ -95,6 +95,22 @@ asm ( + "int3\n\t" + "vmcode_int80:\n\t" + "int $0x80\n\t" ++ "vmcode_umip:\n\t" ++ /* addressing via displacements */ ++ "smsw (2052)\n\t" ++ "sidt (2054)\n\t" ++ "sgdt (2060)\n\t" ++ /* addressing via registers */ ++ "mov $2066, %bx\n\t" ++ "smsw (%bx)\n\t" ++ "mov $2068, %bx\n\t" ++ "sidt (%bx)\n\t" ++ "mov $2074, %bx\n\t" ++ "sgdt (%bx)\n\t" ++ /* register operands, only for smsw */ ++ "smsw %ax\n\t" ++ "mov %ax, (2080)\n\t" ++ "int3\n\t" + ".size vmcode, . - vmcode\n\t" + "end_vmcode:\n\t" + ".code32\n\t" +@@ -103,7 +119,7 @@ asm ( + + extern unsigned char vmcode[], end_vmcode[]; + extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], +- vmcode_sti[], vmcode_int3[], vmcode_int80[]; ++ vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[]; + + /* Returns false if the test was skipped. */ + static bool do_test(struct vm86plus_struct *v86, unsigned long eip, +@@ -160,6 +176,58 @@ static bool do_test(struct vm86plus_stru + return true; + } + ++void do_umip_tests(struct vm86plus_struct *vm86, unsigned char *test_mem) ++{ ++ struct table_desc { ++ unsigned short limit; ++ unsigned long base; ++ } __attribute__((packed)); ++ ++ /* Initialize variables with arbitrary values */ ++ struct table_desc gdt1 = { .base = 0x3c3c3c3c, .limit = 0x9999 }; ++ struct table_desc gdt2 = { .base = 0x1a1a1a1a, .limit = 0xaeae }; ++ struct table_desc idt1 = { .base = 0x7b7b7b7b, .limit = 0xf1f1 }; ++ struct table_desc idt2 = { .base = 0x89898989, .limit = 0x1313 }; ++ unsigned short msw1 = 0x1414, msw2 = 0x2525, msw3 = 3737; ++ ++ /* UMIP -- exit with INT3 unless kernel emulation did not trap #GP */ ++ do_test(vm86, vmcode_umip - vmcode, VM86_TRAP, 3, "UMIP tests"); ++ ++ /* Results from displacement-only addressing */ ++ msw1 = *(unsigned short *)(test_mem + 2052); ++ memcpy(&idt1, test_mem + 2054, sizeof(idt1)); ++ memcpy(&gdt1, test_mem + 2060, sizeof(gdt1)); ++ ++ /* Results from register-indirect addressing */ ++ msw2 = *(unsigned short *)(test_mem + 2066); ++ memcpy(&idt2, test_mem + 2068, sizeof(idt2)); ++ memcpy(&gdt2, test_mem + 2074, sizeof(gdt2)); ++ ++ /* Results when using register operands */ ++ msw3 = *(unsigned short *)(test_mem + 2080); ++ ++ printf("[INFO]\tResult from SMSW:[0x%04x]\n", msw1); ++ printf("[INFO]\tResult from SIDT: limit[0x%04x]base[0x%08lx]\n", ++ idt1.limit, idt1.base); ++ printf("[INFO]\tResult from SGDT: limit[0x%04x]base[0x%08lx]\n", ++ gdt1.limit, gdt1.base); ++ ++ if (msw1 != msw2 || msw1 != msw3) ++ printf("[FAIL]\tAll the results of SMSW should be the same.\n"); ++ else ++ printf("[PASS]\tAll the results from SMSW are identical.\n"); ++ ++ if (memcmp(&gdt1, &gdt2, sizeof(gdt1))) ++ printf("[FAIL]\tAll the results of SGDT should be the same.\n"); ++ else ++ printf("[PASS]\tAll the results from SGDT are identical.\n"); ++ ++ if (memcmp(&idt1, &idt2, sizeof(idt1))) ++ printf("[FAIL]\tAll the results of SIDT should be the same.\n"); ++ else ++ printf("[PASS]\tAll the results from SIDT are identical.\n"); ++} ++ + int main(void) + { + struct vm86plus_struct v86; +@@ -218,6 +286,9 @@ int main(void) + v86.regs.eax = (unsigned int)-1; + do_test(&v86, vmcode_int80 - vmcode, VM86_INTx, 0x80, "int80"); + ++ /* UMIP -- should exit with INTx 0x80 unless UMIP was not disabled */ ++ do_umip_tests(&v86, addr); ++ + /* Execute a null pointer */ + v86.regs.cs = 0; + v86.regs.ss = 0; diff --git a/queue-4.4/selftests-x86-entry_from_vm86-add-test-cases-for-popf.patch b/queue-4.4/selftests-x86-entry_from_vm86-add-test-cases-for-popf.patch new file mode 100644 index 00000000000..c99594537de --- /dev/null +++ b/queue-4.4/selftests-x86-entry_from_vm86-add-test-cases-for-popf.patch @@ -0,0 +1,108 @@ +From 78393fdde2a456cafa414b171c90f26a3df98b20 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Tue, 13 Mar 2018 22:03:11 -0700 +Subject: selftests/x86/entry_from_vm86: Add test cases for POPF + +From: Andy Lutomirski + +commit 78393fdde2a456cafa414b171c90f26a3df98b20 upstream. + +POPF is currently broken -- add tests to catch the error. This +results in: + + [RUN] POPF with VIP set and IF clear from vm86 mode + [INFO] Exited vm86 mode due to STI + [FAIL] Incorrect return reason (started at eip = 0xd, ended at eip = 0xf) + +because POPF currently fails to check IF before reporting a pending +interrupt. + +This patch also makes the FAIL message a bit more informative. + +Reported-by: Bart Oldeman +Signed-off-by: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stas Sergeev +Cc: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: http://lkml.kernel.org/r/a16270b5cfe7832d6d00c479d0f871066cbdb52b.1521003603.git.luto@kernel.org +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + tools/testing/selftests/x86/entry_from_vm86.c | 30 +++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +--- a/tools/testing/selftests/x86/entry_from_vm86.c ++++ b/tools/testing/selftests/x86/entry_from_vm86.c +@@ -95,6 +95,10 @@ asm ( + "int3\n\t" + "vmcode_int80:\n\t" + "int $0x80\n\t" ++ "vmcode_popf_hlt:\n\t" ++ "push %ax\n\t" ++ "popf\n\t" ++ "hlt\n\t" + "vmcode_umip:\n\t" + /* addressing via displacements */ + "smsw (2052)\n\t" +@@ -124,8 +128,8 @@ asm ( + + extern unsigned char vmcode[], end_vmcode[]; + extern unsigned char vmcode_bound[], vmcode_sysenter[], vmcode_syscall[], +- vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_umip[], +- vmcode_umip_str[], vmcode_umip_sldt[]; ++ vmcode_sti[], vmcode_int3[], vmcode_int80[], vmcode_popf_hlt[], ++ vmcode_umip[], vmcode_umip_str[], vmcode_umip_sldt[]; + + /* Returns false if the test was skipped. */ + static bool do_test(struct vm86plus_struct *v86, unsigned long eip, +@@ -175,7 +179,7 @@ static bool do_test(struct vm86plus_stru + (VM86_TYPE(ret) == rettype && VM86_ARG(ret) == retarg)) { + printf("[OK]\tReturned correctly\n"); + } else { +- printf("[FAIL]\tIncorrect return reason\n"); ++ printf("[FAIL]\tIncorrect return reason (started at eip = 0x%lx, ended at eip = 0x%lx)\n", eip, v86->regs.eip); + nerrs++; + } + +@@ -264,6 +268,9 @@ int main(void) + v86.regs.ds = load_addr / 16; + v86.regs.es = load_addr / 16; + ++ /* Use the end of the page as our stack. */ ++ v86.regs.esp = 4096; ++ + assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */ + + /* #BR -- should deliver SIG??? */ +@@ -295,6 +302,23 @@ int main(void) + v86.regs.eflags &= ~X86_EFLAGS_IF; + do_test(&v86, vmcode_sti - vmcode, VM86_STI, 0, "STI with VIP set"); + ++ /* POPF with VIP set but IF clear: should not trap */ ++ v86.regs.eflags = X86_EFLAGS_VIP; ++ v86.regs.eax = 0; ++ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP set and IF clear"); ++ ++ /* POPF with VIP set and IF set: should trap */ ++ v86.regs.eflags = X86_EFLAGS_VIP; ++ v86.regs.eax = X86_EFLAGS_IF; ++ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_STI, 0, "POPF with VIP and IF set"); ++ ++ /* POPF with VIP clear and IF set: should not trap */ ++ v86.regs.eflags = 0; ++ v86.regs.eax = X86_EFLAGS_IF; ++ do_test(&v86, vmcode_popf_hlt - vmcode, VM86_UNKNOWN, 0, "POPF with VIP clear and IF set"); ++ ++ v86.regs.eflags = 0; ++ + /* INT3 -- should cause #BP */ + do_test(&v86, vmcode_int3 - vmcode, VM86_TRAP, 3, "INT3"); + diff --git a/queue-4.4/selftests-x86-entry_from_vm86-exit-with-1-if-we-fail.patch b/queue-4.4/selftests-x86-entry_from_vm86-exit-with-1-if-we-fail.patch new file mode 100644 index 00000000000..a66691bb9ce --- /dev/null +++ b/queue-4.4/selftests-x86-entry_from_vm86-exit-with-1-if-we-fail.patch @@ -0,0 +1,43 @@ +From 327d53d005ca47b10eae940616ed11c569f75a9b Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Tue, 13 Mar 2018 22:03:10 -0700 +Subject: selftests/x86/entry_from_vm86: Exit with 1 if we fail + +From: Andy Lutomirski + +commit 327d53d005ca47b10eae940616ed11c569f75a9b upstream. + +Fix a logic error that caused the test to exit with 0 even if test +cases failed. + +Signed-off-by: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Stas Sergeev +Cc: Thomas Gleixner +Cc: bartoldeman@gmail.com +Cc: stable@vger.kernel.org +Link: http://lkml.kernel.org/r/b1cc37144038958a469c8f70a5f47a6a5638636a.1521003603.git.luto@kernel.org +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + tools/testing/selftests/x86/entry_from_vm86.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/testing/selftests/x86/entry_from_vm86.c ++++ b/tools/testing/selftests/x86/entry_from_vm86.c +@@ -231,7 +231,7 @@ int main(void) + clearhandler(SIGSEGV); + + /* Make sure nothing explodes if we fork. */ +- if (fork() > 0) ++ if (fork() == 0) + return 0; + + return (nerrs == 0 ? 0 : 1); diff --git a/queue-4.4/series b/queue-4.4/series index 5c144b2631a..c629dfe03f3 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -107,3 +107,18 @@ asoc-nuc900-fix-a-loop-timeout-test.patch ipvlan-add-l2-check-for-packets-arriving-via-virtual-devices.patch rcutorture-configinit-fix-build-directory-error-message.patch ima-relax-requiring-a-file-signature-for-new-files-with-zero-length.patch +selftests-x86-entry_from_vm86-exit-with-1-if-we-fail.patch +selftests-x86-add-tests-for-user-mode-instruction-prevention.patch +selftests-x86-add-tests-for-the-str-and-sldt-instructions.patch +selftests-x86-entry_from_vm86-add-test-cases-for-popf.patch +x86-vm86-32-fix-popf-emulation.patch +x86-mm-fix-vmalloc_fault-to-use-pxd_large.patch +alsa-pcm-fix-uaf-in-snd_pcm_oss_get_formats.patch +alsa-hda-revert-power_save-option-default-value.patch +alsa-seq-fix-possible-uaf-in-snd_seq_check_queue.patch +alsa-seq-clear-client-entry-before-deleting-else-at-closing.patch +drm-amdgpu-dce-don-t-turn-off-dp-sink-when-disconnected.patch +fs-teach-path_connected-to-handle-nfs-filesystems-with-multiple-roots.patch +lock_parent-needs-to-recheck-if-dentry-got-__dentry_kill-ed-under-it.patch +fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch +fs-aio-use-rcu-accessors-for-kioctx_table-table.patch diff --git a/queue-4.4/x86-mm-fix-vmalloc_fault-to-use-pxd_large.patch b/queue-4.4/x86-mm-fix-vmalloc_fault-to-use-pxd_large.patch new file mode 100644 index 00000000000..64c3bd9518f --- /dev/null +++ b/queue-4.4/x86-mm-fix-vmalloc_fault-to-use-pxd_large.patch @@ -0,0 +1,59 @@ +From 18a955219bf7d9008ce480d4451b6b8bf4483a22 Mon Sep 17 00:00:00 2001 +From: Toshi Kani +Date: Tue, 13 Mar 2018 11:03:46 -0600 +Subject: x86/mm: Fix vmalloc_fault to use pXd_large + +From: Toshi Kani + +commit 18a955219bf7d9008ce480d4451b6b8bf4483a22 upstream. + +Gratian Crisan reported that vmalloc_fault() crashes when CONFIG_HUGETLBFS +is not set since the function inadvertently uses pXn_huge(), which always +return 0 in this case. ioremap() does not depend on CONFIG_HUGETLBFS. + +Fix vmalloc_fault() to call pXd_large() instead. + +Fixes: f4eafd8bcd52 ("x86/mm: Fix vmalloc_fault() to handle large pages properly") +Reported-by: Gratian Crisan +Signed-off-by: Toshi Kani +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Cc: linux-mm@kvack.org +Cc: Borislav Petkov +Cc: Andy Lutomirski +Link: https://lkml.kernel.org/r/20180313170347.3829-2-toshi.kani@hpe.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/mm/fault.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/mm/fault.c ++++ b/arch/x86/mm/fault.c +@@ -287,7 +287,7 @@ static noinline int vmalloc_fault(unsign + if (!pmd_k) + return -1; + +- if (pmd_huge(*pmd_k)) ++ if (pmd_large(*pmd_k)) + return 0; + + pte_k = pte_offset_kernel(pmd_k, address); +@@ -407,7 +407,7 @@ static noinline int vmalloc_fault(unsign + if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref)) + BUG(); + +- if (pud_huge(*pud)) ++ if (pud_large(*pud)) + return 0; + + pmd = pmd_offset(pud, address); +@@ -418,7 +418,7 @@ static noinline int vmalloc_fault(unsign + if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref)) + BUG(); + +- if (pmd_huge(*pmd)) ++ if (pmd_large(*pmd)) + return 0; + + pte_ref = pte_offset_kernel(pmd_ref, address); diff --git a/queue-4.4/x86-vm86-32-fix-popf-emulation.patch b/queue-4.4/x86-vm86-32-fix-popf-emulation.patch new file mode 100644 index 00000000000..3489cbc7b36 --- /dev/null +++ b/queue-4.4/x86-vm86-32-fix-popf-emulation.patch @@ -0,0 +1,44 @@ +From b5069782453459f6ec1fdeb495d9901a4545fcb5 Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Tue, 13 Mar 2018 22:03:12 -0700 +Subject: x86/vm86/32: Fix POPF emulation + +From: Andy Lutomirski + +commit b5069782453459f6ec1fdeb495d9901a4545fcb5 upstream. + +POPF would trap if VIP was set regardless of whether IF was set. Fix it. + +Suggested-by: Stas Sergeev +Reported-by: Bart Oldeman +Signed-off-by: Andy Lutomirski +Cc: Borislav Petkov +Cc: Brian Gerst +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: stable@vger.kernel.org +Fixes: 5ed92a8ab71f ("x86/vm86: Use the normal pt_regs area for vm86") +Link: http://lkml.kernel.org/r/ce95f40556e7b2178b6bc06ee9557827ff94bd28.1521003603.git.luto@kernel.org +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/vm86_32.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/vm86_32.c ++++ b/arch/x86/kernel/vm86_32.c +@@ -715,7 +715,8 @@ void handle_vm86_fault(struct kernel_vm8 + return; + + check_vip: +- if (VEFLAGS & X86_EFLAGS_VIP) { ++ if ((VEFLAGS & (X86_EFLAGS_VIP | X86_EFLAGS_VIF)) == ++ (X86_EFLAGS_VIP | X86_EFLAGS_VIF)) { + save_v86_state(regs, VM86_STI); + return; + }