Commit fb05121f authored by Christophe Leroy's avatar Christophe Leroy Committed by Michael Ellerman

signal: Add unsafe_get_compat_sigset()

In the same way as commit 14026b94 ("signal: Add
unsafe_put_compat_sigset()"), this time add
unsafe_get_compat_sigset() macro which is the 'unsafe'
version of get_compat_sigset()

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

For the littleendian, use a straight unsafe_copy_from_user().

This commit adds the generic fallback for unsafe_copy_from_user().
Architectures wanting to use unsafe_get_compat_sigset() have to
make sure they have their own unsafe_copy_from_user().
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/b05bf434ee13c76bc9df5f02653a10db5e7b54e5.1616151715.git.christophe.leroy@csgroup.eu
parent 5cd29b1f
...@@ -465,6 +465,34 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, ...@@ -465,6 +465,34 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set,
unsafe_put_user(__s->sig[0], &__c->sig[0], label); \ unsafe_put_user(__s->sig[0], &__c->sig[0], label); \
} \ } \
} while (0) } while (0)
#define unsafe_get_compat_sigset(set, compat, label) do { \
const compat_sigset_t __user *__c = compat; \
compat_sigset_word hi, lo; \
sigset_t *__s = set; \
\
switch (_NSIG_WORDS) { \
case 4: \
unsafe_get_user(lo, &__c->sig[7], label); \
unsafe_get_user(hi, &__c->sig[6], label); \
__s->sig[3] = hi | (((long)lo) << 32); \
fallthrough; \
case 3: \
unsafe_get_user(lo, &__c->sig[5], label); \
unsafe_get_user(hi, &__c->sig[4], label); \
__s->sig[2] = hi | (((long)lo) << 32); \
fallthrough; \
case 2: \
unsafe_get_user(lo, &__c->sig[3], label); \
unsafe_get_user(hi, &__c->sig[2], label); \
__s->sig[1] = hi | (((long)lo) << 32); \
fallthrough; \
case 1: \
unsafe_get_user(lo, &__c->sig[1], label); \
unsafe_get_user(hi, &__c->sig[0], label); \
__s->sig[0] = hi | (((long)lo) << 32); \
} \
} while (0)
#else #else
#define unsafe_put_compat_sigset(compat, set, label) do { \ #define unsafe_put_compat_sigset(compat, set, label) do { \
compat_sigset_t __user *__c = compat; \ compat_sigset_t __user *__c = compat; \
...@@ -472,6 +500,13 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, ...@@ -472,6 +500,13 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set,
\ \
unsafe_copy_to_user(__c, __s, sizeof(*__c), label); \ unsafe_copy_to_user(__c, __s, sizeof(*__c), label); \
} while (0) } while (0)
#define unsafe_get_compat_sigset(set, compat, label) do { \
const compat_sigset_t __user *__c = compat; \
sigset_t *__s = set; \
\
unsafe_copy_from_user(__s, __c, sizeof(*__c), label); \
} while (0)
#endif #endif
extern int compat_ptrace_request(struct task_struct *child, extern int compat_ptrace_request(struct task_struct *child,
......
...@@ -397,6 +397,7 @@ long strnlen_user_nofault(const void __user *unsafe_addr, long count); ...@@ -397,6 +397,7 @@ long strnlen_user_nofault(const void __user *unsafe_addr, long count);
#define unsafe_get_user(x,p,e) unsafe_op_wrap(__get_user(x,p),e) #define unsafe_get_user(x,p,e) unsafe_op_wrap(__get_user(x,p),e)
#define unsafe_put_user(x,p,e) unsafe_op_wrap(__put_user(x,p),e) #define unsafe_put_user(x,p,e) unsafe_op_wrap(__put_user(x,p),e)
#define unsafe_copy_to_user(d,s,l,e) unsafe_op_wrap(__copy_to_user(d,s,l),e) #define unsafe_copy_to_user(d,s,l,e) unsafe_op_wrap(__copy_to_user(d,s,l),e)
#define unsafe_copy_from_user(d,s,l,e) unsafe_op_wrap(__copy_from_user(d,s,l),e)
static inline unsigned long user_access_save(void) { return 0UL; } static inline unsigned long user_access_save(void) { return 0UL; }
static inline void user_access_restore(unsigned long flags) { } static inline void user_access_restore(unsigned long flags) { }
#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