diff --git a/ChangeLog b/ChangeLog index c189c7810..2bc077cf7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,13 @@ - djm@cvs.openbsd.org 2007/05/17 07:50:31 [log.c] save and restore errno when logging; ok deraadt@ + - djm@cvs.openbsd.org 2007/05/17 07:55:29 + [sftp-server.c] + bz#1286 stop reading and processing commands when input or output buffer + is nearly full, otherwise sftp-server would happily try to grow the + input/output buffers past the maximum supported by the buffer API and + promptly fatal() + based on patch from Thue Janus Kristensen; feedback & ok dtucker@ 20070509 - (tim) [configure.ac] Bug #1287: Add missing test for ucred.h. @@ -2915,4 +2922,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4664 2007/05/20 05:08:15 dtucker Exp $ +$Id: ChangeLog,v 1.4665 2007/05/20 05:09:04 dtucker Exp $ diff --git a/sftp-server.c b/sftp-server.c index d68584b52..76edebc5a 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.72 2007/04/18 01:12:43 stevesk Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.73 2007/05/17 07:55:29 djm Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -1214,7 +1214,7 @@ main(int argc, char **argv) int in, out, max, ch, skipargs = 0, log_stderr = 0; ssize_t len, olen, set_size; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; - char *cp; + char *cp, buf[4*4096]; extern char *optarg; extern char *__progname; @@ -1298,7 +1298,15 @@ main(int argc, char **argv) memset(rset, 0, set_size); memset(wset, 0, set_size); - FD_SET(in, rset); + /* + * Ensure that we can read a full buffer and handle + * the worst-case length packet it can generate, + * otherwise apply backpressure by stopping reads. + */ + if (buffer_check_alloc(&iqueue, sizeof(buf)) && + buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) + FD_SET(in, rset); + olen = buffer_len(&oqueue); if (olen > 0) FD_SET(out, wset); @@ -1312,7 +1320,6 @@ main(int argc, char **argv) /* copy stdin to iqueue */ if (FD_ISSET(in, rset)) { - char buf[4*4096]; len = read(in, buf, sizeof buf); if (len == 0) { debug("read eof"); @@ -1334,7 +1341,13 @@ main(int argc, char **argv) buffer_consume(&oqueue, len); } } - /* process requests from client */ - process(); + + /* + * Process requests from client if we can fit the results + * into the output buffer, otherwise stop processing input + * and let the output queue drain. + */ + if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) + process(); } }