git: b4736c90adb8 - main - tftpd: Don't consume arbitrary requests when failing to fork.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Fri, 10 Mar 2023 13:29:21 UTC
The branch main has been updated by des:

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

commit b4736c90adb84032aaf1e3bcb8988916a82ed5de
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2023-03-10 13:24:44 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2023-03-10 13:25:16 +0000

    tftpd: Don't consume arbitrary requests when failing to fork.
    
    We've already consumed one request, which is sufficient to prevent inetd from endlessly restarting us in this particular and extremely unlikely case.
    
    Sponsored by:   Klara, Inc.
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D38967
---
 libexec/tftpd/tftpd.c | 52 ++++++++++++---------------------------------------
 1 file changed, 12 insertions(+), 40 deletions(-)

diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 4b8a3024fe5a..8e3d2e13f320 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -134,7 +134,8 @@ main(int argc, char *argv[])
 	struct passwd	*nobody;
 	const char	*chuser = "nobody";
 	char		recvbuffer[MAXPKTSIZE];
-	int		allow_ro = 1, allow_wo = 1;
+	int		allow_ro = 1, allow_wo = 1, on = 1;
+	pid_t		pid;
 
 	tzset();			/* syslog in localtime */
 	acting_as_client = 0;
@@ -222,12 +223,9 @@ main(int argc, char *argv[])
 
 	umask(mask);
 
-	{
-		int on = 1;
-		if (ioctl(0, FIONBIO, &on) < 0) {
-			tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno));
-			exit(1);
-		}
+	if (ioctl(0, FIONBIO, &on) < 0) {
+		tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno));
+		exit(1);
 	}
 
 	/* Find out who we are talking to and what we are going to do */
@@ -255,40 +253,14 @@ main(int argc, char *argv[])
 	 * break before doing the above "recvfrom", inetd would
 	 * spawn endless instances, clogging the system.
 	 */
-	{
-		int i, pid;
-
-		for (i = 1; i < 20; i++) {
-		    pid = fork();
-		    if (pid < 0) {
-				sleep(i);
-				/*
-				 * flush out to most recently sent request.
-				 *
-				 * This may drop some request, but those
-				 * will be resent by the clients when
-				 * they timeout.  The positive effect of
-				 * this flush is to (try to) prevent more
-				 * than one tftpd being started up to service
-				 * a single request from a single client.
-				 */
-				peerlen = sizeof peer_sock;
-				i = recvfrom(0, recvbuffer, MAXPKTSIZE, 0,
-				    (struct sockaddr *)&peer_sock, &peerlen);
-				if (i > 0) {
-					n = i;
-				}
-		    } else {
-				break;
-		    }
-		}
-		if (pid < 0) {
-			tftp_log(LOG_ERR, "fork: %s", strerror(errno));
-			exit(1);
-		} else if (pid != 0) {
-			exit(0);
-		}
+	pid = fork();
+	if (pid < 0) {
+		tftp_log(LOG_ERR, "fork: %s", strerror(errno));
+		exit(1);
+	} else if (pid != 0) {
+		exit(0);
 	}
+	/* child */
 
 #ifdef	LIBWRAP
 	/*