aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/compat.c')
-rw-r--r--kernel/compat.c35
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
29extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
30
28int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) 31int 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
607static 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
604long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, 631long 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 = &current_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