aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/compat.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-06-07 04:42:31 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-06-13 18:00:42 -0400
commitedbeda46322fbcb15af2d2d0f2daffb0cd349a5a (patch)
treea4aa5436d4e5dcce6f4d041d13c521e1660331b7 /kernel/compat.c
parent99e6c0e6ec349575886ca7daffc9cb7ec583176f (diff)
time/posix-timers: Move the compat copyouts to the nanosleep implementations
Turn restart_block.nanosleep.{rmtp,compat_rmtp} into a tagged union (kind = 1 -> native, kind = 2 -> compat, kind = 0 -> nothing) and make the places doing actual copyout handle compat as well as native (that will become a helper in the next commit). Result: compat wrappers, messing with reassignments, etc. are gone. [ tglx: Folded in a variant of Peter Zijlstras enum patch ] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20170607084241.28657-6-viro@ZenIV.linux.org.uk
Diffstat (limited to 'kernel/compat.c')
-rw-r--r--kernel/compat.c131
1 files changed, 0 insertions, 131 deletions
diff --git a/kernel/compat.c b/kernel/compat.c
index cc9ba9d29b47..23afa26f574b 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -213,82 +213,6 @@ int compat_convert_timespec(struct timespec __user **kts,
213 return 0; 213 return 0;
214} 214}
215 215
216static long compat_nanosleep_restart(struct restart_block *restart)
217{
218 struct compat_timespec __user *rmtp;
219 struct timespec rmt;
220 mm_segment_t oldfs;
221 long ret;
222
223 restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
224 oldfs = get_fs();
225 set_fs(KERNEL_DS);
226 ret = hrtimer_nanosleep_restart(restart);
227 set_fs(oldfs);
228
229 if (ret == -ERESTART_RESTARTBLOCK) {
230 rmtp = restart->nanosleep.compat_rmtp;
231
232 if (rmtp && compat_put_timespec(&rmt, rmtp))
233 return -EFAULT;
234 }
235
236 return ret;
237}
238
239COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
240 struct compat_timespec __user *, rmtp)
241{
242 struct timespec tu, rmt;
243 struct timespec64 tu64;
244 mm_segment_t oldfs;
245 long ret;
246
247 if (compat_get_timespec(&tu, rqtp))
248 return -EFAULT;
249
250 tu64 = timespec_to_timespec64(tu);
251 if (!timespec64_valid(&tu64))
252 return -EINVAL;
253
254 oldfs = get_fs();
255 set_fs(KERNEL_DS);
256 current->restart_block.nanosleep.rmtp =
257 rmtp ? (struct timespec __user *)&rmt : NULL;
258 ret = hrtimer_nanosleep(&tu64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
259 set_fs(oldfs);
260
261 /*
262 * hrtimer_nanosleep() can only return 0 or
263 * -ERESTART_RESTARTBLOCK here because:
264 *
265 * - we call it with HRTIMER_MODE_REL and therefor exclude the
266 * -ERESTARTNOHAND return path.
267 *
268 * - we supply the rmtp argument from the task stack (due to
269 * the necessary compat conversion. So the update cannot
270 * fail, which excludes the -EFAULT return path as well. If
271 * it fails nevertheless we have a bigger problem and wont
272 * reach this place anymore.
273 *
274 * - if the return value is 0, we do not have to update rmtp
275 * because there is no remaining time.
276 *
277 * We check for -ERESTART_RESTARTBLOCK nevertheless if the
278 * core implementation decides to return random nonsense.
279 */
280 if (ret == -ERESTART_RESTARTBLOCK) {
281 struct restart_block *restart = &current->restart_block;
282
283 restart->fn = compat_nanosleep_restart;
284 restart->nanosleep.compat_rmtp = rmtp;
285
286 if (rmtp && compat_put_timespec(&rmt, rmtp))
287 return -EFAULT;
288 }
289 return ret;
290}
291
292static inline long get_compat_itimerval(struct itimerval *o, 216static inline long get_compat_itimerval(struct itimerval *o,
293 struct compat_itimerval __user *i) 217 struct compat_itimerval __user *i)
294{ 218{
@@ -821,61 +745,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
821 return err; 745 return err;
822} 746}
823 747
824static long compat_clock_nanosleep_restart(struct restart_block *restart)
825{
826 long err;
827 mm_segment_t oldfs;
828 struct timespec tu;
829 struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
830
831 restart->nanosleep.rmtp = (struct timespec __user *) &tu;
832 oldfs = get_fs();
833 set_fs(KERNEL_DS);
834 err = clock_nanosleep_restart(restart);
835 set_fs(oldfs);
836
837 if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
838 compat_put_timespec(&tu, rmtp))
839 return -EFAULT;
840
841 if (err == -ERESTART_RESTARTBLOCK) {
842 restart->fn = compat_clock_nanosleep_restart;
843 restart->nanosleep.compat_rmtp = rmtp;
844 }
845 return err;
846}
847
848COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
849 struct compat_timespec __user *, rqtp,
850 struct compat_timespec __user *, rmtp)
851{
852 long err;
853 mm_segment_t oldfs;
854 struct timespec in, out;
855 struct restart_block *restart;
856
857 if (compat_get_timespec(&in, rqtp))
858 return -EFAULT;
859
860 oldfs = get_fs();
861 set_fs(KERNEL_DS);
862 err = sys_clock_nanosleep(which_clock, flags,
863 (struct timespec __user *) &in,
864 (struct timespec __user *) &out);
865 set_fs(oldfs);
866
867 if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
868 compat_put_timespec(&out, rmtp))
869 return -EFAULT;
870
871 if (err == -ERESTART_RESTARTBLOCK) {
872 restart = &current->restart_block;
873 restart->fn = compat_clock_nanosleep_restart;
874 restart->nanosleep.compat_rmtp = rmtp;
875 }
876 return err;
877}
878
879/* 748/*
880 * We currently only need the following fields from the sigevent 749 * We currently only need the following fields from the sigevent
881 * structure: sigev_value, sigev_signo, sig_notify and (sometimes 750 * structure: sigev_value, sigev_signo, sig_notify and (sometimes