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 | ||