]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jun 2024 12:45:48 +0000 (14:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Jun 2024 12:45:48 +0000 (14:45 +0200)
added patches:
afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch
drm-i915-audio-fix-audio-time-stamp-programming-for-dp.patch
mmc-core-do-not-force-a-retune-before-rpmb-switch.patch
nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch
riscv-signal-handle-syscall-restart-before-get_signal.patch

queue-6.1/afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch [new file with mode: 0644]
queue-6.1/drm-i915-audio-fix-audio-time-stamp-programming-for-dp.patch [new file with mode: 0644]
queue-6.1/mmc-core-do-not-force-a-retune-before-rpmb-switch.patch [new file with mode: 0644]
queue-6.1/nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch [new file with mode: 0644]
queue-6.1/riscv-signal-handle-syscall-restart-before-get_signal.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch b/queue-6.1/afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch
new file mode 100644 (file)
index 0000000..4a07b1e
--- /dev/null
@@ -0,0 +1,50 @@
+From 29be9100aca2915fab54b5693309bc42956542e5 Mon Sep 17 00:00:00 2001
+From: Marc Dionne <marc.dionne@auristor.com>
+Date: Fri, 24 May 2024 17:17:55 +0100
+Subject: afs: Don't cross .backup mountpoint from backup volume
+
+From: Marc Dionne <marc.dionne@auristor.com>
+
+commit 29be9100aca2915fab54b5693309bc42956542e5 upstream.
+
+Don't cross a mountpoint that explicitly specifies a backup volume
+(target is <vol>.backup) when starting from a backup volume.
+
+It it not uncommon to mount a volume's backup directly in the volume
+itself.  This can cause tools that are not paying attention to get
+into a loop mounting the volume onto itself as they attempt to
+traverse the tree, leading to a variety of problems.
+
+This doesn't prevent the general case of loops in a sequence of
+mountpoints, but addresses a common special case in the same way
+as other afs clients.
+
+Reported-by: Jan Henrik Sylvester <jan.henrik.sylvester@uni-hamburg.de>
+Link: http://lists.infradead.org/pipermail/linux-afs/2024-May/008454.html
+Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
+Link: http://lists.infradead.org/pipermail/linux-afs/2024-February/008074.html
+Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Link: https://lore.kernel.org/r/768760.1716567475@warthog.procyon.org.uk
+Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
+cc: linux-afs@lists.infradead.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/afs/mntpt.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/afs/mntpt.c
++++ b/fs/afs/mntpt.c
+@@ -140,6 +140,11 @@ static int afs_mntpt_set_params(struct f
+               put_page(page);
+               if (ret < 0)
+                       return ret;
++
++              /* Don't cross a backup volume mountpoint from a backup volume */
++              if (src_as->volume && src_as->volume->type == AFSVL_BACKVOL &&
++                  ctx->type == AFSVL_BACKVOL)
++                      return -ENODEV;
+       }
+       return 0;
diff --git a/queue-6.1/drm-i915-audio-fix-audio-time-stamp-programming-for-dp.patch b/queue-6.1/drm-i915-audio-fix-audio-time-stamp-programming-for-dp.patch
new file mode 100644 (file)
index 0000000..90d75a7
--- /dev/null
@@ -0,0 +1,171 @@
+From c66b8356273c8d22498f88e4223af47a7bf8a23c Mon Sep 17 00:00:00 2001
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Date: Tue, 30 Apr 2024 14:48:25 +0530
+Subject: drm/i915/audio: Fix audio time stamp programming for DP
+
+From: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+
+commit c66b8356273c8d22498f88e4223af47a7bf8a23c upstream.
+
+Intel hardware is capable of programming the Maud/Naud SDPs on its
+own based on real-time clocks. While doing so, it takes care
+of any deviations from the theoretical values. Programming the registers
+explicitly with static values can interfere with this logic. Therefore,
+let the HW decide the Maud and Naud SDPs on it's own.
+
+Cc: stable@vger.kernel.org # v5.17
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8097
+Co-developed-by: Kai Vehmanen <kai.vehmanen@intel.com>
+Signed-off-by: Kai Vehmanen <kai.vehmanen@intel.com>
+Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>
+Reviewed-by: Uma Shankar <uma.shankar@intel.com>
+Signed-off-by: Animesh Manna <animesh.manna@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240430091825.733499-1-chaitanya.kumar.borah@intel.com
+(cherry picked from commit 8e056b50d92ae7f4d6895d1c97a69a2a953cf97b)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/i915/display/intel_audio.c |  116 ++---------------------------
+ 1 file changed, 9 insertions(+), 107 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_audio.c
++++ b/drivers/gpu/drm/i915/display/intel_audio.c
+@@ -73,19 +73,6 @@ struct intel_audio_funcs {
+                                   const struct drm_connector_state *old_conn_state);
+ };
+-/* DP N/M table */
+-#define LC_810M       810000
+-#define LC_540M       540000
+-#define LC_270M       270000
+-#define LC_162M       162000
+-
+-struct dp_aud_n_m {
+-      int sample_rate;
+-      int clock;
+-      u16 m;
+-      u16 n;
+-};
+-
+ struct hdmi_aud_ncts {
+       int sample_rate;
+       int clock;
+@@ -93,60 +80,6 @@ struct hdmi_aud_ncts {
+       int cts;
+ };
+-/* Values according to DP 1.4 Table 2-104 */
+-static const struct dp_aud_n_m dp_aud_n_m[] = {
+-      { 32000, LC_162M, 1024, 10125 },
+-      { 44100, LC_162M, 784, 5625 },
+-      { 48000, LC_162M, 512, 3375 },
+-      { 64000, LC_162M, 2048, 10125 },
+-      { 88200, LC_162M, 1568, 5625 },
+-      { 96000, LC_162M, 1024, 3375 },
+-      { 128000, LC_162M, 4096, 10125 },
+-      { 176400, LC_162M, 3136, 5625 },
+-      { 192000, LC_162M, 2048, 3375 },
+-      { 32000, LC_270M, 1024, 16875 },
+-      { 44100, LC_270M, 784, 9375 },
+-      { 48000, LC_270M, 512, 5625 },
+-      { 64000, LC_270M, 2048, 16875 },
+-      { 88200, LC_270M, 1568, 9375 },
+-      { 96000, LC_270M, 1024, 5625 },
+-      { 128000, LC_270M, 4096, 16875 },
+-      { 176400, LC_270M, 3136, 9375 },
+-      { 192000, LC_270M, 2048, 5625 },
+-      { 32000, LC_540M, 1024, 33750 },
+-      { 44100, LC_540M, 784, 18750 },
+-      { 48000, LC_540M, 512, 11250 },
+-      { 64000, LC_540M, 2048, 33750 },
+-      { 88200, LC_540M, 1568, 18750 },
+-      { 96000, LC_540M, 1024, 11250 },
+-      { 128000, LC_540M, 4096, 33750 },
+-      { 176400, LC_540M, 3136, 18750 },
+-      { 192000, LC_540M, 2048, 11250 },
+-      { 32000, LC_810M, 1024, 50625 },
+-      { 44100, LC_810M, 784, 28125 },
+-      { 48000, LC_810M, 512, 16875 },
+-      { 64000, LC_810M, 2048, 50625 },
+-      { 88200, LC_810M, 1568, 28125 },
+-      { 96000, LC_810M, 1024, 16875 },
+-      { 128000, LC_810M, 4096, 50625 },
+-      { 176400, LC_810M, 3136, 28125 },
+-      { 192000, LC_810M, 2048, 16875 },
+-};
+-
+-static const struct dp_aud_n_m *
+-audio_config_dp_get_n_m(const struct intel_crtc_state *crtc_state, int rate)
+-{
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) {
+-              if (rate == dp_aud_n_m[i].sample_rate &&
+-                  crtc_state->port_clock == dp_aud_n_m[i].clock)
+-                      return &dp_aud_n_m[i];
+-      }
+-
+-      return NULL;
+-}
+-
+ static const struct {
+       int clock;
+       u32 config;
+@@ -392,48 +325,17 @@ static void
+ hsw_dp_audio_config_update(struct intel_encoder *encoder,
+                          const struct intel_crtc_state *crtc_state)
+ {
+-      struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+-      struct i915_audio_component *acomp = dev_priv->display.audio.component;
++      struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+-      enum port port = encoder->port;
+-      const struct dp_aud_n_m *nm;
+-      int rate;
+-      u32 tmp;
+-
+-      rate = acomp ? acomp->aud_sample_rate[port] : 0;
+-      nm = audio_config_dp_get_n_m(crtc_state, rate);
+-      if (nm)
+-              drm_dbg_kms(&dev_priv->drm, "using Maud %u, Naud %u\n", nm->m,
+-                          nm->n);
+-      else
+-              drm_dbg_kms(&dev_priv->drm, "using automatic Maud, Naud\n");
+-
+-      tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder));
+-      tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+-      tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+-      tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+-      tmp |= AUD_CONFIG_N_VALUE_INDEX;
+-
+-      if (nm) {
+-              tmp &= ~AUD_CONFIG_N_MASK;
+-              tmp |= AUD_CONFIG_N(nm->n);
+-              tmp |= AUD_CONFIG_N_PROG_ENABLE;
+-      }
+-
+-      intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp);
+-
+-      tmp = intel_de_read(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
+-      tmp &= ~AUD_CONFIG_M_MASK;
+-      tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+-      tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+-
+-      if (nm) {
+-              tmp |= nm->m;
+-              tmp |= AUD_M_CTS_M_VALUE_INDEX;
+-              tmp |= AUD_M_CTS_M_PROG_ENABLE;
+-      }
+-      intel_de_write(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
++      /* Enable time stamps. Let HW calculate Maud/Naud values */
++      intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder),
++                   AUD_CONFIG_N_VALUE_INDEX |
++                   AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK |
++                   AUD_CONFIG_UPPER_N_MASK |
++                   AUD_CONFIG_LOWER_N_MASK |
++                   AUD_CONFIG_N_PROG_ENABLE,
++                   AUD_CONFIG_N_VALUE_INDEX);
+ }
+ static void
diff --git a/queue-6.1/mmc-core-do-not-force-a-retune-before-rpmb-switch.patch b/queue-6.1/mmc-core-do-not-force-a-retune-before-rpmb-switch.patch
new file mode 100644 (file)
index 0000000..5c2d8e8
--- /dev/null
@@ -0,0 +1,66 @@
+From 67380251e8bbd3302c64fea07f95c31971b91c22 Mon Sep 17 00:00:00 2001
+From: Jorge Ramirez-Ortiz <jorge@foundries.io>
+Date: Wed, 3 Jan 2024 12:29:11 +0100
+Subject: mmc: core: Do not force a retune before RPMB switch
+
+From: Jorge Ramirez-Ortiz <jorge@foundries.io>
+
+commit 67380251e8bbd3302c64fea07f95c31971b91c22 upstream.
+
+Requesting a retune before switching to the RPMB partition has been
+observed to cause CRC errors on the RPMB reads (-EILSEQ).
+
+Since RPMB reads can not be retried, the clients would be directly
+affected by the errors.
+
+This commit disables the retune request prior to switching to the RPMB
+partition: mmc_retune_pause() no longer triggers a retune before the
+pause period begins.
+
+This was verified with the sdhci-of-arasan driver (ZynqMP) configured
+for HS200 using two separate eMMC cards (DG4064 and 064GB2). In both
+cases, the error was easy to reproduce triggering every few tenths of
+reads.
+
+With this commit, systems that were utilizing OP-TEE to access RPMB
+variables will experience an enhanced performance. Specifically, when
+OP-TEE is configured to employ RPMB as a secure storage solution, it not
+only writes the data but also the secure filesystem within the
+partition. As a result, retrieving any variable involves multiple RPMB
+reads, typically around five.
+
+For context, on ZynqMP, each retune request consumed approximately
+8ms. Consequently, reading any RPMB variable used to take at the very
+minimum 40ms.
+
+After droping the need to retune before switching to the RPMB partition,
+this is no longer the case.
+
+Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
+Acked-by: Avri Altman <avri.altman@wdc.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240103112911.2954632-1-jorge@foundries.io
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/host.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mmc/core/host.c
++++ b/drivers/mmc/core/host.c
+@@ -119,13 +119,12 @@ void mmc_retune_enable(struct mmc_host *
+ /*
+  * Pause re-tuning for a small set of operations.  The pause begins after the
+- * next command and after first doing re-tuning.
++ * next command.
+  */
+ void mmc_retune_pause(struct mmc_host *host)
+ {
+       if (!host->retune_paused) {
+               host->retune_paused = 1;
+-              mmc_retune_needed(host);
+               mmc_retune_hold(host);
+       }
+ }
diff --git a/queue-6.1/nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch b/queue-6.1/nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch
new file mode 100644 (file)
index 0000000..ee2791e
--- /dev/null
@@ -0,0 +1,122 @@
+From f5d4e04634c9cf68bdf23de08ada0bb92e8befe7 Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Date: Mon, 20 May 2024 22:26:19 +0900
+Subject: nilfs2: fix use-after-free of timer for log writer thread
+
+From: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+
+commit f5d4e04634c9cf68bdf23de08ada0bb92e8befe7 upstream.
+
+Patch series "nilfs2: fix log writer related issues".
+
+This bug fix series covers three nilfs2 log writer-related issues,
+including a timer use-after-free issue and potential deadlock issue on
+unmount, and a potential freeze issue in event synchronization found
+during their analysis.  Details are described in each commit log.
+
+
+This patch (of 3):
+
+A use-after-free issue has been reported regarding the timer sc_timer on
+the nilfs_sc_info structure.
+
+The problem is that even though it is used to wake up a sleeping log
+writer thread, sc_timer is not shut down until the nilfs_sc_info structure
+is about to be freed, and is used regardless of the thread's lifetime.
+
+Fix this issue by limiting the use of sc_timer only while the log writer
+thread is alive.
+
+Link: https://lkml.kernel.org/r/20240520132621.4054-1-konishi.ryusuke@gmail.com
+Link: https://lkml.kernel.org/r/20240520132621.4054-2-konishi.ryusuke@gmail.com
+Fixes: fdce895ea5dd ("nilfs2: change sc_timer from a pointer to an embedded one in struct nilfs_sc_info")
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Reported-by: "Bai, Shuangpeng" <sjb7183@psu.edu>
+Closes: https://groups.google.com/g/syzkaller/c/MK_LYqtt8ko/m/8rgdWeseAwAJ
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nilfs2/segment.c |   25 +++++++++++++++++++------
+ 1 file changed, 19 insertions(+), 6 deletions(-)
+
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -2159,8 +2159,10 @@ static void nilfs_segctor_start_timer(st
+ {
+       spin_lock(&sci->sc_state_lock);
+       if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) {
+-              sci->sc_timer.expires = jiffies + sci->sc_interval;
+-              add_timer(&sci->sc_timer);
++              if (sci->sc_task) {
++                      sci->sc_timer.expires = jiffies + sci->sc_interval;
++                      add_timer(&sci->sc_timer);
++              }
+               sci->sc_state |= NILFS_SEGCTOR_COMMIT;
+       }
+       spin_unlock(&sci->sc_state_lock);
+@@ -2378,10 +2380,21 @@ int nilfs_construct_dsync_segment(struct
+  */
+ static void nilfs_segctor_accept(struct nilfs_sc_info *sci)
+ {
++      bool thread_is_alive;
++
+       spin_lock(&sci->sc_state_lock);
+       sci->sc_seq_accepted = sci->sc_seq_request;
++      thread_is_alive = (bool)sci->sc_task;
+       spin_unlock(&sci->sc_state_lock);
+-      del_timer_sync(&sci->sc_timer);
++
++      /*
++       * This function does not race with the log writer thread's
++       * termination.  Therefore, deleting sc_timer, which should not be
++       * done after the log writer thread exits, can be done safely outside
++       * the area protected by sc_state_lock.
++       */
++      if (thread_is_alive)
++              del_timer_sync(&sci->sc_timer);
+ }
+ /**
+@@ -2407,7 +2420,7 @@ static void nilfs_segctor_notify(struct
+                       sci->sc_flush_request &= ~FLUSH_DAT_BIT;
+               /* re-enable timer if checkpoint creation was not done */
+-              if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
++              if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && sci->sc_task &&
+                   time_before(jiffies, sci->sc_timer.expires))
+                       add_timer(&sci->sc_timer);
+       }
+@@ -2597,6 +2610,7 @@ static int nilfs_segctor_thread(void *ar
+       int timeout = 0;
+       sci->sc_timer_task = current;
++      timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0);
+       /* start sync. */
+       sci->sc_task = current;
+@@ -2663,6 +2677,7 @@ static int nilfs_segctor_thread(void *ar
+  end_thread:
+       /* end sync. */
+       sci->sc_task = NULL;
++      del_timer_sync(&sci->sc_timer);
+       wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */
+       spin_unlock(&sci->sc_state_lock);
+       return 0;
+@@ -2726,7 +2741,6 @@ static struct nilfs_sc_info *nilfs_segct
+       INIT_LIST_HEAD(&sci->sc_gc_inodes);
+       INIT_LIST_HEAD(&sci->sc_iput_queue);
+       INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func);
+-      timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0);
+       sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
+       sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;
+@@ -2812,7 +2826,6 @@ static void nilfs_segctor_destroy(struct
+       down_write(&nilfs->ns_segctor_sem);
+-      del_timer_sync(&sci->sc_timer);
+       kfree(sci);
+ }
diff --git a/queue-6.1/riscv-signal-handle-syscall-restart-before-get_signal.patch b/queue-6.1/riscv-signal-handle-syscall-restart-before-get_signal.patch
new file mode 100644 (file)
index 0000000..61435eb
--- /dev/null
@@ -0,0 +1,171 @@
+From ce4f78f1b53d3327fbd32764aa333bf05fb68818 Mon Sep 17 00:00:00 2001
+From: Haorong Lu <ancientmodern4@gmail.com>
+Date: Thu, 3 Aug 2023 15:44:54 -0700
+Subject: riscv: signal: handle syscall restart before get_signal
+
+From: Haorong Lu <ancientmodern4@gmail.com>
+
+commit ce4f78f1b53d3327fbd32764aa333bf05fb68818 upstream.
+
+In the current riscv implementation, blocking syscalls like read() may
+not correctly restart after being interrupted by ptrace. This problem
+arises when the syscall restart process in arch_do_signal_or_restart()
+is bypassed due to changes to the regs->cause register, such as an
+ebreak instruction.
+
+Steps to reproduce:
+1. Interrupt the tracee process with PTRACE_SEIZE & PTRACE_INTERRUPT.
+2. Backup original registers and instruction at new_pc.
+3. Change pc to new_pc, and inject an instruction (like ebreak) to this
+   address.
+4. Resume with PTRACE_CONT and wait for the process to stop again after
+   executing ebreak.
+5. Restore original registers and instructions, and detach from the
+   tracee process.
+6. Now the read() syscall in tracee will return -1 with errno set to
+   ERESTARTSYS.
+
+Specifically, during an interrupt, the regs->cause changes from
+EXC_SYSCALL to EXC_BREAKPOINT due to the injected ebreak, which is
+inaccessible via ptrace so we cannot restore it. This alteration breaks
+the syscall restart condition and ends the read() syscall with an
+ERESTARTSYS error. According to include/linux/errno.h, it should never
+be seen by user programs. X86 can avoid this issue as it checks the
+syscall condition using a register (orig_ax) exposed to user space.
+Arm64 handles syscall restart before calling get_signal, where it could
+be paused and inspected by ptrace/debugger.
+
+This patch adjusts the riscv implementation to arm64 style, which also
+checks syscall using a kernel register (syscallno). It ensures the
+syscall restart process is not bypassed when changes to the cause
+register occur, providing more consistent behavior across various
+architectures.
+
+For a simplified reproduction program, feel free to visit:
+https://github.com/ancientmodern/riscv-ptrace-bug-demo.
+
+Signed-off-by: Haorong Lu <ancientmodern4@gmail.com>
+Link: https://lore.kernel.org/r/20230803224458.4156006-1-ancientmodern4@gmail.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Cc: Conor Dooley <conor@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/kernel/signal.c |   85 ++++++++++++++++++++++++---------------------
+ 1 file changed, 46 insertions(+), 39 deletions(-)
+
+--- a/arch/riscv/kernel/signal.c
++++ b/arch/riscv/kernel/signal.c
+@@ -246,30 +246,6 @@ static void handle_signal(struct ksignal
+       sigset_t *oldset = sigmask_to_save();
+       int ret;
+-      /* Are we from a system call? */
+-      if (regs->cause == EXC_SYSCALL) {
+-              /* Avoid additional syscall restarting via ret_from_exception */
+-              regs->cause = -1UL;
+-              /* If so, check system call restarting.. */
+-              switch (regs->a0) {
+-              case -ERESTART_RESTARTBLOCK:
+-              case -ERESTARTNOHAND:
+-                      regs->a0 = -EINTR;
+-                      break;
+-
+-              case -ERESTARTSYS:
+-                      if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
+-                              regs->a0 = -EINTR;
+-                              break;
+-                      }
+-                      fallthrough;
+-              case -ERESTARTNOINTR:
+-                        regs->a0 = regs->orig_a0;
+-                      regs->epc -= 0x4;
+-                      break;
+-              }
+-      }
+-
+       rseq_signal_deliver(ksig, regs);
+       /* Set up the stack frame */
+@@ -283,36 +259,67 @@ static void handle_signal(struct ksignal
+ static void do_signal(struct pt_regs *regs)
+ {
++      unsigned long continue_addr = 0, restart_addr = 0;
++      int retval = 0;
+       struct ksignal ksig;
++      bool syscall = (regs->cause == EXC_SYSCALL);
+-      if (get_signal(&ksig)) {
+-              /* Actually deliver the signal */
+-              handle_signal(&ksig, regs);
+-              return;
+-      }
++      /* If we were from a system call, check for system call restarting */
++      if (syscall) {
++              continue_addr = regs->epc;
++              restart_addr = continue_addr - 4;
++              retval = regs->a0;
+-      /* Did we come from a system call? */
+-      if (regs->cause == EXC_SYSCALL) {
+               /* Avoid additional syscall restarting via ret_from_exception */
+               regs->cause = -1UL;
+-              /* Restart the system call - no handlers present */
+-              switch (regs->a0) {
++              /*
++               * Prepare for system call restart. We do this here so that a
++               * debugger will see the already changed PC.
++               */
++              switch (retval) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
+-                        regs->a0 = regs->orig_a0;
+-                      regs->epc -= 0x4;
+-                      break;
+               case -ERESTART_RESTARTBLOCK:
+-                        regs->a0 = regs->orig_a0;
+-                      regs->a7 = __NR_restart_syscall;
+-                      regs->epc -= 0x4;
++                      regs->a0 = regs->orig_a0;
++                      regs->epc = restart_addr;
+                       break;
+               }
+       }
+       /*
++       * Get the signal to deliver. When running under ptrace, at this point
++       * the debugger may change all of our registers.
++       */
++      if (get_signal(&ksig)) {
++              /*
++               * Depending on the signal settings, we may need to revert the
++               * decision to restart the system call, but skip this if a
++               * debugger has chosen to restart at a different PC.
++               */
++              if (regs->epc == restart_addr &&
++                  (retval == -ERESTARTNOHAND ||
++                   retval == -ERESTART_RESTARTBLOCK ||
++                   (retval == -ERESTARTSYS &&
++                    !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
++                      regs->a0 = -EINTR;
++                      regs->epc = continue_addr;
++              }
++
++              /* Actually deliver the signal */
++              handle_signal(&ksig, regs);
++              return;
++      }
++
++      /*
++       * Handle restarting a different system call. As above, if a debugger
++       * has chosen to restart at a different PC, ignore the restart.
++       */
++      if (syscall && regs->epc == restart_addr && retval == -ERESTART_RESTARTBLOCK)
++              regs->a7 = __NR_restart_syscall;
++
++      /*
+        * If there is no signal to deliver, we just put the saved
+        * sigmask back.
+        */
index 3b42b7f09b3d51afbe375b64b13376004163fd10..87906437d6045b8a8643a3386d2622fe2a5f4757 100644 (file)
@@ -3,3 +3,8 @@ drm-check-polling-initialized-before-enabling-in-drm_helper_probe_single_connect
 bluetooth-btrtl-add-missing-module_firmware-declarations.patch
 maple_tree-fix-allocation-in-mas_sparse_area.patch
 maple_tree-fix-mas_empty_area_rev-null-pointer-dereference.patch
+mmc-core-do-not-force-a-retune-before-rpmb-switch.patch
+afs-don-t-cross-.backup-mountpoint-from-backup-volume.patch
+riscv-signal-handle-syscall-restart-before-get_signal.patch
+nilfs2-fix-use-after-free-of-timer-for-log-writer-thread.patch
+drm-i915-audio-fix-audio-time-stamp-programming-for-dp.patch