diff options
Diffstat (limited to 'kernel/compat.c')
| -rw-r--r-- | kernel/compat.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 126dee9530aa..b4fbd838cd77 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -22,9 +22,12 @@ | |||
| 22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
| 23 | #include <linux/timex.h> | 23 | #include <linux/timex.h> |
| 24 | #include <linux/migrate.h> | 24 | #include <linux/migrate.h> |
| 25 | #include <linux/posix-timers.h> | ||
| 25 | 26 | ||
| 26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 27 | 28 | ||
| 29 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | ||
| 30 | |||
| 28 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) | 31 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) |
| 29 | { | 32 | { |
| 30 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || | 33 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || |
| @@ -601,6 +604,30 @@ long compat_sys_clock_getres(clockid_t which_clock, | |||
| 601 | return err; | 604 | return err; |
| 602 | } | 605 | } |
| 603 | 606 | ||
| 607 | static long compat_clock_nanosleep_restart(struct restart_block *restart) | ||
| 608 | { | ||
| 609 | long err; | ||
| 610 | mm_segment_t oldfs; | ||
| 611 | struct timespec tu; | ||
| 612 | struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1); | ||
| 613 | |||
| 614 | restart->arg1 = (unsigned long) &tu; | ||
| 615 | oldfs = get_fs(); | ||
| 616 | set_fs(KERNEL_DS); | ||
| 617 | err = clock_nanosleep_restart(restart); | ||
| 618 | set_fs(oldfs); | ||
| 619 | |||
| 620 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | ||
| 621 | put_compat_timespec(&tu, rmtp)) | ||
| 622 | return -EFAULT; | ||
| 623 | |||
| 624 | if (err == -ERESTART_RESTARTBLOCK) { | ||
| 625 | restart->fn = compat_clock_nanosleep_restart; | ||
| 626 | restart->arg1 = (unsigned long) rmtp; | ||
| 627 | } | ||
| 628 | return err; | ||
| 629 | } | ||
| 630 | |||
| 604 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | 631 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, |
| 605 | struct compat_timespec __user *rqtp, | 632 | struct compat_timespec __user *rqtp, |
| 606 | struct compat_timespec __user *rmtp) | 633 | struct compat_timespec __user *rmtp) |
| @@ -608,6 +635,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | |||
| 608 | long err; | 635 | long err; |
| 609 | mm_segment_t oldfs; | 636 | mm_segment_t oldfs; |
| 610 | struct timespec in, out; | 637 | struct timespec in, out; |
| 638 | struct restart_block *restart; | ||
| 611 | 639 | ||
| 612 | if (get_compat_timespec(&in, rqtp)) | 640 | if (get_compat_timespec(&in, rqtp)) |
| 613 | return -EFAULT; | 641 | return -EFAULT; |
| @@ -618,9 +646,16 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | |||
| 618 | (struct timespec __user *) &in, | 646 | (struct timespec __user *) &in, |
| 619 | (struct timespec __user *) &out); | 647 | (struct timespec __user *) &out); |
| 620 | set_fs(oldfs); | 648 | set_fs(oldfs); |
| 649 | |||
| 621 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | 650 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && |
| 622 | put_compat_timespec(&out, rmtp)) | 651 | put_compat_timespec(&out, rmtp)) |
| 623 | return -EFAULT; | 652 | return -EFAULT; |
| 653 | |||
| 654 | if (err == -ERESTART_RESTARTBLOCK) { | ||
| 655 | restart = ¤t_thread_info()->restart_block; | ||
| 656 | restart->fn = compat_clock_nanosleep_restart; | ||
| 657 | restart->arg1 = (unsigned long) rmtp; | ||
| 658 | } | ||
| 624 | return err; | 659 | return err; |
| 625 | } | 660 | } |
| 626 | 661 | ||
