diff --git a/TODO b/TODO index c397e69e0fe..90900648f7e 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 6406536c30e..afc843b1e1a 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 1af19185c20..1688019729a 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 5f07737110b..e1f500b1e98 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 b6b3c18240c..e79f569d3d0 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 8e3e7a3940d..6f560d14ff4 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 30bfa8b8e62..39cdfa5cb03 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 2b175c77d08..52a017a1ee3 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 3f0f3c9be15..dd9c6297d9e 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 276c46741f6..f1925624c56 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 390d6dec9b7..512aebca354 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 25b6e5bcd12..aac0cf92bbb 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 7819e06e004..616148bc948 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 06099965151..0f6164565a9 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 a61a68a7ed0..197d5d90ade 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 44fb6f7a2bb..a7c874cb0ef 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 29e91d7cd86..229d8604b92 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 f532a626880..f0e9319ff2a 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 d55c874d63e..3f80b8d2456 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 815851634dc..3089ac423fc 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. */