Commit de781ebd authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman
Browse files

powerpc/signal32: Add and use unsafe_put_sigset_t()



put_sigset_t() calls copy_to_user() for copying two words.

This is terribly inefficient for copying two words.

By switching to unsafe_put_user(), we end up with something as
simple as:

 3cc:   81 3d 00 00     lwz     r9,0(r29)
 3d0:   91 26 00 b4     stw     r9,180(r6)
 3d4:   81 3d 00 04     lwz     r9,4(r29)
 3d8:   91 26 00 b8     stw     r9,184(r6)

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/06def97e87ac1c4ae8e3197e0982e1fab7b3c8ae.1597770847.git.christophe.leroy@csgroup.eu
parent 14026b94
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
	return put_compat_sigset(uset, set, sizeof(*uset));
}

#define unsafe_put_sigset_t	unsafe_put_compat_sigset

static inline int get_sigset_t(sigset_t *set,
			       const compat_sigset_t __user *uset)
{
@@ -141,6 +143,13 @@ static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set)
	return copy_to_user(uset, set, sizeof(*uset));
}

#define unsafe_put_sigset_t(uset, set, label) do {			\
	sigset_t __user *__us = uset	;				\
	const sigset_t *__s = set;					\
									\
	unsafe_copy_to_user(__us, __s, sizeof(*__us), label);		\
} while (0)

static inline int get_sigset_t(sigset_t *set, const sigset_t __user *uset)
{
	return copy_from_user(set, uset, sizeof(*uset));
@@ -780,10 +789,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
				failed);
		unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed);
	}
	unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed);

	user_write_access_end();

	if (put_sigset_t(&frame->uc.uc_sigmask, oldset))
		goto badframe;
	if (copy_siginfo_to_user(&frame->info, &ksig->info))
		goto badframe;