aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/compat.c')
-rw-r--r--kernel/compat.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/kernel/compat.c b/kernel/compat.c
index 42a1ed4b61b1..5f0e201bcfd3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -40,10 +40,35 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
40 __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; 40 __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
41} 41}
42 42
43static long compat_nanosleep_restart(struct restart_block *restart)
44{
45 struct compat_timespec __user *rmtp;
46 struct timespec rmt;
47 mm_segment_t oldfs;
48 long ret;
49
50 rmtp = (struct compat_timespec __user *)(restart->arg1);
51 restart->arg1 = (unsigned long)&rmt;
52 oldfs = get_fs();
53 set_fs(KERNEL_DS);
54 ret = hrtimer_nanosleep_restart(restart);
55 set_fs(oldfs);
56
57 if (ret) {
58 restart->arg1 = (unsigned long)rmtp;
59
60 if (rmtp && put_compat_timespec(&rmt, rmtp))
61 return -EFAULT;
62 }
63
64 return ret;
65}
66
43asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, 67asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
44 struct compat_timespec __user *rmtp) 68 struct compat_timespec __user *rmtp)
45{ 69{
46 struct timespec tu, rmt; 70 struct timespec tu, rmt;
71 mm_segment_t oldfs;
47 long ret; 72 long ret;
48 73
49 if (get_compat_timespec(&tu, rqtp)) 74 if (get_compat_timespec(&tu, rqtp))
@@ -52,11 +77,21 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
52 if (!timespec_valid(&tu)) 77 if (!timespec_valid(&tu))
53 return -EINVAL; 78 return -EINVAL;
54 79
55 ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL, 80 oldfs = get_fs();
56 CLOCK_MONOTONIC); 81 set_fs(KERNEL_DS);
82 ret = hrtimer_nanosleep(&tu,
83 rmtp ? (struct timespec __user *)&rmt : NULL,
84 HRTIMER_MODE_REL, CLOCK_MONOTONIC);
85 set_fs(oldfs);
86
87 if (ret) {
88 struct restart_block *restart
89 = &current_thread_info()->restart_block;
90
91 restart->fn = compat_nanosleep_restart;
92 restart->arg1 = (unsigned long)rmtp;
57 93
58 if (ret && rmtp) { 94 if (rmtp && put_compat_timespec(&rmt, rmtp))
59 if (put_compat_timespec(&rmt, rmtp))
60 return -EFAULT; 95 return -EFAULT;
61 } 96 }
62 97