All of lore.kernel.org
 help / color / mirror / Atom feed
From: Deepa Dinamani <deepa.kernel@gmail.com>
To: tglx@linutronix.de, viro@zeniv.linux.org.uk,
	linux-kernel@vger.kernel.org
Cc: john.stultz@linaro.org, nicolas.pitre@linaro.org, arnd@arndb.de,
	y2038@lists.linaro.org, linux-fsdevel@vger.kernel.org
Subject: [PATCH 2/8] nanosleep: Move native and compat syscalls
Date: Sun, 18 Jun 2017 23:45:09 -0700	[thread overview]
Message-ID: <20170619064515.922-3-deepa.kernel@gmail.com> (raw)
In-Reply-To: <20170619064515.922-1-deepa.kernel@gmail.com>

Move nanosleep syscall to a new file that is compiled
unconditionally. This helps share common nanosleep code
between posix-timers and posix-stubs. The latter part
is addressed in subsequent patches in the series.

In this series, this also servers as a preparatory patch
to eliminate the use of set_fs()/get_fs() in the compat
syscall path.

Note that the clock_nanosleep compat syscalls have to be moved
twice, once into each file: posix_timers.c and posix-stubs.c.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
 kernel/compat.c            | 131 ---------------------------------------------
 kernel/time/hrtimer.c      |  17 +-----
 kernel/time/nanosleep.c    |  94 ++++++++++++++++++++++++++++++++
 kernel/time/posix-stubs.c  |  56 +++++++++++++++++++
 kernel/time/posix-timers.c |  58 ++++++++++++++++++++
 5 files changed, 209 insertions(+), 147 deletions(-)
 create mode 100644 kernel/time/nanosleep.c

diff --git a/kernel/compat.c b/kernel/compat.c
index c7a01a01222d..89d10cf47e9c 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -257,82 +257,6 @@ int compat_convert_timespec(struct timespec __user **kts,
 	return 0;
 }
 
-static long compat_nanosleep_restart(struct restart_block *restart)
-{
-	struct compat_timespec __user *rmtp;
-	struct timespec rmt;
-	mm_segment_t oldfs;
-	long ret;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		rmtp = restart->nanosleep.compat_rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	struct timespec tu, rmt;
-	struct timespec64 tu64;
-	mm_segment_t oldfs;
-	long ret;
-
-	if (compat_get_timespec(&tu, rqtp))
-		return -EFAULT;
-
-	tu64 = timespec_to_timespec64(tu);
-	if (!timespec64_valid(&tu64))
-		return -EINVAL;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = hrtimer_nanosleep(&tu64,
-				rmtp ? (struct timespec __user *)&rmt : NULL,
-				HRTIMER_MODE_REL, CLOCK_MONOTONIC);
-	set_fs(oldfs);
-
-	/*
-	 * hrtimer_nanosleep() can only return 0 or
-	 * -ERESTART_RESTARTBLOCK here because:
-	 *
-	 * - we call it with HRTIMER_MODE_REL and therefor exclude the
-	 *   -ERESTARTNOHAND return path.
-	 *
-	 * - we supply the rmtp argument from the task stack (due to
-	 *   the necessary compat conversion. So the update cannot
-	 *   fail, which excludes the -EFAULT return path as well. If
-	 *   it fails nevertheless we have a bigger problem and wont
-	 *   reach this place anymore.
-	 *
-	 * - if the return value is 0, we do not have to update rmtp
-	 *    because there is no remaining time.
-	 *
-	 * We check for -ERESTART_RESTARTBLOCK nevertheless if the
-	 * core implementation decides to return random nonsense.
-	 */
-	if (ret == -ERESTART_RESTARTBLOCK) {
-		struct restart_block *restart = &current->restart_block;
-
-		restart->fn = compat_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-
-		if (rmtp && compat_put_timespec(&rmt, rmtp))
-			return -EFAULT;
-	}
-	return ret;
-}
-
 static inline long get_compat_itimerval(struct itimerval *o,
 		struct compat_itimerval __user *i)
 {
@@ -865,61 +789,6 @@ COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 	return err;
 }
 
-static long compat_clock_nanosleep_restart(struct restart_block *restart)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec tu;
-	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
-
-	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = clock_nanosleep_restart(restart);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&tu, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
-COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
-		       struct compat_timespec __user *, rqtp,
-		       struct compat_timespec __user *, rmtp)
-{
-	long err;
-	mm_segment_t oldfs;
-	struct timespec in, out;
-	struct restart_block *restart;
-
-	if (compat_get_timespec(&in, rqtp))
-		return -EFAULT;
-
-	oldfs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_clock_nanosleep(which_clock, flags,
-				  (struct timespec __user *) &in,
-				  (struct timespec __user *) &out);
-	set_fs(oldfs);
-
-	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
-	    compat_put_timespec(&out, rmtp))
-		return -EFAULT;
-
-	if (err == -ERESTART_RESTARTBLOCK) {
-		restart = &current->restart_block;
-		restart->fn = compat_clock_nanosleep_restart;
-		restart->nanosleep.compat_rmtp = rmtp;
-	}
-	return err;
-}
-
 /*
  * We currently only need the following fields from the sigevent
  * structure: sigev_value, sigev_signo, sig_notify and (sometimes
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index ac053bb5296e..e95628910b00 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -37,6 +37,7 @@
 #include <linux/hrtimer.h>
 #include <linux/notifier.h>
 #include <linux/syscalls.h>
+#include <linux/compat.h>
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
 #include <linux/tick.h>
@@ -1544,22 +1545,6 @@ long hrtimer_nanosleep(struct timespec64 *rqtp, struct timespec __user *rmtp,
 	return ret;
 }
 
-SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
-		struct timespec __user *, rmtp)
-{
-	struct timespec64 tu64;
-	struct timespec tu;
-
-	if (copy_from_user(&tu, rqtp, sizeof(tu)))
-		return -EFAULT;
-
-	tu64 = timespec_to_timespec64(tu);
-	if (!timespec64_valid(&tu64))
-		return -EINVAL;
-
-	return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
-}
-
 /*
  * Functions related to boot-time initialization:
  */
diff --git a/kernel/time/nanosleep.c b/kernel/time/nanosleep.c
new file mode 100644
index 000000000000..2b6e6980b65d
--- /dev/null
+++ b/kernel/time/nanosleep.c
@@ -0,0 +1,94 @@
+SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
+		struct timespec __user *, rmtp)
+{
+	struct timespec64 tu64;
+	struct timespec tu;
+
+	if (copy_from_user(&tu, rqtp, sizeof(tu)))
+		return -EFAULT;
+
+	tu64 = timespec_to_timespec64(tu);
+	if (!timespec64_valid(&tu64))
+		return -EINVAL;
+
+	return hrtimer_nanosleep(&tu64, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+}
+
+#ifdef CONFIG_COMPAT
+static long compat_nanosleep_restart(struct restart_block *restart)
+{
+	struct compat_timespec __user *rmtp;
+	struct timespec rmt;
+	mm_segment_t oldfs;
+	long ret;
+
+	restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = hrtimer_nanosleep_restart(restart);
+	set_fs(oldfs);
+
+	if (ret == -ERESTART_RESTARTBLOCK) {
+		rmtp = restart->nanosleep.compat_rmtp;
+
+		if (rmtp && compat_put_timespec(&rmt, rmtp))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
+{
+	struct timespec tu, rmt;
+	struct timespec64 tu64;
+	mm_segment_t oldfs;
+	long ret;
+
+	if (compat_get_timespec(&tu, rqtp))
+		return -EFAULT;
+
+	tu64 = timespec_to_timespec64(tu);
+	if (!timespec64_valid(&tu64))
+		return -EINVAL;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = hrtimer_nanosleep(&tu64,
+				rmtp ? (struct timespec __user *)&rmt : NULL,
+				HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+	set_fs(oldfs);
+
+	/*
+	 * hrtimer_nanosleep() can only return 0 or
+	 * -ERESTART_RESTARTBLOCK here because:
+	 *
+	 * - we call it with HRTIMER_MODE_REL and therefor exclude the
+	 *   -ERESTARTNOHAND return path.
+	 *
+	 * - we supply the rmtp argument from the task stack (due to
+	 *   the necessary compat conversion. So the update cannot
+	 *   fail, which excludes the -EFAULT return path as well. If
+	 *   it fails nevertheless we have a bigger problem and wont
+	 *   reach this place anymore.
+	 *
+	 * - if the return value is 0, we do not have to update rmtp
+	 *    because there is no remaining time.
+	 *
+	 * We check for -ERESTART_RESTARTBLOCK nevertheless if the
+	 * core implementation decides to return random nonsense.
+	 */
+	if (ret == -ERESTART_RESTARTBLOCK) {
+		struct restart_block *restart = &current->restart_block;
+
+		restart->fn = compat_nanosleep_restart;
+		restart->nanosleep.compat_rmtp = rmtp;
+
+		if (rmtp && compat_put_timespec(&rmt, rmtp))
+			return -EFAULT;
+	}
+	return ret;
+}
+#endif
+
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
index c0cd53eb018a..3031a28921ba 100644
--- a/kernel/time/posix-stubs.c
+++ b/kernel/time/posix-stubs.c
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/syscalls.h>
+#include <linux/compat.h>
 #include <linux/ktime.h>
 #include <linux/timekeeping.h>
 #include <linux/posix-timers.h>
@@ -128,4 +129,59 @@ long clock_nanosleep_restart(struct restart_block *restart_block)
 {
 	return hrtimer_nanosleep_restart(restart_block);
 }
+
+static long compat_clock_nanosleep_restart(struct restart_block *restart)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec tu;
+	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
+
+	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = clock_nanosleep_restart(restart);
+	set_fs(oldfs);
+
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    compat_put_timespec(&tu, rmtp))
+		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->nanosleep.compat_rmtp = rmtp;
+	}
+	return err;
+}
+
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec in, out;
+	struct restart_block *restart;
+
+	if (compat_get_timespec(&in, rqtp))
+		return -EFAULT;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_clock_nanosleep(which_clock, flags,
+				  (struct timespec __user *) &in,
+				  (struct timespec __user *) &out);
+	set_fs(oldfs);
+
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    compat_put_timespec(&out, rmtp))
+		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart = &current->restart_block;
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->nanosleep.compat_rmtp = rmtp;
+	}
+	return err;
+}
 #endif
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 6e7a70b1bf37..cf32adccd062 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -45,6 +45,7 @@
 #include <linux/posix-clock.h>
 #include <linux/posix-timers.h>
 #include <linux/syscalls.h>
+#include <linux/compat.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/export.h>
@@ -1176,3 +1177,60 @@ static const struct k_clock *clockid_to_kclock(const clockid_t id)
 		return NULL;
 	return posix_clocks[id];
 }
+
+#ifdef CONFIG_COMPAT
+static long compat_clock_nanosleep_restart(struct restart_block *restart)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec tu;
+	struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
+
+	restart->nanosleep.rmtp = (struct timespec __user *) &tu;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = clock_nanosleep_restart(restart);
+	set_fs(oldfs);
+
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    compat_put_timespec(&tu, rmtp))
+		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->nanosleep.compat_rmtp = rmtp;
+	}
+	return err;
+}
+
+COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
+		       struct compat_timespec __user *, rqtp,
+		       struct compat_timespec __user *, rmtp)
+{
+	long err;
+	mm_segment_t oldfs;
+	struct timespec in, out;
+	struct restart_block *restart;
+
+	if (compat_get_timespec(&in, rqtp))
+		return -EFAULT;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_clock_nanosleep(which_clock, flags,
+				  (struct timespec __user *) &in,
+				  (struct timespec __user *) &out);
+	set_fs(oldfs);
+
+	if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+	    compat_put_timespec(&out, rmtp))
+		return -EFAULT;
+
+	if (err == -ERESTART_RESTARTBLOCK) {
+		restart = &current->restart_block;
+		restart->fn = compat_clock_nanosleep_restart;
+		restart->nanosleep.compat_rmtp = rmtp;
+	}
+	return err;
+}
+#endif
-- 
2.11.0

  parent reply	other threads:[~2017-06-19  6:45 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-19  6:45 [PATCH 0/8] Isolate time_t data types for clock/timer syscalls Deepa Dinamani
2017-06-19  6:45 ` [PATCH 1/8] time: add get_timespec64 and put_timespec64 Deepa Dinamani
2017-06-19  6:45 ` Deepa Dinamani [this message]
2017-06-19  6:45 ` [PATCH 3/8] kernel: compat: Move clock and timer compat syscalls Deepa Dinamani
2017-06-19  6:45 ` [PATCH 4/8] nanosleep: Use get_timespec64() and set_timespec64() Deepa Dinamani
2017-06-19  6:45 ` [PATCH 5/8] posix-timers: Use get_timepsec64() and put_timespec64() Deepa Dinamani
2017-06-19  6:45 ` [PATCH 6/8] time: introduce {get,put}_itimerspec64 Deepa Dinamani
2017-06-19  6:45 ` [PATCH 7/8] posix_clocks: Use get_itimerspec64() and put_itimerspec64() Deepa Dinamani
2017-06-19  6:45 ` [PATCH 8/8] timerfd: " Deepa Dinamani
2017-06-19  7:25 ` [PATCH 0/8] Isolate time_t data types for clock/timer syscalls Al Viro
2017-06-19 19:31   ` Deepa Dinamani
2017-06-19 19:46     ` Al Viro
2017-06-19 20:52       ` Deepa Dinamani
2017-06-19 21:12         ` Al Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170619064515.922-3-deepa.kernel@gmail.com \
    --to=deepa.kernel@gmail.com \
    --cc=arnd@arndb.de \
    --cc=john.stultz@linaro.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nicolas.pitre@linaro.org \
    --cc=tglx@linutronix.de \
    --cc=viro@zeniv.linux.org.uk \
    --cc=y2038@lists.linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.