- Notifications
You must be signed in to change notification settings - Fork 8.2k
arch: arm: switch to privilege stack in SVC handler #95101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
arch: arm: switch to privilege stack in SVC handler #95101
Conversation
Introduce a test to overwrite the return address in the exception stack frame of a lower-priority thread performing an SVC call. Signed-off-by: Sudan Landge <sudan.landge@arm.com>
8a235e3 to db4c1d7 Compare | Hi @andyross could you please help with the review of this PR? |
ceolin left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks right to me.
| Hi @andyross, @bbolen, @carlocaione, @galak, @MaureenHelm, @microbuilder, @stephanosio |
| Also, requesting @mathieuchopstm for a review since he has been involved with Arm assembly reviews for a while |
mathieuchopstm left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll give it a second pass tomorrow. Overall seems OK but I may have missed some details (haven't looked at z_arm_do_syscall either so some things still seem a bit weird to me)
`west build` does not build the `empty_cpu0` application making `west build -b mps2/an521/cpu1 -t run` fail because of the missing empty_cpu0's binary. Signed-off-by: Sudan Landge <sudan.landge@arm.com>
db4c1d7 to 3b71022 Compare a933d24 to 86c8de7 Compare | Hi @mathieuchopstm could you please have another look at this? |
mathieuchopstm left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments apply to the ARMv7/8-Mainline as well but I did not write them twice.
Additionally, ~L305 of userspace.S says:
* This function is used to do system calls from unprivileged code. This * function is responsible for the following: * 1) Fixing up bad syscalls * 2) Configuring privileged stack and loading up stack arguments * 3) Dispatching the system call * 4) Restoring stack and calling back to the caller of the SVCThis should be updated to remove (2) since it's now done in SVC handler.
The comment right under also says
* Note [when using built-in stack limit checking on ARMv8-M]: * At this point PSPLIM is already configured to guard the default (user) * stack, so pushing to the default thread's stack is safe. That also needs to be updated.
Initialize the privilege stack and switch PSP to it early in the SVC handler to ensure `z_arm_do_syscall` does not start on a user-accessible stack frame. Signed-off-by: Sudan Landge <sudan.landge@arm.com>
86c8de7 to df57f95 Compare |
| @mathieuchopstm I have tried to update the table with more comments, let me know if it looks good. |
mathieuchopstm left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor non-blockers. LGTM otherwise
| * located at *lower* memory area. Since we switch to the top of the | ||
| * privileged stack we are safe, as long as the stack can accommodate | ||
| * the maximum exception stack frame. | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this whole comment can be removed too since we pivot PSPLIM while in Handler mode?
| */ |
| beq .L_no_padding | ||
| /* special handling for padded sf */ | ||
| bics r1, r3 /* clear the pad bit (priv stack is aligned and doesn't need it) */ | ||
| adds r2, #4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd really comment this here, it's not obvious that this is the +4B comment right below talks about
| adds r2, #4 | |
| adds r2, #4 /* add +4B to compensate padding (see below) */ |
| /* Calculate original pre-svc user sp with pad */ | ||
| add r2, #4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Single line would be sufficient + reword proposal:
| /* Calculate original pre-svc user sp with pad */ | |
| add r2, #4 | |
| add r2, #4 /* take pad into account for pre-svc user sp computation */ |
| { | ||
| printf("Call %s from %s\n", __func__, k_is_user_context() ? "user" : "kernel"); | ||
| while (1) { | ||
| attack_sp[-2] = (int)attack_entry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain why the index is -2 instead of -3, -1 or 0?
I meet an issue related this, thanks!
The following patch cause this test fail but I have no idea about this issue.
diff --git a/kernel/sched.c b/kernel/sched.c index 37fdbf3bf0b..b119381ef83 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -77,6 +77,7 @@ static ALWAYS_INLINE void *curr_cpu_runq(void) static ALWAYS_INLINE void runq_add(struct k_thread *thread) { __ASSERT_NO_MSG(!z_is_idle_thread_object(thread)); + __ASSERT_NO_MSG(!is_thread_dummy(thread)); _priq_run_add(thread_runq(thread), thread); } There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attack_sp is the value of sp upon execution of the svc instruction. The hardware then saves processor context on this stack as follows:

Notice that ReturnAddress - the address at which execution should resume upon return from exception - is at offset sp - 0x20 + 0x18 = sp - 8, a.k.a. attack_sp[-2] since attack_sp is a uint32_t* here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attack_spis the value ofspupon execution of thesvcinstruction. The hardware then saves processor context on this stack as follows:Notice that
ReturnAddress- the address at which execution should resume upon return from exception - is at offsetsp - 0x20 + 0x18=sp - 8, a.k.a.attack_sp[-2]sinceattack_spis auint32_t*here
Got it, thanks for your detailed explanation.




Initialize the privilege stack and switch PSP to it early in the SVC handler to ensure
z_arm_do_syscalldoes not start on a user-accessible stack frame. Also add a test to validate this behavior.