View | Details | Raw Unified | Return to bug 2953 | Differences between
and this patch

Collapse All | Expand All

(-)a/sshd.c (-27 / +80 lines)
Lines 194-202 u_int session_id2_len = 0; Link Here
194
/* record remote hostname or ip */
194
/* record remote hostname or ip */
195
u_int utmp_len = HOST_NAME_MAX+1;
195
u_int utmp_len = HOST_NAME_MAX+1;
196
196
197
/* options.max_startup sized array of fd ints */
197
/*
198
 * startup_pipes/flags are used for tracking children of the listening sshd
199
 * process early in their lifespans. This tracking is needed for three things:
200
 *
201
 * 1) Implementing the MaxStartups limit of concurrent unauthenticated
202
 *    connections.
203
 * 2) Avoiding a race condition for SIGHUP processing, where child processes
204
 *    may have listen_socks open that could collide with main listener process
205
 *    after it restarts.
206
 * 3) Ensuring that rexec'd sshd processes have received their initial state
207
 *    from the parent listen process before handling SIGHUP.
208
 *
209
 * Child processes signal that they have completed closure of the listen_socks
210
 * and (if applicable) received their rexec state by sending a char over their
211
 * sock. Child processes signal that authentication has completed by closing
212
 * the sock (or by exiting).
213
 */
198
static int *startup_pipes = NULL;
214
static int *startup_pipes = NULL;
199
static int startup_pipe;		/* in child */
215
static int *startup_flags = NULL;	/* Indicates child closed listener */
216
static int startup_pipe = -1;		/* in child */
200
217
201
/* variables used for privilege separation */
218
/* variables used for privilege separation */
202
int use_privsep = -1;
219
int use_privsep = -1;
Lines 850-863 server_accept_inetd(int *sock_in, int *sock_out) Link Here
850
{
867
{
851
	int fd;
868
	int fd;
852
869
853
	startup_pipe = -1;
854
	if (rexeced_flag) {
870
	if (rexeced_flag) {
855
		close(REEXEC_CONFIG_PASS_FD);
871
		close(REEXEC_CONFIG_PASS_FD);
856
		*sock_in = *sock_out = dup(STDIN_FILENO);
872
		*sock_in = *sock_out = dup(STDIN_FILENO);
857
		if (!debug_flag) {
858
			startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
859
			close(REEXEC_STARTUP_PIPE_FD);
860
		}
861
	} else {
873
	} else {
862
		*sock_in = dup(STDIN_FILENO);
874
		*sock_in = dup(STDIN_FILENO);
863
		*sock_out = dup(STDOUT_FILENO);
875
		*sock_out = dup(STDOUT_FILENO);
Lines 978-985 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
978
{
990
{
979
	fd_set *fdset;
991
	fd_set *fdset;
980
	int i, j, ret, maxfd;
992
	int i, j, ret, maxfd;
981
	int startups = 0;
993
	int startups = 0, listening = 0, lameduck = 0;
982
	int startup_p[2] = { -1 , -1 };
994
	int startup_p[2] = { -1 , -1 };
995
	char c = 0;
983
	struct sockaddr_storage from;
996
	struct sockaddr_storage from;
984
	socklen_t fromlen;
997
	socklen_t fromlen;
985
	pid_t pid;
998
	pid_t pid;
Lines 992-997 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
992
			maxfd = listen_socks[i];
1005
			maxfd = listen_socks[i];
993
	/* pipes connected to unauthenticated childs */
1006
	/* pipes connected to unauthenticated childs */
994
	startup_pipes = xcalloc(options.max_startups, sizeof(int));
1007
	startup_pipes = xcalloc(options.max_startups, sizeof(int));
1008
	startup_flags = xcalloc(options.max_startups, sizeof(int));
995
	for (i = 0; i < options.max_startups; i++)
1009
	for (i = 0; i < options.max_startups; i++)
996
		startup_pipes[i] = -1;
1010
		startup_pipes[i] = -1;
997
1011
Lines 1000-1007 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1000
	 * the daemon is killed with a signal.
1014
	 * the daemon is killed with a signal.
1001
	 */
1015
	 */
1002
	for (;;) {
1016
	for (;;) {
1003
		if (received_sighup)
1017
		if (received_sighup) {
1004
			sighup_restart();
1018
			if (!lameduck) {
1019
				debug("Received SIGHUP; waiting for children");
1020
				close_listen_socks();
1021
				lameduck = 1;
1022
			}
1023
			if (listening <= 0)
1024
				sighup_restart();
1025
		}
1005
		free(fdset);
1026
		free(fdset);
1006
		fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
1027
		fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
1007
		    sizeof(fd_mask));
1028
		    sizeof(fd_mask));
Lines 1027-1045 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1027
		if (ret < 0)
1048
		if (ret < 0)
1028
			continue;
1049
			continue;
1029
1050
1030
		for (i = 0; i < options.max_startups; i++)
1051
		for (i = 0; i < options.max_startups; i++) {
1031
			if (startup_pipes[i] != -1 &&
1052
			if (startup_pipes[i] == -1 ||
1032
			    FD_ISSET(startup_pipes[i], fdset)) {
1053
			    !FD_ISSET(startup_pipes[i], fdset))
1033
				/*
1054
				continue;
1034
				 * the read end of the pipe is ready
1055
			switch (read(startup_pipes[i], &c, sizeof(c))) {
1035
				 * if the child has closed the pipe
1056
			case -1:
1036
				 * after successful authentication
1057
				if (errno == EINTR || errno == EAGAIN)
1037
				 * or if the child has died
1058
					continue;
1038
				 */
1059
				error("%s: startup pipe %d: read %s",
1060
				    __func__, i, strerror(errno));
1061
				/* FALLTHROUGH */
1062
			case 0:
1063
				/* child exited or completed auth */
1039
				close(startup_pipes[i]);
1064
				close(startup_pipes[i]);
1040
				startup_pipes[i] = -1;
1065
				startup_pipes[i] = -1;
1041
				startups--;
1066
				startups--;
1067
				if (startup_flags[i])
1068
					listening--;
1069
				break;
1070
			case 1:
1071
				/* child has finished preliminaries */
1072
				listening--;
1073
				startup_flags[i] = 0;
1074
				break;
1042
			}
1075
			}
1076
		}
1043
		for (i = 0; i < num_listen_socks; i++) {
1077
		for (i = 0; i < num_listen_socks; i++) {
1044
			if (!FD_ISSET(listen_socks[i], fdset))
1078
			if (!FD_ISSET(listen_socks[i], fdset))
1045
				continue;
1079
				continue;
Lines 1093-1098 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1093
					if (maxfd < startup_p[0])
1127
					if (maxfd < startup_p[0])
1094
						maxfd = startup_p[0];
1128
						maxfd = startup_p[0];
1095
					startups++;
1129
					startups++;
1130
					startup_flags[j] = 1;
1096
					break;
1131
					break;
1097
				}
1132
				}
1098
1133
Lines 1118-1124 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1118
					send_rexec_state(config_s[0], cfg);
1153
					send_rexec_state(config_s[0], cfg);
1119
					close(config_s[0]);
1154
					close(config_s[0]);
1120
				}
1155
				}
1121
				break;
1156
				return;
1122
			}
1157
			}
1123
1158
1124
			/*
1159
			/*
Lines 1126-1138 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1126
			 * the child process the connection. The
1161
			 * the child process the connection. The
1127
			 * parent continues listening.
1162
			 * parent continues listening.
1128
			 */
1163
			 */
1164
			listening++;
1129
			if ((pid = fork()) == 0) {
1165
			if ((pid = fork()) == 0) {
1130
				/*
1166
				/*
1131
				 * Child.  Close the listening and
1167
				 * Child.  Close the listening and
1132
				 * max_startup sockets.  Start using
1168
				 * max_startup sockets.  Start using
1133
				 * the accepted socket. Reinitialize
1169
				 * the accepted socket. Reinitialize
1134
				 * logging (since our pid has changed).
1170
				 * logging (since our pid has changed).
1135
				 * We break out of the loop to handle
1171
				 * We return from this function to handle
1136
				 * the connection.
1172
				 * the connection.
1137
				 */
1173
				 */
1138
				startup_pipe = startup_p[1];
1174
				startup_pipe = startup_p[1];
Lines 1146-1152 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1146
				    log_stderr);
1182
				    log_stderr);
1147
				if (rexec_flag)
1183
				if (rexec_flag)
1148
					close(config_s[0]);
1184
					close(config_s[0]);
1149
				break;
1185
				else {
1186
					/*
1187
					 * Signal parent that the preliminaries
1188
					 * for this child are complete. For the
1189
					 * re-exec case, this happens after the
1190
					 * child has received the rexec state
1191
					 * from the server.
1192
					 */
1193
					(void)atomicio(vwrite, startup_pipe,
1194
					    "\0", 1);
1195
				}
1196
				return;
1150
			}
1197
			}
1151
1198
1152
			/* Parent.  Stay in the loop. */
1199
			/* Parent.  Stay in the loop. */
Lines 1164-1173 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1164
			}
1211
			}
1165
			close(*newsock);
1212
			close(*newsock);
1166
		}
1213
		}
1167
1168
		/* child process check (or debug mode) */
1169
		if (num_listen_socks < 0)
1170
			break;
1171
	}
1214
	}
1172
}
1215
}
1173
1216
Lines 1456-1463 main(int ac, char **av) Link Here
1456
	/* Fetch our configuration */
1499
	/* Fetch our configuration */
1457
	if ((cfg = sshbuf_new()) == NULL)
1500
	if ((cfg = sshbuf_new()) == NULL)
1458
		fatal("%s: sshbuf_new failed", __func__);
1501
		fatal("%s: sshbuf_new failed", __func__);
1459
	if (rexeced_flag)
1502
	if (rexeced_flag) {
1460
		recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg);
1503
		recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg);
1504
		if (!debug_flag) {
1505
			startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
1506
			close(REEXEC_STARTUP_PIPE_FD);
1507
			/*
1508
			 * Signal parent that this child is at a point where
1509
			 * they can go away if they have a SIGHUP pending.
1510
			 */
1511
			(void)atomicio(vwrite, startup_pipe, "\0", 1);
1512
		}
1513
	}
1461
	else if (strcasecmp(config_file_name, "none") != 0)
1514
	else if (strcasecmp(config_file_name, "none") != 0)
1462
		load_server_config(config_file_name, cfg);
1515
		load_server_config(config_file_name, cfg);
1463
1516

Return to bug 2953