signal: Add unsafe_put_compat_sigset()

Implement 'unsafe' version of put_compat_sigset()

For the bigendian, use unsafe_put_user() directly
to avoid intermediate copy through the stack.

For the littleendian, use a straight unsafe_copy_to_user().

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/537c7082ee309a0bb9c67a50c5d9dd929aedb82d.1597770847.git.christophe.leroy@csgroup.eu
This commit is contained in:
Christophe Leroy 2020-08-18 17:19:32 +00:00 committed by Michael Ellerman
parent f1cf4f93de
commit 14026b94cc

View File

@ -442,6 +442,38 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set,
#endif
}
#ifdef CONFIG_CPU_BIG_ENDIAN
#define unsafe_put_compat_sigset(compat, set, label) do { \
compat_sigset_t __user *__c = compat; \
const sigset_t *__s = set; \
\
switch (_NSIG_WORDS) { \
case 4: \
unsafe_put_user(__s->sig[3] >> 32, &__c->sig[7], label); \
unsafe_put_user(__s->sig[3], &__c->sig[6], label); \
fallthrough; \
case 3: \
unsafe_put_user(__s->sig[2] >> 32, &__c->sig[5], label); \
unsafe_put_user(__s->sig[2], &__c->sig[4], label); \
fallthrough; \
case 2: \
unsafe_put_user(__s->sig[1] >> 32, &__c->sig[3], label); \
unsafe_put_user(__s->sig[1], &__c->sig[2], label); \
fallthrough; \
case 1: \
unsafe_put_user(__s->sig[0] >> 32, &__c->sig[1], label); \
unsafe_put_user(__s->sig[0], &__c->sig[0], label); \
} \
} while (0)
#else
#define unsafe_put_compat_sigset(compat, set, label) do { \
compat_sigset_t __user *__c = compat; \
const sigset_t *__s = set; \
\
unsafe_copy_to_user(__c, __s, sizeof(*__c), label); \
} while (0)
#endif
extern int compat_ptrace_request(struct task_struct *child,
compat_long_t request,
compat_ulong_t addr, compat_ulong_t data);