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

Collapse All | Expand All

(-)a/ssh-agent.c (-6 / +38 lines)
Lines 967-983 new_socket(sock_type type, int fd) Link Here
967
967
968
static int
968
static int
969
prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
969
prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
970
    struct timeval **tvpp)
970
    u_int *livep, u_int live_max, struct timeval **tvpp)
971
{
971
{
972
	u_int i, sz;
972
	u_int i, sz;
973
	int n = 0;
973
	int n = 0;
974
	static struct timeval tv;
974
	static struct timeval tv;
975
	time_t deadline;
975
	time_t deadline;
976
976
977
	for (i = 0; i < sockets_alloc; i++) {
977
	for (i = *livep = 0; i < sockets_alloc; i++) {
978
		switch (sockets[i].type) {
978
		switch (sockets[i].type) {
979
		case AUTH_SOCKET:
980
		case AUTH_CONNECTION:
979
		case AUTH_CONNECTION:
980
			(*livep)++;
981
			/* FALLTHROUGH */
982
		case AUTH_SOCKET:
981
			n = MAX(n, sockets[i].fd);
983
			n = MAX(n, sockets[i].fd);
982
			break;
984
			break;
983
		case AUTH_UNUSED:
985
		case AUTH_UNUSED:
Lines 988-993 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, Link Here
988
		}
990
		}
989
	}
991
	}
990
992
993
	if (*livep >= live_max)
994
		debug("%s: over fd limit %u >= %u", __func__, *livep, live_max);
995
991
	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
996
	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
992
	if (*fdrp == NULL || sz > *nallocp) {
997
	if (*fdrp == NULL || sz > *nallocp) {
993
		free(*fdrp);
998
		free(*fdrp);
Lines 1005-1010 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, Link Here
1005
	for (i = 0; i < sockets_alloc; i++) {
1010
	for (i = 0; i < sockets_alloc; i++) {
1006
		switch (sockets[i].type) {
1011
		switch (sockets[i].type) {
1007
		case AUTH_SOCKET:
1012
		case AUTH_SOCKET:
1013
			/*
1014
			 * If we are over our FD limit then ignore
1015
			 * new connections until some close.
1016
			 */
1017
			if (*livep >= live_max)
1018
				break;
1019
			/* FALLTHROUGH */
1008
		case AUTH_CONNECTION:
1020
		case AUTH_CONNECTION:
1009
			FD_SET(sockets[i].fd, *fdrp);
1021
			FD_SET(sockets[i].fd, *fdrp);
1010
			if (sshbuf_len(sockets[i].output) > 0)
1022
			if (sshbuf_len(sockets[i].output) > 0)
Lines 1029-1035 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, Link Here
1029
}
1041
}
1030
1042
1031
static void
1043
static void
1032
after_select(fd_set *readset, fd_set *writeset)
1044
after_select(fd_set *readset, fd_set *writeset, u_int *livep, u_int live_max)
1033
{
1045
{
1034
	struct sockaddr_un sunaddr;
1046
	struct sockaddr_un sunaddr;
1035
	socklen_t slen;
1047
	socklen_t slen;
Lines 1046-1051 after_select(fd_set *readset, fd_set *writeset) Link Here
1046
		case AUTH_SOCKET:
1058
		case AUTH_SOCKET:
1047
			if (FD_ISSET(sockets[i].fd, readset)) {
1059
			if (FD_ISSET(sockets[i].fd, readset)) {
1048
				slen = sizeof(sunaddr);
1060
				slen = sizeof(sunaddr);
1061
				if (*livep >= live_max) {
1062
					debug("over FD limit; skipping accept");
1063
					break;
1064
				}
1049
				sock = accept(sockets[i].fd,
1065
				sock = accept(sockets[i].fd,
1050
				    (struct sockaddr *)&sunaddr, &slen);
1066
				    (struct sockaddr *)&sunaddr, &slen);
1051
				if (sock < 0) {
1067
				if (sock < 0) {
Lines 1053-1058 after_select(fd_set *readset, fd_set *writeset) Link Here
1053
					    strerror(errno));
1069
					    strerror(errno));
1054
					break;
1070
					break;
1055
				}
1071
				}
1072
				(*livep)++;
1056
				if (getpeereid(sock, &euid, &egid) < 0) {
1073
				if (getpeereid(sock, &euid, &egid) < 0) {
1057
					error("getpeereid %d failed: %s",
1074
					error("getpeereid %d failed: %s",
1058
					    sock, strerror(errno));
1075
					    sock, strerror(errno));
Lines 1080-1085 after_select(fd_set *readset, fd_set *writeset) Link Here
1080
					continue;
1097
					continue;
1081
				if (len <= 0) {
1098
				if (len <= 0) {
1082
					close_socket(&sockets[i]);
1099
					close_socket(&sockets[i]);
1100
					(*livep)--;
1083
					break;
1101
					break;
1084
				}
1102
				}
1085
				if ((r = sshbuf_consume(sockets[i].output,
1103
				if ((r = sshbuf_consume(sockets[i].output,
Lines 1094-1099 after_select(fd_set *readset, fd_set *writeset) Link Here
1094
					continue;
1112
					continue;
1095
				if (len <= 0) {
1113
				if (len <= 0) {
1096
					close_socket(&sockets[i]);
1114
					close_socket(&sockets[i]);
1115
					(*livep)--;
1097
					break;
1116
					break;
1098
				}
1117
				}
1099
				if ((r = sshbuf_put(sockets[i].input,
1118
				if ((r = sshbuf_put(sockets[i].input,
Lines 1179-1184 main(int ac, char **av) Link Here
1179
	struct timeval *tvp = NULL;
1198
	struct timeval *tvp = NULL;
1180
	size_t len;
1199
	size_t len;
1181
	mode_t prev_mask;
1200
	mode_t prev_mask;
1201
	u_int live = 0, live_max;
1182
1202
1183
	ssh_malloc_init();	/* must be called before any mallocs */
1203
	ssh_malloc_init();	/* must be called before any mallocs */
1184
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1204
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
Lines 1275-1280 main(int ac, char **av) Link Here
1275
	}
1295
	}
1276
	parent_pid = getpid();
1296
	parent_pid = getpid();
1277
1297
1298
	if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
1299
		fatal("%s: getrlimit: %s", __progname, strerror(errno));
1300
	/*
1301
	 * Minimum file descriptors:
1302
	 * stdio (3) + listener (1) + syslog (1 maybe) + connection (1).
1303
	 */
1304
	if (rlim.rlim_cur < (3+1+1+1))
1305
		fatal("%s: file descriptior rlimit %ld too low",
1306
		    __progname, (long)rlim.rlim_cur);
1307
	live_max = rlim.rlim_cur - (3+1+1);
1308
1278
	if (agentsocket == NULL) {
1309
	if (agentsocket == NULL) {
1279
		/* Create private directory for agent socket */
1310
		/* Create private directory for agent socket */
1280
		mktemp_proto(socket_dir, sizeof(socket_dir));
1311
		mktemp_proto(socket_dir, sizeof(socket_dir));
Lines 1390-1396 skip: Link Here
1390
		fatal("%s: pledge: %s", __progname, strerror(errno));
1421
		fatal("%s: pledge: %s", __progname, strerror(errno));
1391
1422
1392
	while (1) {
1423
	while (1) {
1393
		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1424
		prepare_select(&readsetp, &writesetp, &max_fd,
1425
		    &nalloc, &live, live_max, &tvp);
1394
		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1426
		result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1395
		saved_errno = errno;
1427
		saved_errno = errno;
1396
		if (parent_alive_interval != 0)
1428
		if (parent_alive_interval != 0)
Lines 1401-1407 skip: Link Here
1401
				continue;
1433
				continue;
1402
			fatal("select: %s", strerror(saved_errno));
1434
			fatal("select: %s", strerror(saved_errno));
1403
		} else if (result > 0)
1435
		} else if (result > 0)
1404
			after_select(readsetp, writesetp);
1436
			after_select(readsetp, writesetp, &live, live_max);
1405
	}
1437
	}
1406
	/* NOTREACHED */
1438
	/* NOTREACHED */
1407
}
1439
}

Return to bug 2576