diff --git a/TODO b/TODO index c397e69e0f..90900648f7 100644 --- a/TODO +++ b/TODO @@ -1065,7 +1065,7 @@ o Kernel/Protected Build Linux, applications do not have separate user and supervisor stacks; everything is done on the user stack. - In the implementation of up_sigdeliver, a copy of the + In the implementation of up_sigdeliver(), a copy of the register contents that will be restored is present on the stack and could be modified by the user application. Thus, if the user mucks with the return stack, problems could @@ -1077,6 +1077,12 @@ o Kernel/Protected Build return address and switch to supervisor mode. Other register are still modifiable and there is other possible mayhem that could be done. + + A better solution, in lieu of a kernel stack, would be to + eliminate the stack-based register save area and, instead, + save the registers in another, dedicated state save area in + the TCB. The only hesitation to this option is that it would + significantly increase the size of the TCB structure. Status: Open Priority: Medium-ish if are attempting to make a secure environment that may host malicious code. Very low for the typical FLAT build, diff --git a/arch/arm/src/arm/up_sigdeliver.c b/arch/arm/src/arm/up_sigdeliver.c index 6406536c30..afc843b1e1 100644 --- a/arch/arm/src/arm/up_sigdeliver.c +++ b/arch/arm/src/arm/up_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -92,14 +91,6 @@ void up_sigdeliver(void) up_copyfullstate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. we do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -108,9 +99,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -119,7 +110,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -131,8 +122,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/arm/src/armv6-m/up_sigdeliver.c b/arch/arm/src/armv6-m/up_sigdeliver.c index 1af19185c2..1688019729 100644 --- a/arch/arm/src/armv6-m/up_sigdeliver.c +++ b/arch/arm/src/armv6-m/up_sigdeliver.c @@ -77,7 +77,6 @@ void up_sigdeliver(void) struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS + 4]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -96,14 +95,6 @@ void up_sigdeliver(void) up_copyfullstate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -114,7 +105,7 @@ void up_sigdeliver(void) /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -135,12 +126,13 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_PRIMASK] = rtcb->xcp.saved_primask; - regs[REG_XPSR] = rtcb->xcp.saved_xpsr; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_PRIMASK] = rtcb->xcp.saved_primask; + regs[REG_XPSR] = rtcb->xcp.saved_xpsr; #ifdef CONFIG_BUILD_PROTECTED - regs[REG_LR] = rtcb->xcp.saved_lr; + regs[REG_LR] = rtcb->xcp.saved_lr; #endif + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/arm/src/armv7-a/arm_sigdeliver.c b/arch/arm/src/armv7-a/arm_sigdeliver.c index 5f07737110..e1f500b1e9 100644 --- a/arch/arm/src/armv7-a/arm_sigdeliver.c +++ b/arch/arm/src/armv7-a/arm_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -101,14 +100,6 @@ void up_sigdeliver(void) up_copyfullstate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. we do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the @@ -139,7 +130,7 @@ void up_sigdeliver(void) /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -160,7 +151,7 @@ void up_sigdeliver(void) /* Restore the saved errno value */ - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -172,8 +163,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ #ifdef CONFIG_SMP /* Restore the saved 'irqcount' and recover the critical section diff --git a/arch/arm/src/armv7-m/up_sigdeliver.c b/arch/arm/src/armv7-m/up_sigdeliver.c index b6b3c18240..e79f569d3d 100644 --- a/arch/arm/src/armv7-m/up_sigdeliver.c +++ b/arch/arm/src/armv7-m/up_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -101,14 +100,6 @@ void up_sigdeliver(void) up_copyfullstate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = (sig_deliver_t)rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the @@ -143,7 +134,7 @@ void up_sigdeliver(void) /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -164,7 +155,7 @@ void up_sigdeliver(void) /* Restore the saved errno value */ - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -176,16 +167,17 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_PC] = rtcb->xcp.saved_pc; #ifdef CONFIG_ARMV7M_USEBASEPRI - regs[REG_BASEPRI] = rtcb->xcp.saved_basepri; + regs[REG_BASEPRI] = rtcb->xcp.saved_basepri; #else - regs[REG_PRIMASK] = rtcb->xcp.saved_primask; + regs[REG_PRIMASK] = rtcb->xcp.saved_primask; #endif - regs[REG_XPSR] = rtcb->xcp.saved_xpsr; + regs[REG_XPSR] = rtcb->xcp.saved_xpsr; #ifdef CONFIG_BUILD_PROTECTED - regs[REG_LR] = rtcb->xcp.saved_lr; + regs[REG_LR] = rtcb->xcp.saved_lr; #endif + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ #ifdef CONFIG_SMP /* Restore the saved 'irqcount' and recover the critical section diff --git a/arch/arm/src/armv7-r/arm_sigdeliver.c b/arch/arm/src/armv7-r/arm_sigdeliver.c index 8e3e7a3940..6f560d14ff 100644 --- a/arch/arm/src/armv7-r/arm_sigdeliver.c +++ b/arch/arm/src/armv7-r/arm_sigdeliver.c @@ -72,7 +72,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -91,14 +90,6 @@ void up_sigdeliver(void) up_copyfullstate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. we do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -107,9 +98,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -132,6 +123,7 @@ void up_sigdeliver(void) regs[REG_PC] = rtcb->xcp.saved_pc; regs[REG_CPSR] = rtcb->xcp.saved_cpsr; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/avr/src/avr/up_sigdeliver.c b/arch/avr/src/avr/up_sigdeliver.c index 30bfa8b8e6..39cdfa5cb0 100644 --- a/arch/avr/src/avr/up_sigdeliver.c +++ b/arch/avr/src/avr/up_sigdeliver.c @@ -72,7 +72,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint8_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably EINTR). @@ -90,14 +89,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -106,9 +97,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -117,7 +108,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -129,12 +120,13 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC0] = rtcb->xcp.saved_pc0; - regs[REG_PC1] = rtcb->xcp.saved_pc1; + regs[REG_PC0] = rtcb->xcp.saved_pc0; + regs[REG_PC1] = rtcb->xcp.saved_pc1; #if defined(REG_PC2) - regs[REG_PC2] = rtcb->xcp.saved_pc2; + regs[REG_PC2] = rtcb->xcp.saved_pc2; #endif - regs[REG_SREG] = rtcb->xcp.saved_sreg; + regs[REG_SREG] = rtcb->xcp.saved_sreg; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is diff --git a/arch/avr/src/avr32/up_sigdeliver.c b/arch/avr/src/avr32/up_sigdeliver.c index 2b175c77d0..52a017a1ee 100644 --- a/arch/avr/src/avr32/up_sigdeliver.c +++ b/arch/avr/src/avr32/up_sigdeliver.c @@ -76,7 +76,6 @@ void up_sigdeliver(void) #else uint32_t regs[XCPTCONTEXT_REGS]; #endif - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably EINTR). @@ -94,14 +93,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -110,9 +101,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -121,7 +112,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -133,8 +124,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_SR] = rtcb->xcp.saved_sr; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_SR] = rtcb->xcp.saved_sr; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is diff --git a/arch/mips/src/mips32/up_sigdeliver.c b/arch/mips/src/mips32/up_sigdeliver.c index 3f0f3c9be1..dd9c6297d9 100644 --- a/arch/mips/src/mips32/up_sigdeliver.c +++ b/arch/mips/src/mips32/up_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -92,14 +91,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -108,9 +99,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -120,7 +111,7 @@ void up_sigdeliver(void) sinfo("Resuming EPC: %08x STATUS: %08x\n", regs[REG_EPC], regs[REG_STATUS]); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -132,8 +123,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EPC] = rtcb->xcp.saved_epc; - regs[REG_STATUS] = rtcb->xcp.saved_status; + regs[REG_EPC] = rtcb->xcp.saved_epc; + regs[REG_STATUS] = rtcb->xcp.saved_status; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/misoc/src/lm32/lm32_sigdeliver.c b/arch/misoc/src/lm32/lm32_sigdeliver.c index 276c46741f..f1925624c5 100644 --- a/arch/misoc/src/lm32/lm32_sigdeliver.c +++ b/arch/misoc/src/lm32/lm32_sigdeliver.c @@ -72,7 +72,6 @@ void lm32_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -91,14 +90,6 @@ void lm32_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -107,9 +98,9 @@ void lm32_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -119,7 +110,7 @@ void lm32_sigdeliver(void) sinfo("Resuming EPC: %08x INT_CTX: %08x\n", regs[REG_EPC], regs[REG_INT_CTX]); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -131,8 +122,9 @@ void lm32_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EPC] = rtcb->xcp.saved_epc; - regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; + regs[REG_EPC] = rtcb->xcp.saved_epc; + regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/renesas/src/m16c/m16c_sigdeliver.c b/arch/renesas/src/m16c/m16c_sigdeliver.c index 390d6dec9b..512aebca35 100644 --- a/arch/renesas/src/m16c/m16c_sigdeliver.c +++ b/arch/renesas/src/m16c/m16c_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS struct tcb_s *rtcb = this_task(); uint8_t regs[XCPTCONTEXT_SIZE]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -92,15 +91,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -109,9 +99,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)sig_rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -120,7 +110,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -132,9 +122,10 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc[0]; - regs[REG_PC+1] = rtcb->xcp.saved_pc[1]; - regs[REG_FLG] = rtcb->xcp.saved_flg; + regs[REG_PC] = rtcb->xcp.saved_pc[0]; + regs[REG_PC + 1] = rtcb->xcp.saved_pc[1]; + regs[REG_FLG] = rtcb->xcp.saved_flg; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/renesas/src/sh1/sh1_sigdeliver.c b/arch/renesas/src/sh1/sh1_sigdeliver.c index 25b6e5bcd1..aac0cf92bb 100644 --- a/arch/renesas/src/sh1/sh1_sigdeliver.c +++ b/arch/renesas/src/sh1/sh1_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -92,15 +91,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -109,9 +99,9 @@ void up_sigdeliver(void) up_irq_enable(); #endif - /* Deliver the signals */ + /* Deliver the signal */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -120,7 +110,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -132,8 +122,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_SR] = rtcb->xcp.saved_sr; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_SR] = rtcb->xcp.saved_sr; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/risc-v/src/rv32im/up_sigdeliver.c b/arch/risc-v/src/rv32im/up_sigdeliver.c index 7819e06e00..616148bc94 100644 --- a/arch/risc-v/src/rv32im/up_sigdeliver.c +++ b/arch/risc-v/src/rv32im/up_sigdeliver.c @@ -78,7 +78,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -97,14 +96,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -115,7 +106,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -125,7 +116,7 @@ void up_sigdeliver(void) sinfo("Resuming EPC: %08x INT_CTX: %08x\n", regs[REG_EPC], regs[REG_INT_CTX]); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -137,8 +128,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EPC] = rtcb->xcp.saved_epc; - regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; + regs[REG_EPC] = rtcb->xcp.saved_epc; + regs[REG_INT_CTX] = rtcb->xcp.saved_int_ctx; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of * execution. diff --git a/arch/x86/src/i486/up_sigdeliver.c b/arch/x86/src/i486/up_sigdeliver.c index 0609996515..0f6164565a 100644 --- a/arch/x86/src/i486/up_sigdeliver.c +++ b/arch/x86/src/i486/up_sigdeliver.c @@ -72,7 +72,6 @@ void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -91,14 +90,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. we do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -109,7 +100,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -118,7 +109,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -130,8 +121,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[REG_EIP] = rtcb->xcp.saved_eip; - regs[REG_EFLAGS] = rtcb->xcp.saved_eflags; + regs[REG_EIP] = rtcb->xcp.saved_eip; + regs[REG_EFLAGS] = rtcb->xcp.saved_eflags; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/xtensa/src/common/xtensa_sigdeliver.c b/arch/xtensa/src/common/xtensa_sigdeliver.c index a61a68a7ed..197d5d90ad 100644 --- a/arch/xtensa/src/common/xtensa_sigdeliver.c +++ b/arch/xtensa/src/common/xtensa_sigdeliver.c @@ -69,9 +69,8 @@ void xtensa_sig_deliver(void) { - struct tcb_s *rtcb = this_task(); + struct tcb_s *rtcb = this_task(); uint32_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -99,14 +98,6 @@ void xtensa_sig_deliver(void) xtensa_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. we do this so that - * we can nullify the sigdeliver function pointer in the TCB and accept - * more signal deliveries while processing the current pending signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifdef CONFIG_SMP /* In the SMP case, up_schedule_sigaction(0) will have incremented * 'irqcount' in order to force us into a critical section. Save the @@ -137,7 +128,7 @@ void xtensa_sig_deliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -149,7 +140,7 @@ void xtensa_sig_deliver(void) /* Restore the saved errno value */ - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -161,8 +152,9 @@ void xtensa_sig_deliver(void) * could be modified by a hostile program. */ - regs[REG_PC] = rtcb->xcp.saved_pc; - regs[REG_PS] = rtcb->xcp.saved_ps; + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_PS] = rtcb->xcp.saved_ps; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ #ifdef CONFIG_SMP /* Restore the saved 'irqcount' and recover the critical section diff --git a/arch/z16/src/common/up_sigdeliver.c b/arch/z16/src/common/up_sigdeliver.c index 44fb6f7a2b..a7c874cb0e 100644 --- a/arch/z16/src/common/up_sigdeliver.c +++ b/arch/z16/src/common/up_sigdeliver.c @@ -74,7 +74,6 @@ void up_sigdeliver(void) FAR struct tcb_s *rtcb = this_task(); chipreg_t regs[XCPTCONTEXT_REGS]; FAR uint32_t *regs32 = (FAR uint32_t*)regs; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -93,15 +92,6 @@ void up_sigdeliver(void) up_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function point in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = (sig_deliver_t)rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -112,7 +102,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -121,7 +111,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -133,8 +123,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs32[REG_PC / 2] = rtcb->xcp.saved_pc; - regs[REG_FLAGS] = rtcb->xcp.saved_i; + regs32[REG_PC / 2] = rtcb->xcp.saved_pc; + regs[REG_FLAGS] = rtcb->xcp.saved_i; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/src/ez80/ez80_sigdeliver.c b/arch/z80/src/ez80/ez80_sigdeliver.c index 29e91d7cd8..229d8604b9 100644 --- a/arch/z80/src/ez80/ez80_sigdeliver.c +++ b/arch/z80/src/ez80/ez80_sigdeliver.c @@ -73,7 +73,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS FAR struct tcb_s *rtcb = this_task(); chipreg_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -92,15 +91,6 @@ void up_sigdeliver(void) ez80_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -111,7 +101,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -120,10 +110,21 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; + /* Modify the saved return state with the actual saved values in the + * TCB. This depends on the fact that nested signal handling is + * not supported. Therefore, these values will persist throughout the + * signal handling action. + * + * Keeping this data in the TCB resolves a security problem in protected + * and kernel mode: The regs[] array is visible on the user stack and + * could be modified by a hostile program. + */ + + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is diff --git a/arch/z80/src/z180/z180_sigdeliver.c b/arch/z80/src/z180/z180_sigdeliver.c index f532a62688..f0e9319ff2 100644 --- a/arch/z80/src/z180/z180_sigdeliver.c +++ b/arch/z80/src/z180/z180_sigdeliver.c @@ -71,7 +71,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS FAR struct tcb_s *rtcb = this_task(); chipreg_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -90,15 +89,6 @@ void up_sigdeliver(void) z180_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -109,7 +99,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -118,7 +108,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -130,8 +120,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/src/z8/z8_sigdeliver.c b/arch/z80/src/z8/z8_sigdeliver.c index d55c874d63..3f80b8d245 100644 --- a/arch/z80/src/z8/z8_sigdeliver.c +++ b/arch/z80/src/z8/z8_sigdeliver.c @@ -91,7 +91,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS FAR struct tcb_s *rtcb = this_task(); chipreg_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -110,15 +109,6 @@ void up_sigdeliver(void) z8_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -129,7 +119,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -138,7 +128,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -150,8 +140,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_IRQCTL] = rtcb->xcp.saved_irqctl; + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_IRQCTL] = rtcb->xcp.saved_irqctl; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */ diff --git a/arch/z80/src/z80/z80_sigdeliver.c b/arch/z80/src/z80/z80_sigdeliver.c index 815851634d..3089ac423f 100644 --- a/arch/z80/src/z80/z80_sigdeliver.c +++ b/arch/z80/src/z80/z80_sigdeliver.c @@ -72,7 +72,6 @@ void up_sigdeliver(void) #ifndef CONFIG_DISABLE_SIGNALS FAR struct tcb_s *rtcb = this_task(); chipreg_t regs[XCPTCONTEXT_REGS]; - sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably @@ -91,15 +90,6 @@ void up_sigdeliver(void) z80_copystate(regs, rtcb->xcp.regs); - /* Get a local copy of the sigdeliver function pointer. We do this so - * that we can nullify the sigdeliver function pointer in the TCB and - * accept more signal deliveries while processing the current pending - * signals. - */ - - sigdeliver = rtcb->xcp.sigdeliver; - rtcb->xcp.sigdeliver = NULL; - #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. @@ -110,7 +100,7 @@ void up_sigdeliver(void) /* Deliver the signals */ - sigdeliver(rtcb); + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original @@ -119,7 +109,7 @@ void up_sigdeliver(void) sinfo("Resuming\n"); (void)up_irq_save(); - rtcb->pterrno = saved_errno; + rtcb->pterrno = saved_errno; /* Modify the saved return state with the actual saved values in the * TCB. This depends on the fact that nested signal handling is @@ -131,8 +121,9 @@ void up_sigdeliver(void) * could be modified by a hostile program. */ - regs[XCPT_PC] = rtcb->xcp.saved_pc; - regs[XCPT_I] = rtcb->xcp.saved_i; + regs[XCPT_PC] = rtcb->xcp.saved_pc; + regs[XCPT_I] = rtcb->xcp.saved_i; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ /* Then restore the correct state for this thread of execution. */