Fix msr check in compat_sys_swapcontext
PATCH 1/1 Fix msr check in compat_sys_swapcontext
The new context may not be 16-byte aligned, so the real address of the mcontext structure should be read from the uc_regs pointer instead of directly using the (unaligned) uc_mcontext field.
---
arch/powerpc/kernel/signal_32.c +11 -3
@@ -941,9 +941,17 @@ long sys_swapcontext(struct ucontext __user *old_ctx,#ifdef CONFIG_PPC64 unsigned long new_msr =0 ; -if (new_ctx && -get_user (new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR ])) -return -EFAULT ; +if (new_ctx) { +struct mcontext __user *mcp; +u32 cmcp; + +/* Get pointer to the real mcontext. */ +if (__get_user (cmcp, &new_ctx->uc_regs)) +return -EFAULT ; + mcp = (struct mcontext __user *)(u64 )cmcp; +if (__get_user (new_msr, &mcp->mc_gregs[PT_MSR ])) +return -EFAULT ; + }/* * Check that the context is not smaller than the original * size (with VMX but without VSX)
Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
Quoted 3 lines · Andreas Schwab
The new context may not be 16-byte aligned, so the real address of the mcontext structure should be read from the
uc_regspointer instead of directly using the (unaligned)uc_mcontextfield.
Good catch, but...
arch/powerpc/kernel/signal_32.c long sys_swapcontext(struct ucontext __user *old_ctx, · line 949
Quoted 13 lines
arch/powerpc/kernel/signal_32.c +6
-3@@ -941,9 +941,17 @@ long sys_swapcontext(struct ucontext __user *old_ctx,#ifdef CONFIG_PPC64 unsigned long new_msr =0 ; -if (new_ctx && -get_user (new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR ])) -return -EFAULT ; +if (new_ctx) { +struct mcontext __user *mcp; +u32 cmcp; + +/* Get pointer to the real mcontext. */ +if (__get_user (cmcp, &new_ctx->uc_regs))
we need to use get_user, not __get_user, since we haven't done an access_ok() check on the address.
arch/powerpc/kernel/signal_32.c long sys_swapcontext(struct ucontext __user *old_ctx, · line 952
Quoted 3 lines
arch/powerpc/kernel/signal_32.c +3
-0+return -EFAULT ; + mcp = (struct mcontext __user *)(u64 )cmcp; +if (__get_user (new_msr, &mcp->mc_gregs[PT_MSR ]))
ditto here.
Paul.
Quoted 2 lines · Paul Mackerras
we need to use
get_user, not__get_user, since we haven't done anaccess_ok()check on the address.
The address is always ok since its a compat pointer, see do_setcontext.
Andreas.
Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
Quoted 6 lines · Andreas Schwab
Quoted 2 lines · Paul Mackerras
we need to use
get_user, not__get_user, since we haven't done anaccess_ok()check on the address.The address is always ok since its a compat pointer, see
do_setcontext.
OK, since it's inside a CONFIG_PPC64 block. I'll add a paragraph to the patch description pointing that out.
Paul.
Quoted 11 lines · Paul Mackerras
Quoted 6 lines · Andreas Schwab
Quoted 2 lines · Paul Mackerras
we need to use
get_user, not__get_user, since we haven't done anaccess_ok()check on the address.The address is always ok since its a compat pointer, see
do_setcontext.OK, since it's inside a
CONFIG_PPC64block. I'll add a paragraph to the patch description pointing that out.
How about this:
arch/powerpc/kernel/signal_32.c +15 -3
@@ -941,9 +941,21 @@ long sys_swapcontext(struct ucontext __user *old_ctx,#ifdef CONFIG_PPC64 unsigned long new_msr =0 ; -if (new_ctx && -get_user (new_msr, &new_ctx->uc_mcontext.mc_gregs[PT_MSR ])) -return -EFAULT ; +if (new_ctx) { +struct mcontext __user *mcp; +u32 cmcp; + +/* +* Get pointer to the real mcontext. No need for +* access_ok since we are dealing with compat +* pointers. +*/ +if (__get_user (cmcp, &new_ctx->uc_regs)) +return -EFAULT ; + mcp = (struct mcontext __user *)(u64 )cmcp; +if (__get_user (new_msr, &mcp->mc_gregs[PT_MSR ])) +return -EFAULT ; + }/* * Check that the context is not smaller than the original * size (with VMX but without VSX)
Andreas.
Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."