|
17 | 17 | #include <linux/if.h>
|
18 | 18 | #include <linux/fs.h>
|
19 | 19 | #include <linux/aio_abi.h> /* for aio_context_t */
|
| 20 | +#include <linux/uaccess.h> |
20 | 21 | #include <linux/unistd.h>
|
21 | 22 |
|
22 | 23 | #include <asm/compat.h>
|
@@ -550,8 +551,29 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
|
550 | 551 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
|
551 | 552 |
|
552 | 553 | extern int get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat);
|
553 |
| -extern int put_compat_sigset(compat_sigset_t __user *compat, |
554 |
| - const sigset_t *set, unsigned int size); |
| 554 | + |
| 555 | +/* |
| 556 | + * Defined inline such that size can be compile time constant, which avoids |
| 557 | + * CONFIG_HARDENED_USERCOPY complaining about copies from task_struct |
| 558 | + */ |
| 559 | +static inline int |
| 560 | +put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, |
| 561 | + unsigned int size) |
| 562 | +{ |
| 563 | + /* size <= sizeof(compat_sigset_t) <= sizeof(sigset_t) */ |
| 564 | +#ifdef __BIG_ENDIAN |
| 565 | + compat_sigset_t v; |
| 566 | + switch (_NSIG_WORDS) { |
| 567 | + case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3]; |
| 568 | + case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2]; |
| 569 | + case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1]; |
| 570 | + case 1: v.sig[1] = (set->sig[0] >> 32); v.sig[0] = set->sig[0]; |
| 571 | + } |
| 572 | + return copy_to_user(compat, &v, size) ? -EFAULT : 0; |
| 573 | +#else |
| 574 | + return copy_to_user(compat, set, size) ? -EFAULT : 0; |
| 575 | +#endif |
| 576 | +} |
555 | 577 |
|
556 | 578 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,
|
557 | 579 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes,
|
|
0 commit comments