public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	Michael Schmitz <schmitzmic@gmail.com>,
	Finn Thain <fthain@linux-m68k.org>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Sasha Levin <sashal@kernel.org>,
	axboe@kernel.dk, elver@google.com, ebiederm@xmission.com,
	linux-m68k@lists.linux-m68k.org
Subject: [PATCH AUTOSEL 5.14 23/40] m68k: Handle arrivals of multiple signals correctly
Date: Tue,  5 Oct 2021 09:50:02 -0400	[thread overview]
Message-ID: <20211005135020.214291-23-sashal@kernel.org> (raw)
In-Reply-To: <20211005135020.214291-1-sashal@kernel.org>

From: Al Viro <viro@zeniv.linux.org.uk>

[ Upstream commit 4bb0bd81ce5e97092dfda6a106d414b703ec0ee8 ]

When we have several pending signals, have entered with the kernel
with large exception frame *and* have already built at least one
sigframe, regs->stkadj is going to be non-zero and regs->format/sr/pc
are going to be junk - the real values are in shifted exception stack
frame we'd built when putting together the first sigframe.

If that happens, subsequent sigframes are going to be garbage.
Not hard to fix - just need to find the "adjusted" frame first
and look for format/vector/sr/pc in it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Reviewed-by: Michael Schmitz <schmitzmic@gmail.com>
Tested-by: Finn Thain <fthain@linux-m68k.org>
Link: https://lore.kernel.org/r/YP2dBIAPTaVvHiZ6@zeniv-ca.linux.org.uk
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 arch/m68k/kernel/signal.c | 88 +++++++++++++++++++--------------------
 1 file changed, 42 insertions(+), 46 deletions(-)

diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 8f215e79e70e..cd11eb101eac 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -447,7 +447,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
 
 	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
 		fpu_version = sc->sc_fpstate[0];
-		if (CPU_IS_020_OR_030 &&
+		if (CPU_IS_020_OR_030 && !regs->stkadj &&
 		    regs->vector >= (VEC_FPBRUC * 4) &&
 		    regs->vector <= (VEC_FPNAN * 4)) {
 			/* Clear pending exception in 68882 idle frame */
@@ -510,7 +510,7 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *
 		if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
 			context_size = fpstate[1];
 		fpu_version = fpstate[0];
-		if (CPU_IS_020_OR_030 &&
+		if (CPU_IS_020_OR_030 && !regs->stkadj &&
 		    regs->vector >= (VEC_FPBRUC * 4) &&
 		    regs->vector <= (VEC_FPNAN * 4)) {
 			/* Clear pending exception in 68882 idle frame */
@@ -832,18 +832,24 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw)
 	return 0;
 }
 
+static inline struct pt_regs *rte_regs(struct pt_regs *regs)
+{
+	return (void *)regs + regs->stkadj;
+}
+
 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
 			     unsigned long mask)
 {
+	struct pt_regs *tregs = rte_regs(regs);
 	sc->sc_mask = mask;
 	sc->sc_usp = rdusp();
 	sc->sc_d0 = regs->d0;
 	sc->sc_d1 = regs->d1;
 	sc->sc_a0 = regs->a0;
 	sc->sc_a1 = regs->a1;
-	sc->sc_sr = regs->sr;
-	sc->sc_pc = regs->pc;
-	sc->sc_formatvec = regs->format << 12 | regs->vector;
+	sc->sc_sr = tregs->sr;
+	sc->sc_pc = tregs->pc;
+	sc->sc_formatvec = tregs->format << 12 | tregs->vector;
 	save_a5_state(sc, regs);
 	save_fpu_state(sc, regs);
 }
@@ -851,6 +857,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
 static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
 {
 	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	struct pt_regs *tregs = rte_regs(regs);
 	greg_t __user *gregs = uc->uc_mcontext.gregs;
 	int err = 0;
 
@@ -871,9 +878,9 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
 	err |= __put_user(sw->a5, &gregs[13]);
 	err |= __put_user(sw->a6, &gregs[14]);
 	err |= __put_user(rdusp(), &gregs[15]);
-	err |= __put_user(regs->pc, &gregs[16]);
-	err |= __put_user(regs->sr, &gregs[17]);
-	err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
+	err |= __put_user(tregs->pc, &gregs[16]);
+	err |= __put_user(tregs->sr, &gregs[17]);
+	err |= __put_user((tregs->format << 12) | tregs->vector, &uc->uc_formatvec);
 	err |= rt_save_fpu_state(uc, regs);
 	return err;
 }
@@ -890,13 +897,14 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
 			struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	int fsize = frame_extra_sizes(regs->format);
+	struct pt_regs *tregs = rte_regs(regs);
+	int fsize = frame_extra_sizes(tregs->format);
 	struct sigcontext context;
 	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
 		pr_debug("setup_frame: Unknown frame format %#x\n",
-			 regs->format);
+			 tregs->format);
 		return -EFAULT;
 	}
 
@@ -907,7 +915,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
 
 	err |= __put_user(sig, &frame->sig);
 
-	err |= __put_user(regs->vector, &frame->code);
+	err |= __put_user(tregs->vector, &frame->code);
 	err |= __put_user(&frame->sc, &frame->psc);
 
 	if (_NSIG_WORDS > 1)
@@ -933,34 +941,28 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
 
 	push_cache ((unsigned long) &frame->retcode);
 
-	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
-	adjustformat(regs);
-
 	/*
 	 * This is subtle; if we build more than one sigframe, all but the
 	 * first one will see frame format 0 and have fsize == 0, so we won't
 	 * screw stkadj.
 	 */
-	if (fsize)
+	if (fsize) {
 		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
+		tregs = rte_regs(regs);
 		pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
 		tregs->vector = 0;
 		tregs->format = 0;
-		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	adjustformat(regs);
+
 	return 0;
 }
 
@@ -968,7 +970,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 			   struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int fsize = frame_extra_sizes(regs->format);
+	struct pt_regs *tregs = rte_regs(regs);
+	int fsize = frame_extra_sizes(tregs->format);
 	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
@@ -1018,34 +1021,27 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 
 	push_cache ((unsigned long) &frame->retcode);
 
-	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
-	adjustformat(regs);
-
 	/*
 	 * This is subtle; if we build more than one sigframe, all but the
 	 * first one will see frame format 0 and have fsize == 0, so we won't
 	 * screw stkadj.
 	 */
-	if (fsize)
+	if (fsize) {
 		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
+		tregs = rte_regs(regs);
 		pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
 		tregs->vector = 0;
 		tregs->format = 0;
-		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	adjustformat(regs);
 	return 0;
 }
 
-- 
2.33.0


  parent reply	other threads:[~2021-10-05 13:53 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-05 13:49 [PATCH AUTOSEL 5.14 01/40] ext4: check and update i_disksize properly Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 02/40] ext4: correct the error path of ext4_write_inline_data_end() Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 03/40] ASoC: Intel: sof_sdw: tag SoundWire BEs as non-atomic Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 04/40] ext4: enforce buffer head state assertion in ext4_da_map_blocks Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 05/40] ALSA: oxfw: fix transmission method for Loud models based on OXFW971 Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 06/40] dt-bindings: interconnect: sdm660: Add missing a2noc qos clocks Sasha Levin
2021-10-05 19:11   ` Georgi Djakov
2021-10-06 15:12     ` Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 07/40] interconnect: qcom: " Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 08/40] ALSA: usb-audio: Unify mixer resume and reset_resume procedure Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 09/40] netfilter: ipset: Fix oversized kvmalloc() calls Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 10/40] HID: betop: fix slab-out-of-bounds Write in betop_probe Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 11/40] HID: apple: Fix logical maximum and usage maximum of Magic Keyboard JIS Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 12/40] netfilter: ip6_tables: zero-initialize fragment offset Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 13/40] HID: wacom: Add new Intuos BT (CTL-4100WL/CTL-6100WL) device IDs Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 14/40] HID: amd_sfh: Fix potential NULL pointer dereference Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 15/40] ASoC: SOF: loader: release_firmware() on load failure to avoid batching Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 16/40] KVM: arm64: nvhe: Fix missing FORCE for hyp-reloc.S build rule Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 17/40] netfilter: nf_tables: Fix oversized kvmalloc() calls Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 18/40] netfilter: nf_nat_masquerade: make async masq_inet6_event handling generic Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 19/40] netfilter: nf_nat_masquerade: defer conntrack walk to work queue Sasha Levin
2021-10-05 13:49 ` [PATCH AUTOSEL 5.14 20/40] netfilter: conntrack: serialize hash resizes and cleanups Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 21/40] mac80211: Drop frames from invalid MAC address in ad-hoc mode Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 22/40] pinctrl: qcom: sc7280: Add PM suspend callbacks Sasha Levin
2021-10-05 13:50 ` Sasha Levin [this message]
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 24/40] hwmon: (ltc2947) Properly handle errors when looking for the external clock Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 25/40] net: prevent user from passing illegal stab size Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 26/40] mac80211: check return value of rhashtable_init Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 27/40] net: bgmac-platform: handle mac-address deferral Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 28/40] net: mdiobus: Fix memory leak in __mdiobus_register Sasha Levin
2021-10-05 14:02   ` Andrew Lunn
2021-10-06 15:12     ` Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 29/40] nvme: add command id quirk for apple controllers Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 30/40] vboxfs: fix broken legacy mount signature checking Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 31/40] net: sun: SUNVNET_COMMON should depend on INET Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 32/40] drm/amdgpu: fix gart.bo pin_count leak Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 33/40] scsi: ses: Fix unsigned comparison with less than zero Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 34/40] scsi: virtio_scsi: Fix spelling mistake "Unsupport" -> "Unsupported" Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 35/40] scsi: qla2xxx: Fix excessive messages during device logout Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 36/40] perf/x86: Reset destroy callback on event init failure Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 37/40] perf/core: fix userpage->time_enabled of inactive events Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 38/40] sched: Always inline is_percpu_thread() Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 39/40] io_uring: kill fasync Sasha Levin
2021-10-05 13:50 ` [PATCH AUTOSEL 5.14 40/40] hwmon: (pmbus/ibm-cffps) max_power_out swap changes Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211005135020.214291-23-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=ebiederm@xmission.com \
    --cc=elver@google.com \
    --cc=fthain@linux-m68k.org \
    --cc=geert@linux-m68k.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    --cc=schmitzmic@gmail.com \
    --cc=stable@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox