|
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 |
} |