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: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/9273ba664db769b8d9c7540ae91395e346e4945e.1616151715.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
627b72bee8
commit
887f3ceb51
@ -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 @@
|
|||||||
* 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 @@ failed:
|
|||||||
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
|
|||||||
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,
|
|||||||
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,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
user_read_access_end();
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user