Commit 887f3ceb authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

powerpc/signal32: Convert do_setcontext[_tm]() to user access block

Add unsafe_get_user_sigset() and transform PPC32 get_sigset_t()
into an unsafe version unsafe_get_sigset_t().

Then convert do_setcontext() and do_setcontext_tm() to use
user_read_access_begin/end.
Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/9273ba664db769b8d9c7540ae91395e346e4945e.1616151715.git.christophe.leroy@csgroup.eu
parent 627b72be
...@@ -25,6 +25,8 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src) ...@@ -25,6 +25,8 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src)
return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]); return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]);
} }
#define unsafe_get_user_sigset(dst, src, label) \
unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label)
#ifdef CONFIG_VSX #ifdef CONFIG_VSX
extern unsigned long copy_vsx_to_user(void __user *to, extern unsigned long copy_vsx_to_user(void __user *to,
......
...@@ -83,12 +83,7 @@ ...@@ -83,12 +83,7 @@
* implementation that makes things simple for little endian only) * implementation that makes things simple for little endian only)
*/ */
#define unsafe_put_sigset_t unsafe_put_compat_sigset #define unsafe_put_sigset_t unsafe_put_compat_sigset
#define unsafe_get_sigset_t unsafe_get_compat_sigset
static inline int get_sigset_t(sigset_t *set,
const compat_sigset_t __user *uset)
{
return get_compat_sigset(set, uset);
}
#define to_user_ptr(p) ptr_to_compat(p) #define to_user_ptr(p) ptr_to_compat(p)
#define from_user_ptr(p) compat_ptr(p) #define from_user_ptr(p) compat_ptr(p)
...@@ -144,10 +139,7 @@ __unsafe_restore_general_regs(struct pt_regs *regs, struct mcontext __user *sr) ...@@ -144,10 +139,7 @@ __unsafe_restore_general_regs(struct pt_regs *regs, struct mcontext __user *sr)
unsafe_copy_to_user(__us, __s, sizeof(*__us), label); \ unsafe_copy_to_user(__us, __s, sizeof(*__us), label); \
} while (0) } while (0)
static inline int get_sigset_t(sigset_t *set, const sigset_t __user *uset) #define unsafe_get_sigset_t unsafe_get_user_sigset
{
return __get_user_sigset(set, uset);
}
#define to_user_ptr(p) ((unsigned long)(p)) #define to_user_ptr(p) ((unsigned long)(p))
#define from_user_ptr(p) ((void __user *)(p)) #define from_user_ptr(p) ((void __user *)(p))
...@@ -982,25 +974,31 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int ...@@ -982,25 +974,31 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
sigset_t set; sigset_t set;
struct mcontext __user *mcp; struct mcontext __user *mcp;
if (get_sigset_t(&set, &ucp->uc_sigmask)) if (user_read_access_begin(ucp, sizeof(*ucp)))
return -EFAULT; return -EFAULT;
unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
{ {
u32 cmcp; u32 cmcp;
if (__get_user(cmcp, &ucp->uc_regs)) unsafe_get_user(cmcp, &ucp->uc_regs, failed);
return -EFAULT;
mcp = (struct mcontext __user *)(u64)cmcp; mcp = (struct mcontext __user *)(u64)cmcp;
} }
#else #else
if (__get_user(mcp, &ucp->uc_regs)) unsafe_get_user(mcp, &ucp->uc_regs, failed);
return -EFAULT;
#endif #endif
user_read_access_end();
set_current_blocked(&set); set_current_blocked(&set);
if (restore_user_regs(regs, mcp, sig)) if (restore_user_regs(regs, mcp, sig))
return -EFAULT; return -EFAULT;
return 0; return 0;
failed:
user_read_access_end();
return -EFAULT;
} }
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
...@@ -1014,11 +1012,15 @@ static int do_setcontext_tm(struct ucontext __user *ucp, ...@@ -1014,11 +1012,15 @@ static int do_setcontext_tm(struct ucontext __user *ucp,
u32 cmcp; u32 cmcp;
u32 tm_cmcp; u32 tm_cmcp;
if (get_sigset_t(&set, &ucp->uc_sigmask)) if (user_read_access_begin(ucp, sizeof(*ucp)))
return -EFAULT; return -EFAULT;
if (__get_user(cmcp, &ucp->uc_regs) || unsafe_get_sigset_t(&set, &ucp->uc_sigmask, failed);
__get_user(tm_cmcp, &tm_ucp->uc_regs)) unsafe_get_user(cmcp, &ucp->uc_regs, failed);
user_read_access_end();
if (__get_user(tm_cmcp, &tm_ucp->uc_regs))
return -EFAULT; return -EFAULT;
mcp = (struct mcontext __user *)(u64)cmcp; mcp = (struct mcontext __user *)(u64)cmcp;
tm_mcp = (struct mcontext __user *)(u64)tm_cmcp; tm_mcp = (struct mcontext __user *)(u64)tm_cmcp;
...@@ -1029,6 +1031,10 @@ static int do_setcontext_tm(struct ucontext __user *ucp, ...@@ -1029,6 +1031,10 @@ static int do_setcontext_tm(struct ucontext __user *ucp,
return -EFAULT; return -EFAULT;
return 0; return 0;
failed:
user_read_access_end();
return -EFAULT;
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment