diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | ssh-agent.c | 36 |
2 files changed, 22 insertions, 21 deletions
@@ -73,6 +73,13 @@ | |||
73 | - djm@cvs.openbsd.org 2009/08/31 21:01:29 | 73 | - djm@cvs.openbsd.org 2009/08/31 21:01:29 |
74 | [sftp-server.8] | 74 | [sftp-server.8] |
75 | document -e and -h; prodded by jmc@ | 75 | document -e and -h; prodded by jmc@ |
76 | - djm@cvs.openbsd.org 2009/09/01 14:43:17 | ||
77 | [ssh-agent.c] | ||
78 | fix a race condition in ssh-agent that could result in a wedged or | ||
79 | spinning agent: don't read off the end of the allocated fd_sets, and | ||
80 | don't issue blocking read/write on agent sockets - just fall back to | ||
81 | select() on retriable read/write errors. bz#1633 reported and tested | ||
82 | by "noodle10000 AT googlemail.com"; ok dtucker@ markus@ | ||
76 | 83 | ||
77 | 20091002 | 84 | 20091002 |
78 | - (djm) [Makefile.in] Mention readconf.o in ssh-keysign's make deps. | 85 | - (djm) [Makefile.in] Mention readconf.o in ssh-keysign's make deps. |
diff --git a/ssh-agent.c b/ssh-agent.c index f77dea3a6..df3a87d9a 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.161 2009/03/23 19:38:04 tobias Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.162 2009/09/01 14:43:17 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -919,11 +919,11 @@ after_select(fd_set *readset, fd_set *writeset) | |||
919 | socklen_t slen; | 919 | socklen_t slen; |
920 | char buf[1024]; | 920 | char buf[1024]; |
921 | int len, sock; | 921 | int len, sock; |
922 | u_int i; | 922 | u_int i, orig_alloc; |
923 | uid_t euid; | 923 | uid_t euid; |
924 | gid_t egid; | 924 | gid_t egid; |
925 | 925 | ||
926 | for (i = 0; i < sockets_alloc; i++) | 926 | for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++) |
927 | switch (sockets[i].type) { | 927 | switch (sockets[i].type) { |
928 | case AUTH_UNUSED: | 928 | case AUTH_UNUSED: |
929 | break; | 929 | break; |
@@ -956,16 +956,13 @@ after_select(fd_set *readset, fd_set *writeset) | |||
956 | case AUTH_CONNECTION: | 956 | case AUTH_CONNECTION: |
957 | if (buffer_len(&sockets[i].output) > 0 && | 957 | if (buffer_len(&sockets[i].output) > 0 && |
958 | FD_ISSET(sockets[i].fd, writeset)) { | 958 | FD_ISSET(sockets[i].fd, writeset)) { |
959 | do { | 959 | len = write(sockets[i].fd, |
960 | len = write(sockets[i].fd, | 960 | buffer_ptr(&sockets[i].output), |
961 | buffer_ptr(&sockets[i].output), | 961 | buffer_len(&sockets[i].output)); |
962 | buffer_len(&sockets[i].output)); | 962 | if (len == -1 && (errno == EAGAIN || |
963 | if (len == -1 && (errno == EAGAIN || | 963 | errno == EWOULDBLOCK || |
964 | errno == EINTR || | 964 | errno == EINTR)) |
965 | errno == EWOULDBLOCK)) | 965 | continue; |
966 | continue; | ||
967 | break; | ||
968 | } while (1); | ||
969 | if (len <= 0) { | 966 | if (len <= 0) { |
970 | close_socket(&sockets[i]); | 967 | close_socket(&sockets[i]); |
971 | break; | 968 | break; |
@@ -973,14 +970,11 @@ after_select(fd_set *readset, fd_set *writeset) | |||
973 | buffer_consume(&sockets[i].output, len); | 970 | buffer_consume(&sockets[i].output, len); |
974 | } | 971 | } |
975 | if (FD_ISSET(sockets[i].fd, readset)) { | 972 | if (FD_ISSET(sockets[i].fd, readset)) { |
976 | do { | 973 | len = read(sockets[i].fd, buf, sizeof(buf)); |
977 | len = read(sockets[i].fd, buf, sizeof(buf)); | 974 | if (len == -1 && (errno == EAGAIN || |
978 | if (len == -1 && (errno == EAGAIN || | 975 | errno == EWOULDBLOCK || |
979 | errno == EINTR || | 976 | errno == EINTR)) |
980 | errno == EWOULDBLOCK)) | 977 | continue; |
981 | continue; | ||
982 | break; | ||
983 | } while (1); | ||
984 | if (len <= 0) { | 978 | if (len <= 0) { |
985 | close_socket(&sockets[i]); | 979 | close_socket(&sockets[i]); |
986 | break; | 980 | break; |