git: 5a37b53f165c - stable/13 - linux(4): Add a helper intended for copying timespec's to the userspace.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Fri, 17 Jun 2022 19:40:02 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=5a37b53f165cf3f4c530a99bb346c5a5aeaa132e

commit 5a37b53f165cf3f4c530a99bb346c5a5aeaa132e
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-08 12:37:27 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:34:58 +0000

    linux(4): Add a helper intended for copying timespec's to the userspace.
    
    There are many places where we convert natvie timespec and copyout it to
    the userspace. To avoid code duplication add a tiny halper for doing this.
    
    MFC after:              2 weeks
    
    (cherry picked from commit 9a9482f87490bcbb054ba1799d69fdab7cdb6dc9)
---
 sys/compat/linux/linux_misc.c  | 48 +++++++---------------------
 sys/compat/linux/linux_time.c  | 71 ++++++++++++++++++++----------------------
 sys/compat/linux/linux_timer.h |  4 +++
 3 files changed, 50 insertions(+), 73 deletions(-)

diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index cdc68d64fc5b..61de64b50489 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -2386,7 +2386,7 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
 {
 	struct l_timespec lts;
 	struct timespec ts, *tsp;
-	int error, error2;
+	int error;
 
 	if (args->tsp != NULL) {
 		error = copyin(args->tsp, &lts, sizeof(lts));
@@ -2402,11 +2402,8 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
 	error = linux_common_pselect6(td, args->nfds, args->readfds,
 	    args->writefds, args->exceptfds, tsp, args->sig);
 
-	if (args->tsp != NULL) {
-		error2 = native_to_linux_timespec(&lts, tsp);
-		if (error2 == 0)
-			copyout(&lts, args->tsp, sizeof(lts));
-	}
+	if (args->tsp != NULL)
+		linux_put_timespec(&ts, args->tsp);
 	return (error);
 }
 
@@ -2481,7 +2478,7 @@ linux_pselect6_time64(struct thread *td,
 {
 	struct l_timespec64 lts;
 	struct timespec ts, *tsp;
-	int error, error2;
+	int error;
 
 	if (args->tsp != NULL) {
 		error = copyin(args->tsp, &lts, sizeof(lts));
@@ -2497,11 +2494,8 @@ linux_pselect6_time64(struct thread *td,
 	error = linux_common_pselect6(td, args->nfds, args->readfds,
 	    args->writefds, args->exceptfds, tsp, args->sig);
 
-	if (args->tsp != NULL) {
-		error2 = native_to_linux_timespec64(&lts, tsp);
-		if (error2 == 0)
-			copyout(&lts, args->tsp, sizeof(lts));
-	}
+	if (args->tsp != NULL)
+		linux_put_timespec64(&ts, args->tsp);
 	return (error);
 }
 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -2526,13 +2520,8 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
 
 	error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
 	    args->sset, args->ssize);
-	if (error != 0)
-		return (error);
-	if (tsp != NULL) {
-		error = native_to_linux_timespec(&lts, tsp);
-		if (error == 0)
-			error = copyout(&lts, args->tsp, sizeof(lts));
-	}
+	if (error == 0 && args->tsp != NULL)
+		error = linux_put_timespec(&uts, args->tsp);
 	return (error);
 }
 
@@ -2612,13 +2601,8 @@ linux_ppoll_time64(struct thread *td, struct linux_ppoll_time64_args *args)
  		tsp = NULL;
 	error = linux_common_ppoll(td, args->fds, args->nfds, tsp,
 	    args->sset, args->ssize);
-	if (error != 0)
-		return (error);
-	if (tsp != NULL) {
-		error = native_to_linux_timespec64(&lts, tsp);
-		if (error == 0)
-			error = copyout(&lts, args->tsp, sizeof(lts));
-	}
+	if (error == 0 && args->tsp != NULL)
+		error = linux_put_timespec64(&uts, args->tsp);
 	return (error);
 }
 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -2693,16 +2677,12 @@ linux_sched_rr_get_interval(struct thread *td,
     struct linux_sched_rr_get_interval_args *uap)
 {
 	struct timespec ts;
-	struct l_timespec lts;
 	int error;
 
 	error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
 	if (error != 0)
 		return (error);
-	error = native_to_linux_timespec(&lts, &ts);
-	if (error != 0)
-		return (error);
-	return (copyout(&lts, uap->interval, sizeof(lts)));
+	return (linux_put_timespec(&ts, uap->interval));
 }
 
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
@@ -2711,16 +2691,12 @@ linux_sched_rr_get_interval_time64(struct thread *td,
     struct linux_sched_rr_get_interval_time64_args *uap)
 {
 	struct timespec ts;
-	struct l_timespec64 lts;
 	int error;
 
 	error = linux_sched_rr_get_interval_common(td, uap->pid, &ts);
 	if (error != 0)
 		return (error);
-	error = native_to_linux_timespec64(&lts, &ts);
-	if (error != 0)
-		return (error);
-	return (copyout(&lts, uap->interval, sizeof(lts)));
+	return (linux_put_timespec64(&ts, uap->interval));
 }
 #endif
 
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 447319a7edc9..e97a1145d31b 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -150,6 +150,18 @@ linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
 	return (0);
 }
 
+int
+linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
+{
+	struct l_timespec lts;
+	int error;
+
+	error = native_to_linux_timespec(&lts, ntp);
+	if (error != 0)
+		return (error);
+	return (copyout(&lts, ltp, sizeof(lts)));
+}
+
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 int
 native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
@@ -172,6 +184,18 @@ linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
 
 	return (0);
 }
+
+int
+linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
+{
+	struct l_timespec64 lts;
+	int error;
+
+	error = native_to_linux_timespec64(&lts, ntp);
+	if (error != 0)
+		return (error);
+	return (copyout(&lts, ltp, sizeof(lts)));
+}
 #endif
 
 int
@@ -414,7 +438,6 @@ linux_common_clock_gettime(struct thread *td, clockid_t which,
 int
 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
 {
-	struct l_timespec lts;
 	struct timespec tp;
 	int error;
 
@@ -423,10 +446,7 @@ linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
 		return (error);
 	}
-	error = native_to_linux_timespec(&lts, &tp);
-	if (error != 0)
-		return (error);
-	error = copyout(&lts, args->tp, sizeof(lts));
+	error = linux_put_timespec(&tp, args->tp);
 	if (error != 0)
 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
 
@@ -437,7 +457,6 @@ linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
 int
 linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
 {
-	struct l_timespec64 lts;
 	struct timespec tp;
 	int error;
 
@@ -446,10 +465,7 @@ linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args
 		LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
 		return (error);
 	}
-	error = native_to_linux_timespec64(&lts, &tp);
-	if (error != 0)
-		return (error);
-	error = copyout(&lts, args->tp, sizeof(lts));
+	error = linux_put_timespec64(&tp, args->tp);
 	if (error != 0)
 		LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
 
@@ -622,17 +638,12 @@ linux_clock_getres(struct thread *td,
     struct linux_clock_getres_args *args)
 {
 	struct timespec ts;
-	struct l_timespec lts;
 	int error;
 
 	error = linux_common_clock_getres(td, args->which, &ts);
 	if (error != 0 || args->tp == NULL)
 		return (error);
-
-	error = native_to_linux_timespec(&lts, &ts);
-	if (error != 0)
-		return (error);
-	error = copyout(&lts, args->tp, sizeof(lts));
+	error = linux_put_timespec(&ts, args->tp);
 	if (error != 0)
 		LIN_SDT_PROBE1(time, linux_clock_getres,
 		    copyout_error, error);
@@ -645,17 +656,12 @@ linux_clock_getres_time64(struct thread *td,
     struct linux_clock_getres_time64_args *args)
 {
 	struct timespec ts;
-	struct l_timespec64 lts;
 	int error;
 
 	error = linux_common_clock_getres(td, args->which, &ts);
 	if (error != 0 || args->tp == NULL)
 		return (error);
-
-	error = native_to_linux_timespec64(&lts, &ts);
-	if (error != 0)
-		return (error);
-	error = copyout(&lts, args->tp, sizeof(lts));
+	error = linux_put_timespec64(&ts, args->tp);
 	if (error != 0)
 		LIN_SDT_PROBE1(time, linux_clock_getres_time64,
 		    copyout_error, error);
@@ -667,7 +673,7 @@ int
 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec lrqts, lrmts;
+	struct l_timespec lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
@@ -689,10 +695,7 @@ linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
 	}
 	error = kern_nanosleep(td, &rqts, rmtp);
 	if (error == EINTR && args->rmtp != NULL) {
-		error2 = native_to_linux_timespec(&lrmts, rmtp);
-		if (error2 != 0)
-			return (error2);
-		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
+		error2 = linux_put_timespec(rmtp, args->rmtp);
 		if (error2 != 0) {
 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
 			    error2);
@@ -736,7 +739,7 @@ linux_clock_nanosleep(struct thread *td,
     struct linux_clock_nanosleep_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec lrqts, lrmts;
+	struct l_timespec lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
@@ -763,10 +766,7 @@ linux_clock_nanosleep(struct thread *td,
 	    &rqts, rmtp);
 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
 	    args->rmtp != NULL) {
-		error2 = native_to_linux_timespec(&lrmts, rmtp);
-		if (error2 != 0)
-			return (error2);
-		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
+		error2 = linux_put_timespec(rmtp, args->rmtp);
 		if (error2 != 0) {
 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
 			    copyout_error, error2);
@@ -782,7 +782,7 @@ linux_clock_nanosleep_time64(struct thread *td,
     struct linux_clock_nanosleep_time64_args *args)
 {
 	struct timespec *rmtp;
-	struct l_timespec64 lrqts, lrmts;
+	struct l_timespec64 lrqts;
 	struct timespec rqts, rmts;
 	int error, error2;
 
@@ -809,10 +809,7 @@ linux_clock_nanosleep_time64(struct thread *td,
 	    &rqts, rmtp);
 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
 	    args->rmtp != NULL) {
-		error2 = native_to_linux_timespec64(&lrmts, rmtp);
-		if (error2 != 0)
-			return (error2);
-		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
+		error2 = linux_put_timespec64(rmtp, args->rmtp);
 		if (error2 != 0) {
 			LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
 			    copyout_error, error2);
diff --git a/sys/compat/linux/linux_timer.h b/sys/compat/linux/linux_timer.h
index 7617316b09c6..edff6c845032 100644
--- a/sys/compat/linux/linux_timer.h
+++ b/sys/compat/linux/linux_timer.h
@@ -115,11 +115,15 @@ int native_to_linux_timespec(struct l_timespec *,
 				     struct timespec *);
 int linux_to_native_timespec(struct timespec *,
 				     struct l_timespec *);
+int linux_put_timespec(struct timespec *,
+				     struct l_timespec *);
 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
 int native_to_linux_timespec64(struct l_timespec64 *,
 				     struct timespec *);
 int linux_to_native_timespec64(struct timespec *,
 				     struct l_timespec64 *);
+int linux_put_timespec64(struct timespec *,
+				     struct l_timespec64 *);
 #endif
 int linux_to_native_clockid(clockid_t *, clockid_t);
 int native_to_linux_itimerspec(struct l_itimerspec *,