You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2015/11/14 15:24:50 UTC

svn commit: r1714333 - in /subversion/trunk/subversion: include/svn_error_codes.h include/svn_ra_svn.h libsvn_ra_svn/deprecated.c libsvn_ra_svn/marshal.c libsvn_ra_svn/ra_svn.h svnserve/serve.c svnserve/server.h svnserve/svnserve.c

Author: stefan2
Date: Sat Nov 14 14:24:50 2015
New Revision: 1714333

URL: http://svn.apache.org/viewvc?rev=1714333&view=rev
Log:
Following up on r1714330, implement a similar limit to svnserve responses.

If --max-response-size is specified and a response exceeds that limit,
it gets truncated and the connetion will be reset.  This allows us to limit
the server load caused by "don't do that" type of requests like exporting
the root of the repository instead of some project branch.

By default, this limit is 0, i.e. inactive.

* subversion/include/svn_error_codes.h
  (SVN_ERR_RA_SVN_RESPONSE_SIZE): New error code.

* subversion/include/svn_ra_svn.h
  (svn_ra_svn_create_conn5): Add another limit parameter.

* subversion/libsvn_ra_svn/ra_svn.h
  (svn_ra_svn_conn_st): Add fields for the new data counter and its limit.

* subversion/libsvn_ra_svn/deprecated.c
  (svn_ra_svn_create_conn4): Update.

* subversion/libsvn_ra_svn/marshal.c
  (svn_ra_svn_create_conn5): Initialize the new struct elements.
  (svn_ra_svn__reset_command_io_counters): One more counter to reset.
  (check_io_limits): One more limit to check.
  (writebuf_output): Count outgoing data and enforce limits.

* subversion/svnserve/server.h
  (serve_params_t): Add field for the new --max-response-size option.

* subversion/svnserve/serve.c
  (serve_interruptable): Pass the new option to the bumped API.

* subversion/svnserve/svnserve.c
  (SVNSERVE_OPT_MAX_RESPONSE): Declare the new option.
  (svnserve__options): Define and document the new option.
  (sub_main): Handle the new option and pass it to the bumped API.

Modified:
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/include/svn_ra_svn.h
    subversion/trunk/subversion/libsvn_ra_svn/deprecated.c
    subversion/trunk/subversion/libsvn_ra_svn/marshal.c
    subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h
    subversion/trunk/subversion/svnserve/serve.c
    subversion/trunk/subversion/svnserve/server.h
    subversion/trunk/subversion/svnserve/svnserve.c

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Sat Nov 14 14:24:50 2015
@@ -1547,6 +1547,11 @@ SVN_ERROR_START
              SVN_ERR_RA_SVN_CATEGORY_START + 9,
              "Client request too long")
 
+  /** @since New in 1.10  */
+  SVN_ERRDEF(SVN_ERR_RA_SVN_RESPONSE_SIZE,
+             SVN_ERR_RA_SVN_CATEGORY_START + 10,
+             "Server response too long")
+
   /* libsvn_auth errors */
 
        /* this error can be used when an auth provider doesn't have

Modified: subversion/trunk/subversion/include/svn_ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_ra_svn.h?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_ra_svn.h (original)
+++ subversion/trunk/subversion/include/svn_ra_svn.h Sat Nov 14 14:24:50 2015
@@ -191,7 +191,10 @@ typedef svn_error_t *(*svn_ra_svn_edit_c
  *
  * If @a max_in is not 0, error out and close the connection whenever more
  * than @a max_in bytes are received for a command (e.g. a client request).
- * The limit enforced may be slightly different, +/- the I/O buffer size. 
+ * If @a max_out is not 0, error out and close the connection whenever more
+ * than @a max_out bytes have been send as response to some command.
+ *
+ * @note The limits enforced may vary slightly by +/- the I/O buffer size. 
  *
  * @note If @a out_stream is an wrapped apr_file_t* the backing file will be
  * used for some operations.
@@ -207,6 +210,7 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
                                            apr_size_t zero_copy_limit,
                                            apr_size_t error_check_interval,
                                            apr_uint64_t max_in,
+                                           apr_uint64_t max_out,
                                            apr_pool_t *result_pool);
 
 

Modified: subversion/trunk/subversion/libsvn_ra_svn/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/deprecated.c?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/deprecated.c Sat Nov 14 14:24:50 2015
@@ -272,7 +272,7 @@ svn_ra_svn_create_conn4(apr_socket_t *so
 {
   return svn_ra_svn_create_conn5(sock, in_stream, out_stream,
                                  compression_level, zero_copy_limit,
-                                 error_check_interval, 0, pool);
+                                 error_check_interval, 0, 0, pool);
 }
 
 svn_ra_svn_conn_t *

Modified: subversion/trunk/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/marshal.c?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/marshal.c Sat Nov 14 14:24:50 2015
@@ -186,6 +186,7 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
                                            apr_size_t zero_copy_limit,
                                            apr_size_t error_check_interval,
                                            apr_uint64_t max_in,
+                                           apr_uint64_t max_out,
                                            apr_pool_t *result_pool)
 {
   svn_ra_svn_conn_t *conn;
@@ -207,6 +208,8 @@ svn_ra_svn_conn_t *svn_ra_svn_create_con
   conn->may_check_for_error = error_check_interval == 0;
   conn->max_in = max_in;
   conn->current_in = 0;
+  conn->max_out = max_out;
+  conn->current_out = 0;
   conn->block_handler = NULL;
   conn->block_baton = NULL;
   conn->capabilities = apr_hash_make(result_pool);
@@ -319,12 +322,13 @@ void
 svn_ra_svn__reset_command_io_counters(svn_ra_svn_conn_t *conn)
 {
   conn->current_in = 0;
+  conn->current_out = 0;
 }
 
 
 /* --- WRITE BUFFER MANAGEMENT --- */
 
-/* Return an error object if CONN exceeded its send limits. */
+/* Return an error object if CONN exceeded its send or receive limits. */
 static svn_error_t *
 check_io_limits(svn_ra_svn_conn_t *conn)
 {
@@ -333,6 +337,11 @@ check_io_limits(svn_ra_svn_conn_t *conn)
                             "The client request size exceeds the "
                             "configured limit");
 
+  if (conn->max_out && (conn->current_out > conn->max_out))
+    return svn_error_create(SVN_ERR_RA_SVN_RESPONSE_SIZE, NULL,
+                            "The server response size exceeds the "
+                            "configured limit");
+
   return SVN_NO_ERROR;
 }
 
@@ -345,6 +354,12 @@ static svn_error_t *writebuf_output(svn_
   apr_pool_t *subpool = NULL;
   svn_ra_svn__session_baton_t *session = conn->session;
 
+  /* Limit the size of the response, if a limit has been configured.
+   * This is to limit the server load in case users e.g. accidentally ran
+   * an export on the root folder. */
+  conn->current_out += len;
+  SVN_ERR(check_io_limits(conn));
+
   while (data < end)
     {
       count = end - data;

Modified: subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/trunk/subversion/libsvn_ra_svn/ra_svn.h Sat Nov 14 14:24:50 2015
@@ -99,6 +99,8 @@ struct svn_ra_svn_conn_st {
   /* I/O limits and tracking */
   apr_uint64_t max_in;
   apr_uint64_t current_in;
+  apr_uint64_t max_out;
+  apr_uint64_t current_out;
 
   /* repository info */
   const char *uuid;

Modified: subversion/trunk/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/serve.c?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/serve.c (original)
+++ subversion/trunk/subversion/svnserve/serve.c Sat Nov 14 14:24:50 2015
@@ -4128,6 +4128,7 @@ serve_interruptable(svn_boolean_t *termi
                                   connection->params->zero_copy_limit,
                                   connection->params->error_check_interval,
                                   connection->params->max_request_size,
+                                  connection->params->max_response_size,
                                   connection->pool);
 
       /* Construct server baton and open the repository for the first time. */

Modified: subversion/trunk/subversion/svnserve/server.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/server.h?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/server.h (original)
+++ subversion/trunk/subversion/svnserve/server.h Sat Nov 14 14:24:50 2015
@@ -155,6 +155,9 @@ typedef struct serve_params_t {
   /* If not 0, error out on requests exceeding this value. */
   apr_uint64_t max_request_size;
 
+  /* If not 0, stop sending a response once it exceeds this value. */
+  apr_uint64_t max_response_size;
+
   /* Use virtual-host-based path to repo. */
   svn_boolean_t vhost;
 } serve_params_t;

Modified: subversion/trunk/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnserve/svnserve.c?rev=1714333&r1=1714332&r2=1714333&view=diff
==============================================================================
--- subversion/trunk/subversion/svnserve/svnserve.c (original)
+++ subversion/trunk/subversion/svnserve/svnserve.c Sat Nov 14 14:24:50 2015
@@ -220,6 +220,7 @@ void winservice_notify_stop(void)
 #define SVNSERVE_OPT_MAX_THREADS     272
 #define SVNSERVE_OPT_BLOCK_READ      273
 #define SVNSERVE_OPT_MAX_REQUEST     274
+#define SVNSERVE_OPT_MAX_RESPONSE    275
 
 /* Text macro because we can't use #ifdef sections inside a N_("...")
    macro expansion. */
@@ -368,6 +369,16 @@ static const apr_getopt_option_t svnserv
         "                             "
         "0 disables the size check; default is "
         APR_STRINGIFY(MAX_REQUEST_SIZE) ".")},
+    {"max-response-size", SVNSERVE_OPT_MAX_RESPONSE, 1,
+     N_("Maximum acceptable server response size in MB.\n"
+        "                             "
+        "Longer responses get truncated and return an\n"
+        "                             "
+        "error.  This limits the server load e.g. when\n"
+        "                             "
+        "checking out at the wrong path level.\n"
+        "                             "
+        "Default is 0 (disabled).")},
     {"foreground",        SVNSERVE_OPT_FOREGROUND, 0,
      N_("run in foreground (useful for debugging)\n"
         "                             "
@@ -752,6 +763,7 @@ sub_main(int *exit_code, int argc, const
   params.zero_copy_limit = 0;
   params.error_check_interval = 4096;
   params.max_request_size = MAX_REQUEST_SIZE * 0x100000;
+  params.max_response_size = 0;
 
   while (1)
     {
@@ -919,6 +931,10 @@ sub_main(int *exit_code, int argc, const
           params.max_request_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
           break;
 
+        case SVNSERVE_OPT_MAX_RESPONSE:
+          params.max_response_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
+          break;
+
         case SVNSERVE_OPT_MIN_THREADS:
           min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
           break;
@@ -1072,6 +1088,7 @@ sub_main(int *exit_code, int argc, const
                                      params.zero_copy_limit,
                                      params.error_check_interval,
                                      params.max_request_size,
+                                     params.max_response_size,
                                      connection_pool);
       err = serve(conn, &params, connection_pool);
       svn_pool_destroy(connection_pool);