git: 707e567a4061 - main - linux(4): Add a helper intended for copying timespec's from the userspace.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Sun, 08 May 2022 13:17:11 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=707e567a4061669b7643ddbe8a1ad9c4e6545a75

commit 707e567a4061669b7643ddbe8a1ad9c4e6545a75
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-08 13:16:47 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-05-08 13:16:47 +0000

    linux(4): Add a helper intended for copying timespec's from the userspace.
    
    There are many places where we copyin Linux timespec from the userspace
    and then convert it to the kernel timespec. To avoid code duplication
    add a tiny halper for doing this.
    
    MFC after:              2 weeks
---
 sys/compat/linux/linux_event.c  | 10 ++----
 sys/compat/linux/linux_futex.c  | 12 ++-----
 sys/compat/linux/linux_ipc.c    | 10 ++----
 sys/compat/linux/linux_misc.c   | 24 +++-----------
 sys/compat/linux/linux_signal.c | 10 ++----
 sys/compat/linux/linux_socket.c | 12 ++-----
 sys/compat/linux/linux_time.c   | 73 ++++++++++++++++-------------------------
 sys/compat/linux/linux_timer.h  |  4 +++
 8 files changed, 47 insertions(+), 108 deletions(-)

diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index 5e62848303f1..e03335a87ec4 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -540,7 +540,6 @@ int
 linux_epoll_pwait2_64(struct thread *td, struct linux_epoll_pwait2_64_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec64 lts;
 	sigset_t mask, *pmask;
 	int error;
 
@@ -550,9 +549,7 @@ linux_epoll_pwait2_64(struct thread *td, struct linux_epoll_pwait2_64_args *args
 		return (error);
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec64(&ts, &lts);
+		error = linux_get_timespec64(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
@@ -567,7 +564,6 @@ int
 linux_epoll_pwait2(struct thread *td, struct linux_epoll_pwait2_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec lts;
 	sigset_t mask, *pmask;
 	int error;
 
@@ -577,9 +573,7 @@ linux_epoll_pwait2(struct thread *td, struct linux_epoll_pwait2_args *args)
 		return (error);
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec(&ts, &lts);
+		error = linux_get_timespec(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index a194e0ac7962..5591b4fc3234 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -816,7 +816,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
 		.val3 = args->val3,
 		.val3_compare = true,
 	};
-	struct l_timespec lts;
 	int error;
 
 	switch (args->op & LINUX_FUTEX_CMD_MASK) {
@@ -825,10 +824,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
 	case LINUX_FUTEX_LOCK_PI:
 	case LINUX_FUTEX_LOCK_PI2:
 		if (args->timeout != NULL) {
-			error = copyin(args->timeout, &lts, sizeof(lts));
-			if (error != 0)
-				return (error);
-			error = linux_to_native_timespec(&fargs.kts, &lts);
+			error = linux_get_timespec(&fargs.kts, args->timeout);
 			if (error != 0)
 				return (error);
 			fargs.ts = &fargs.kts;
@@ -854,7 +850,6 @@ linux_sys_futex_time64(struct thread *td,
 		.val3 = args->val3,
 		.val3_compare = true,
 	};
-	struct l_timespec64 lts;
 	int error;
 
 	switch (args->op & LINUX_FUTEX_CMD_MASK) {
@@ -863,10 +858,7 @@ linux_sys_futex_time64(struct thread *td,
 	case LINUX_FUTEX_LOCK_PI:
 	case LINUX_FUTEX_LOCK_PI2:
 		if (args->timeout != NULL) {
-			error = copyin(args->timeout, &lts, sizeof(lts));
-			if (error != 0)
-				return (error);
-			error = linux_to_native_timespec64(&fargs.kts, &lts);
+			error = linux_get_timespec64(&fargs.kts, args->timeout);
 			if (error != 0)
 				return (error);
 			fargs.ts = &fargs.kts;
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index 51bf18dcd097..258917e6a969 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -510,13 +510,10 @@ int
 linux_semtimedop_time64(struct thread *td, struct linux_semtimedop_time64_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec64 lts;
 	int error;
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec64(&ts, &lts);
+		error = linux_get_timespec64(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
@@ -532,13 +529,10 @@ int
 linux_semtimedop(struct thread *td, struct linux_semtimedop_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec lts;
 	int error;
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec(&ts, &lts);
+		error = linux_get_timespec(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 81002540633e..54fbc9e2b938 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -2380,15 +2380,11 @@ linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args)
 int
 linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
 {
-	struct l_timespec lts;
 	struct timespec ts, *tsp;
 	int error;
 
 	if (args->tsp != NULL) {
-		error = copyin(args->tsp, &lts, sizeof(lts));
-		if (error != 0)
-			return (error);
-		error = linux_to_native_timespec(&ts, &lts);
+		error = linux_get_timespec(&ts, args->tsp);
 		if (error != 0)
 			return (error);
 		tsp = &ts;
@@ -2472,15 +2468,11 @@ int
 linux_pselect6_time64(struct thread *td,
     struct linux_pselect6_time64_args *args)
 {
-	struct l_timespec64 lts;
 	struct timespec ts, *tsp;
 	int error;
 
 	if (args->tsp != NULL) {
-		error = copyin(args->tsp, &lts, sizeof(lts));
-		if (error != 0)
-			return (error);
-		error = linux_to_native_timespec64(&ts, &lts);
+		error = linux_get_timespec64(&ts, args->tsp);
 		if (error != 0)
 			return (error);
 		tsp = &ts;
@@ -2500,14 +2492,10 @@ int
 linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
 {
 	struct timespec uts, *tsp;
-	struct l_timespec lts;
 	int error;
 
 	if (args->tsp != NULL) {
-		error = copyin(args->tsp, &lts, sizeof(lts));
-		if (error)
-			return (error);
-		error = linux_to_native_timespec(&uts, &lts);
+		error = linux_get_timespec(&uts, args->tsp);
 		if (error != 0)
 			return (error);
 		tsp = &uts;
@@ -2582,14 +2570,10 @@ int
 linux_ppoll_time64(struct thread *td, struct linux_ppoll_time64_args *args)
 {
 	struct timespec uts, *tsp;
-	struct l_timespec64 lts;
 	int error;
 
 	if (args->tsp != NULL) {
-		error = copyin(args->tsp, &lts, sizeof(lts));
-		if (error != 0)
-			return (error);
-		error = linux_to_native_timespec64(&uts, &lts);
+		error = linux_get_timespec64(&uts, args->tsp);
 		if (error != 0)
 			return (error);
 		tsp = &uts;
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index 0848040d009c..a9af0d726f56 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -436,13 +436,10 @@ linux_rt_sigtimedwait(struct thread *td,
 	struct linux_rt_sigtimedwait_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec lts;
 	int error;
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec(&ts, &lts);
+		error = linux_get_timespec(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
@@ -490,13 +487,10 @@ linux_rt_sigtimedwait_time64(struct thread *td,
 	struct linux_rt_sigtimedwait_time64_args *args)
 {
 	struct timespec ts, *tsa;
-	struct l_timespec64 lts;
 	int error;
 
 	if (args->timeout) {
-		if ((error = copyin(args->timeout, &lts, sizeof(lts))))
-			return (error);
-		error = linux_to_native_timespec64(&ts, &lts);
+		error = linux_get_timespec64(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		tsa = &ts;
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 93b5cea7ecc3..b5ec32835981 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -1786,15 +1786,11 @@ linux_recvmmsg_common(struct thread *td, l_int s, struct l_mmsghdr *msg,
 int
 linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
 {
-	struct l_timespec lts;
 	struct timespec ts, tts, *ptts;
 	int error;
 
 	if (args->timeout) {
-		error = copyin(args->timeout, &lts, sizeof(struct l_timespec));
-		if (error != 0)
-			return (error);
-		error = linux_to_native_timespec(&ts, &lts);
+		error = linux_get_timespec(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		getnanotime(&tts);
@@ -1811,15 +1807,11 @@ linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
 int
 linux_recvmmsg_time64(struct thread *td, struct linux_recvmmsg_time64_args *args)
 {
-	struct l_timespec64 lts;
 	struct timespec ts, tts, *ptts;
 	int error;
 
 	if (args->timeout) {
-		error = copyin(args->timeout, &lts, sizeof(struct l_timespec));
-		if (error != 0)
-			return (error);
-		error = linux_to_native_timespec64(&ts, &lts);
+		error = linux_get_timespec64(&ts, args->timeout);
 		if (error != 0)
 			return (error);
 		getnanotime(&tts);
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 0f1af6b3a5cf..0be7025abe05 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -101,16 +101,13 @@ LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int");
 #endif
-LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
-LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
-LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
 #endif
@@ -162,6 +159,18 @@ linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
 	return (copyout(&lts, ltp, sizeof(lts)));
 }
 
+int
+linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp)
+{
+	struct l_timespec lts;
+	int error;
+
+	error = copyin(ultp, &lts, sizeof(lts));
+	if (error != 0)
+		return (error);
+	return (linux_to_native_timespec(ntp, &lts));
+}
+
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 int
 native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
@@ -203,6 +212,18 @@ linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
 		return (error);
 	return (copyout(&lts, ltp, sizeof(lts)));
 }
+
+int
+linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp)
+{
+	struct l_timespec64 lts;
+	int error;
+
+	error = copyin(ultp, &lts, sizeof(lts));
+	if (error != 0)
+		return (error);
+	return (linux_to_native_timespec64(ntp, &lts));
+}
 #endif
 
 int
@@ -508,19 +529,13 @@ int
 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
 {
 	struct timespec ts;
-	struct l_timespec lts;
 	int error;
 
-	error = copyin(args->tp, &lts, sizeof(lts));
+	error = linux_get_timespec(&ts, args->tp);
 	if (error != 0) {
 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
 		return (error);
 	}
-	error = linux_to_native_timespec(&ts, &lts);
-	if (error != 0)
-		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
-		    error);
-
 	return (linux_common_clock_settime(td, args->which, &ts));
 }
 
@@ -529,18 +544,13 @@ int
 linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
 {
 	struct timespec ts;
-	struct l_timespec64 lts;
 	int error;
 
-	error = copyin(args->tp, &lts, sizeof(lts));
+	error = linux_get_timespec64(&ts, args->tp);
 	if (error != 0) {
 		LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
 		return (error);
 	}
-	error = linux_to_native_timespec64(&ts, &lts);
-	if (error != 0)
-		LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
-		    error);
 	return (linux_common_clock_settime(td, args->which, &ts));
 }
 #endif
@@ -680,26 +690,19 @@ int
 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
-	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
+	error = linux_get_timespec(&rqts, args->rqtp);
 	if (error != 0) {
 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
 		return (error);
 	}
-
 	if (args->rmtp != NULL)
 		rmtp = &rmts;
 	else
 		rmtp = NULL;
 
-	error = linux_to_native_timespec(&rqts, &lrqts);
-	if (error != 0) {
-		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
-		return (error);
-	}
 	error = kern_nanosleep(td, &rqts, rmtp);
 	if (error == EINTR && args->rmtp != NULL) {
 		error2 = linux_put_timespec(rmtp, args->rmtp);
@@ -746,24 +749,15 @@ linux_clock_nanosleep(struct thread *td,
     struct linux_clock_nanosleep_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
-	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
+	error = linux_get_timespec(&rqts, args->rqtp);
 	if (error != 0) {
 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
 		    error);
 		return (error);
 	}
-
-	error = linux_to_native_timespec(&rqts, &lrqts);
-	if (error != 0) {
-		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
-		    error);
-		return (error);
-	}
-
 	if (args->rmtp != NULL)
 		rmtp = &rmts;
 	else
@@ -789,24 +783,15 @@ linux_clock_nanosleep_time64(struct thread *td,
     struct linux_clock_nanosleep_time64_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec64 lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
-	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
+	error = linux_get_timespec64(&rqts, args->rqtp);
 	if (error != 0) {
 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
 		    copyin_error, error);
 		return (error);
 	}
-
-	error = linux_to_native_timespec64(&rqts, &lrqts);
-	if (error != 0) {
-		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
-		    conversion_error, error);
-		return (error);
-	}
-
 	if (args->rmtp != NULL)
 		rmtp = &rmts;
 	else
diff --git a/sys/compat/linux/linux_timer.h b/sys/compat/linux/linux_timer.h
index edff6c845032..b9f877cc83a4 100644
--- a/sys/compat/linux/linux_timer.h
+++ b/sys/compat/linux/linux_timer.h
@@ -117,6 +117,8 @@ int linux_to_native_timespec(struct timespec *,
 				     struct l_timespec *);
 int linux_put_timespec(struct timespec *,
 				     struct l_timespec *);
+int linux_get_timespec(struct timespec *,
+				     const struct l_timespec *);
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 int native_to_linux_timespec64(struct l_timespec64 *,
 				     struct timespec *);
@@ -124,6 +126,8 @@ int linux_to_native_timespec64(struct timespec *,
 				     struct l_timespec64 *);
 int linux_put_timespec64(struct timespec *,
 				     struct l_timespec64 *);
+int linux_get_timespec64(struct timespec *,
+				    const  struct l_timespec64 *);
 #endif
 int linux_to_native_clockid(clockid_t *, clockid_t);
 int native_to_linux_itimerspec(struct l_itimerspec *,