[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ftpd signal diff



this diff changes two things in ftpd. it makes syscalls in the
monitor process restartable when a signal occurs, as was the case
before privsep and it only wait()'s for it's own slave processes now.

please test this and report back to me, even if it doesn't break
anything for you...

thanks,
moritz

Index: ftpcmd.y
===================================================================
RCS file: /cvs/src/libexec/ftpd/ftpcmd.y,v
retrieving revision 1.47
diff -u -r1.47 ftpcmd.y
--- ftpcmd.y	2004/12/06 23:04:14	1.47
+++ ftpcmd.y	2004/12/08 14:58:56
@@ -168,7 +168,7 @@
 
 			/* Terminate unprivileged pre-auth slave */
 			if (quit)
-				_exit(PREAUTH_SLAVE_DIED);
+				_exit(0);
 		}
 	| PORT check_login_epsvall SP host_port CRLF
 		{
Index: monitor.c
===================================================================
RCS file: /cvs/src/libexec/ftpd/monitor.c,v
retrieving revision 1.5
diff -u -r1.5 monitor.c
--- monitor.c	2004/12/06 20:52:04	1.5
+++ monitor.c	2004/12/08 14:58:57
@@ -60,12 +60,10 @@
 int	nullfd;
 pid_t	slave_pid = -1;
 enum monitor_state	state = PREAUTH;
-volatile sig_atomic_t	quit = 0;
 
 void	send_data(int, void *, size_t);
 void	recv_data(int, void *, size_t);
-int	recv_cmd(int, void *, size_t);
-int	handle_cmds(void);
+void	handle_cmds(void);
 void	set_monitor_signals(void);
 void	sig_pass_to_slave(int);
 void	sig_chld(int);
@@ -114,22 +112,6 @@
 	}
 }
 
-/*
- * Receive command from socket and return 1 if something fails.
- * If command was received successfuly, 0 is returned.
- */
-int
-recv_cmd(int sock, void *buf, size_t len)
-{
-	ssize_t n;
-
-	n = read(sock, buf, len);
-	if (n <= 0)
-		return (1);
-
-	return (0);
-}
-
 void
 set_monitor_signals(void)
 {
@@ -137,7 +119,7 @@
 	int i;
 
 	sigfillset(&act.sa_mask);
-	act.sa_flags = 0;
+	act.sa_flags = SA_RESTART;
 
 	act.sa_handler = SIG_DFL;
 	for (i = 1; i < _NSIG; i++)
@@ -207,10 +189,7 @@
 	setproctitle("%s: [priv pre-auth]", remotehost);
 #endif
 
-	if (handle_cmds() == 1) {
-		debugmsg("slave lost. monitor quits now.");
-		_exit(0);
-	}
+	handle_cmds();
 
 	/* User-privileged slave */
 	return (0);
@@ -250,28 +229,24 @@
 }
 
 /*
- * Handles commands received from the slave process. It returns twice.
- * It returns 0 for the user-privileged slave process after successful
- * authentication and 1 if the user-privileged slave died.
+ * Handles commands received from the slave process. It will not return
+ * except in one situation: After successful authentication it will
+ * return as the user-privileged slave process.
  */
-int
+void
 handle_cmds(void)
 {
 	enum monitor_command cmd;
 	enum auth_ret auth;
 	int err, s, slavequit, serrno;
+	pid_t preauth_slave_pid;
 	size_t len;
 	struct sockaddr sa;
 	socklen_t salen;
 	char *name, *pw;
 
-	while (quit == 0) {
-		if (recv_cmd(fd_slave, &cmd, sizeof(cmd)) != 0) {
-			if (quit == 1)
-				break;
-			else
-				continue;
-		}
+	for (;;) {
+		recv_data(fd_slave, &cmd, sizeof(cmd));
 
 		switch (cmd) {
 		case CMD_USER:
@@ -297,6 +272,8 @@
 				recv_data(fd_slave, pw, len);
 			pw[len] = '\0';
 
+			preauth_slave_pid = slave_pid;
+
 			auth = pass(pw);
 			bzero(pw, len);
 			free(pw);
@@ -312,9 +289,8 @@
 			case AUTH_SLAVE:
 				/* User-privileged slave */
 				debugmsg("user-privileged slave started");
-				return (0);
+				return;
 				/* NOTREACHED */
-				break;
 			case AUTH_MONITOR:
 				/* Post-auth monitor */
 				debugmsg("monitor went into post-auth phase");
@@ -327,11 +303,14 @@
 
 				send_data(fd_slave, &slavequit,
 				    sizeof(slavequit));
+
+				while (waitpid(preauth_slave_pid, NULL, 0) < 0
+				    && errno == EINTR)
+					;
 				break;
 			default:
 				fatalx("bad return value from pass()");
 				/* NOTREACHED */
-				break;
 			}
 			break;
 		case CMD_BIND:
@@ -368,11 +347,9 @@
 		default:
 			fatalx("monitor received unknown command %d", cmd);
 			/* NOTREACHED */
-			break;
 		}
 	}
-
-	return (1);
+	/* NOTREACHED */
 }
 
 void
@@ -394,13 +371,10 @@
 	int stat, olderrno = errno;
 
 	do {
-		pid = waitpid(-1, &stat, WNOHANG);
+		pid = waitpid(slave_pid, &stat, WNOHANG);
+		if (pid > 0)
+			_exit(0);
 	} while (pid == -1 && errno == EINTR);
-
-	if (pid == slave_pid && stat != PREAUTH_SLAVE_DIED) {
-		quit = 1;
-		slave_pid = -1;
-	}
 
 	errno = olderrno;
 }
Index: monitor.h
===================================================================
RCS file: /cvs/src/libexec/ftpd/monitor.h,v
retrieving revision 1.1
diff -u -r1.1 monitor.h
--- monitor.h	2004/11/28 18:49:30	1.1
+++ monitor.h	2004/12/08 14:58:57
@@ -20,7 +20,6 @@
 #define _MONITOR_H
 
 #define FTPD_PRIVSEP_USER "_ftp"
-#define PREAUTH_SLAVE_DIED 3
 
 enum auth_ret {
 	AUTH_FAILED,



Visit your host, monkey.org