git: 5171ed79f6d1 - main - linux(4): Copyout pselect timeout.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Tue, 26 Apr 2022 16:37:15 UTC
The branch main has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=5171ed79f6d1fc3948a7ebfb32b02d698224c29b

commit 5171ed79f6d1fc3948a7ebfb32b02d698224c29b
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-04-26 16:35:56 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-04-26 16:35:56 +0000

    linux(4): Copyout pselect timeout.
    
    According to pselect6 manual, on error timeout becomes undefined, by fact
    Linux modifies the timeout and ignore EFAULT error if so.
    
    MFC after:      2 weeks
---
 sys/compat/linux/linux_misc.c | 46 ++++++++++++++++++-------------------------
 1 file changed, 19 insertions(+), 27 deletions(-)

diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 252c6e0737c0..8a9e34d6cae3 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -2379,7 +2379,7 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
 {
 	struct l_timespec lts;
 	struct timespec ts, *tsp;
-	int error;
+	int error, error2;
 
 	if (args->tsp != NULL) {
 		error = copyin(args->tsp, &lts, sizeof(lts));
@@ -2394,13 +2394,11 @@ 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 (error != 0)
-		return (error);
 
 	if (args->tsp != NULL) {
-		error = native_to_linux_timespec(&lts, tsp);
-		if (error == 0)
-			error = copyout(&lts, args->tsp, sizeof(lts));
+		error2 = native_to_linux_timespec(&lts, tsp);
+		if (error2 == 0)
+			copyout(&lts, args->tsp, sizeof(lts));
 	}
 	return (error);
 }
@@ -2452,21 +2450,17 @@ linux_common_pselect6(struct thread *td, l_int nfds, l_fd_set *readfds,
 	error = kern_pselect(td, nfds, readfds, writefds,
 	    exceptfds, tvp, ssp, LINUX_NFDBITS);
 
-	if (error == 0 && tsp != NULL) {
-		if (td->td_retval[0] != 0) {
-			/*
-			 * Compute how much time was left of the timeout,
-			 * by subtracting the current time and the time
-			 * before we started the call, and subtracting
-			 * that result from the user-supplied value.
-			 */
-
-			microtime(&tv1);
-			timevalsub(&tv1, &tv0);
-			timevalsub(&utv, &tv1);
-			if (utv.tv_sec < 0)
-				timevalclear(&utv);
-		} else
+	if (tsp != NULL) {
+		/*
+		 * Compute how much time was left of the timeout,
+		 * by subtracting the current time and the time
+		 * before we started the call, and subtracting
+		 * that result from the user-supplied value.
+		 */
+		microtime(&tv1);
+		timevalsub(&tv1, &tv0);
+		timevalsub(&utv, &tv1);
+		if (utv.tv_sec < 0)
 			timevalclear(&utv);
 		TIMEVAL_TO_TIMESPEC(&utv, tsp);
 	}
@@ -2480,7 +2474,7 @@ linux_pselect6_time64(struct thread *td,
 {
 	struct l_timespec64 lts;
 	struct timespec ts, *tsp;
-	int error;
+	int error, error2;
 
 	if (args->tsp != NULL) {
 		error = copyin(args->tsp, &lts, sizeof(lts));
@@ -2495,13 +2489,11 @@ linux_pselect6_time64(struct thread *td,
 
 	error = linux_common_pselect6(td, args->nfds, args->readfds,
 	    args->writefds, args->exceptfds, tsp, args->sig);
-	if (error != 0)
-		return (error);
 
 	if (args->tsp != NULL) {
-		error = native_to_linux_timespec64(&lts, tsp);
-		if (error == 0)
-			error = copyout(&lts, args->tsp, sizeof(lts));
+		error2 = native_to_linux_timespec64(&lts, tsp);
+		if (error2 == 0)
+			copyout(&lts, args->tsp, sizeof(lts));
 	}
 	return (error);
 }