[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#781718: unblock: subversion/1.8.10-6



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package subversion

This uploaded backports fixes for 3 recent CVEs.

$ debdiff subversion_1.8.10-5.dsc subversion_1.8.10-6.dsc
diffstat for subversion_1.8.10-5 subversion_1.8.10-6

 debian/patches/CVE-2015-0202            |  474 ++++++++++++++++++++++++++++++++
 debian/patches/CVE-2015-0248            |  105 +++++++
 debian/patches/CVE-2015-0251            |   62 ++++
 subversion-1.8.10/debian/changelog      |   11 
 subversion-1.8.10/debian/patches/series |    3 
 5 files changed, 655 insertions(+)

diff -u subversion-1.8.10/debian/changelog subversion-1.8.10/debian/changelog
--- subversion-1.8.10/debian/changelog
+++ subversion-1.8.10/debian/changelog
@@ -1,3 +1,14 @@
+subversion (1.8.10-6) unstable; urgency=high
+
+  * patches/CVE-2015-0202: Excessive memory use with certain REPORT requests
+    against mod_dav_svn with FSFS repositories
+  * patches/CVE-2015-0248: Assertion DoS vulnerability for certain mod_dav_svn
+    and svnserve requests with dynamically evaluated revision numbers
+  * patches/CVE-2015-0251: mod_dav_svn allows spoofing svn:author property
+    values for new revisions
+
+ -- James McCoy <jamessan@debian.org>  Tue, 31 Mar 2015 22:51:18 -0400
+
 subversion (1.8.10-5) unstable; urgency=medium
 
   * patches/CVE-2014-8108: mod_dav_svn DoS vulnerability with invalid virtual
diff -u subversion-1.8.10/debian/patches/series subversion-1.8.10/debian/patches/series
--- subversion-1.8.10/debian/patches/series
+++ subversion-1.8.10/debian/patches/series
@@ -21,0 +22,3 @@
+CVE-2015-0251
+CVE-2015-0248
+CVE-2015-0202
only in patch2:
unchanged:
--- subversion-1.8.10.orig/debian/patches/CVE-2015-0202
+++ subversion-1.8.10/debian/patches/CVE-2015-0202
@@ -0,0 +1,474 @@
+Index: subversion/libsvn_fs_fs/tree.c
+===================================================================
+--- a/subversion/libsvn_fs_fs/tree.c	(revision 1655679)
++++ b/subversion/libsvn_fs_fs/tree.c	(working copy)
+@@ -127,7 +127,6 @@ typedef struct fs_txn_root_data_t
+ static svn_error_t * get_dag(dag_node_t **dag_node_p,
+                              svn_fs_root_t *root,
+                              const char *path,
+-                             svn_boolean_t needs_lock_cache,
+                              apr_pool_t *pool);
+ 
+ static svn_fs_root_t *make_revision_root(svn_fs_t *fs, svn_revnum_t rev,
+@@ -178,34 +177,10 @@ typedef struct cache_entry_t
+  */
+ enum { BUCKET_COUNT = 256 };
+ 
+-/* Each pool that has received a DAG node, will hold at least on lock on
+-   our cache to ensure that the node remains valid despite being allocated
+-   in the cache's pool.  This is the structure to represent the lock.
+- */
+-typedef struct cache_lock_t
+-{
+-  /* pool holding the lock */
+-  apr_pool_t *pool;
+-
+-  /* cache being locked */
+-  fs_fs_dag_cache_t *cache;
+-
+-  /* next lock. NULL at EOL */
+-  struct cache_lock_t *next;
+-
+-  /* previous lock. NULL at list head. Only then this==cache->first_lock */
+-  struct cache_lock_t *prev;
+-} cache_lock_t;
+-
+ /* The actual cache structure.  All nodes will be allocated in POOL.
+    When the number of INSERTIONS (i.e. objects created form that pool)
+    exceeds a certain threshold, the pool will be cleared and the cache
+    with it.
+-
+-   To ensure that nodes returned from this structure remain valid, the
+-   cache will get locked for the lifetime of the _receiving_ pools (i.e.
+-   those in which we would allocate the node if there was no cache.).
+-   The cache will only be cleared FIRST_LOCK is 0.
+  */
+ struct fs_fs_dag_cache_t
+ {
+@@ -221,47 +196,8 @@ struct fs_fs_dag_cache_t
+   /* Property lookups etc. have a very high locality (75% re-hit).
+      Thus, remember the last hit location for optimistic lookup. */
+   apr_size_t last_hit;
+-
+-  /* List of receiving pools that are still alive. */
+-  cache_lock_t *first_lock;
+ };
+ 
+-/* Cleanup function to be called when a receiving pool gets cleared.
+-   Unlocks the cache once.
+- */
+-static apr_status_t
+-unlock_cache(void *baton_void)
+-{
+-  cache_lock_t *lock = baton_void;
+-
+-  /* remove lock from chain. Update the head */
+-  if (lock->next)
+-    lock->next->prev = lock->prev;
+-  if (lock->prev)
+-    lock->prev->next = lock->next;
+-  else
+-    lock->cache->first_lock = lock->next;
+-
+-  return APR_SUCCESS;
+-}
+-
+-/* Cleanup function to be called when the cache itself gets destroyed.
+-   In that case, we must unregister all unlock requests.
+- */
+-static apr_status_t
+-unregister_locks(void *baton_void)
+-{
+-  fs_fs_dag_cache_t *cache = baton_void;
+-  cache_lock_t *lock;
+-
+-  for (lock = cache->first_lock; lock; lock = lock->next)
+-    apr_pool_cleanup_kill(lock->pool,
+-                          lock,
+-                          unlock_cache);
+-
+-  return APR_SUCCESS;
+-}
+-
+ fs_fs_dag_cache_t*
+ svn_fs_fs__create_dag_cache(apr_pool_t *pool)
+ {
+@@ -268,59 +204,15 @@ svn_fs_fs__create_dag_cache(apr_pool_t *pool)
+   fs_fs_dag_cache_t *result = apr_pcalloc(pool, sizeof(*result));
+   result->pool = svn_pool_create(pool);
+ 
+-  apr_pool_cleanup_register(pool,
+-                            result,
+-                            unregister_locks,
+-                            apr_pool_cleanup_null);
+-
+   return result;
+ }
+ 
+-/* Prevent the entries in CACHE from being destroyed, for as long as the
+-   POOL lives.
+- */
+-static void
+-lock_cache(fs_fs_dag_cache_t* cache, apr_pool_t *pool)
+-{
+-  /* we only need to lock / unlock once per pool.  Since we will often ask
+-     for multiple nodes with the same pool, we can reduce the overhead.
+-     However, if e.g. pools are being used in an alternating pattern,
+-     we may lock the cache more than once for the same pool (and register
+-     just as many cleanup actions).
+-   */
+-  cache_lock_t *lock = cache->first_lock;
+-
+-  /* try to find an existing lock for POOL.
+-     But limit the time spent on chasing pointers.  */
+-  int limiter = 8;
+-  while (lock && --limiter)
+-      if (lock->pool == pool)
+-        return;
+-
+-  /* create a new lock and put it at the beginning of the lock chain */
+-  lock = apr_palloc(pool, sizeof(*lock));
+-  lock->cache = cache;
+-  lock->pool = pool;
+-  lock->next = cache->first_lock;
+-  lock->prev = NULL;
+-
+-  if (cache->first_lock)
+-    cache->first_lock->prev = lock;
+-  cache->first_lock = lock;
+-
+-  /* instruct POOL to remove the look upon cleanup */
+-  apr_pool_cleanup_register(pool,
+-                            lock,
+-                            unlock_cache,
+-                            apr_pool_cleanup_null);
+-}
+-
+ /* Clears the CACHE at regular intervals (destroying all cached nodes)
+  */
+ static void
+ auto_clear_dag_cache(fs_fs_dag_cache_t* cache)
+ {
+-  if (cache->first_lock == NULL && cache->insertions > BUCKET_COUNT)
++  if (cache->insertions > BUCKET_COUNT)
+     {
+       svn_pool_clear(cache->pool);
+ 
+@@ -433,18 +325,12 @@ locate_cache(svn_cache__t **cache,
+     }
+ }
+ 
+-/* Return NODE for PATH from ROOT's node cache, or NULL if the node
+-   isn't cached; read it from the FS. *NODE remains valid until either
+-   POOL or the FS gets cleared or destroyed (whichever comes first).
+-
+-   Since locking can be expensive and POOL may be long-living, for
+-   nodes that will not need to survive the next call to this function,
+-   set NEEDS_LOCK_CACHE to FALSE. */
++/* Return NODE_P for PATH from ROOT's node cache, or NULL if the node
++   isn't cached; read it from the FS. *NODE_P is allocated in POOL. */
+ static svn_error_t *
+ dag_node_cache_get(dag_node_t **node_p,
+                    svn_fs_root_t *root,
+                    const char *path,
+-                   svn_boolean_t needs_lock_cache,
+                    apr_pool_t *pool)
+ {
+   svn_boolean_t found;
+@@ -466,25 +352,23 @@ dag_node_cache_get(dag_node_t **node_p,
+       if (bucket->node == NULL)
+         {
+           locate_cache(&cache, &key, root, path, pool);
+-          SVN_ERR(svn_cache__get((void **)&node, &found, cache, key,
+-                                 ffd->dag_node_cache->pool));
++          SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool));
+           if (found && node)
+             {
+               /* Patch up the FS, since this might have come from an old FS
+               * object. */
+               svn_fs_fs__dag_set_fs(node, root->fs);
+-              bucket->node = node;
++
++              /* Retain the DAG node in L1 cache. */
++              bucket->node = svn_fs_fs__dag_dup(node,
++                                                ffd->dag_node_cache->pool);
+             }
+         }
+       else
+         {
+-          node = bucket->node;
++          /* Copy the node from L1 cache into the passed-in POOL. */
++          node = svn_fs_fs__dag_dup(bucket->node, pool);
+         }
+-
+-      /* if we found a node, make sure it remains valid at least as long
+-         as it would when allocated in POOL. */
+-      if (node && needs_lock_cache)
+-        lock_cache(ffd->dag_node_cache, pool);
+     }
+   else
+     {
+@@ -822,7 +706,7 @@ get_copy_inheritance(copy_id_inherit_t *inherit_p,
+   SVN_ERR(svn_fs_fs__dag_get_copyroot(&copyroot_rev, &copyroot_path,
+                                       child->node));
+   SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev, pool));
+-  SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, FALSE, pool));
++  SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
+   copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
+ 
+   if (svn_fs_fs__id_compare(copyroot_id, child_id) == -1)
+@@ -938,7 +822,7 @@ open_path(parent_path_t **parent_path_p,
+     {
+       directory = svn_dirent_dirname(path, pool);
+       if (directory[1] != 0) /* root nodes are covered anyway */
+-        SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
++        SVN_ERR(dag_node_cache_get(&here, root, directory, pool));
+     }
+ 
+   /* did the shortcut work? */
+@@ -998,8 +882,8 @@ open_path(parent_path_t **parent_path_p,
+              element if we already know the lookup to fail for the
+              complete path. */
+           if (next || !(flags & open_path_uncached))
+-            SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far,
+-                                       TRUE, pool));
++            SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, pool));
++
+           if (cached_node)
+             child = cached_node;
+           else
+@@ -1136,8 +1020,7 @@ make_path_mutable(svn_fs_root_t *root,
+                                           parent_path->node));
+       SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, root->fs,
+                                        copyroot_rev, pool));
+-      SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path,
+-                      FALSE, pool));
++      SVN_ERR(get_dag(&copyroot_node, copyroot_root, copyroot_path, pool));
+ 
+       child_id = svn_fs_fs__dag_get_id(parent_path->node);
+       copyroot_id = svn_fs_fs__dag_get_id(copyroot_node);
+@@ -1174,16 +1057,11 @@ make_path_mutable(svn_fs_root_t *root,
+ 
+ /* Open the node identified by PATH in ROOT.  Set DAG_NODE_P to the
+    node we find, allocated in POOL.  Return the error
+-   SVN_ERR_FS_NOT_FOUND if this node doesn't exist.
+-
+-   Since locking can be expensive and POOL may be long-living, for
+-   nodes that will not need to survive the next call to this function,
+-   set NEEDS_LOCK_CACHE to FALSE. */
++   SVN_ERR_FS_NOT_FOUND if this node doesn't exist. */
+ static svn_error_t *
+ get_dag(dag_node_t **dag_node_p,
+         svn_fs_root_t *root,
+         const char *path,
+-        svn_boolean_t needs_lock_cache,
+         apr_pool_t *pool)
+ {
+   parent_path_t *parent_path;
+@@ -1192,7 +1070,7 @@ get_dag(dag_node_t **dag_node_p,
+   /* First we look for the DAG in our cache
+      (if the path may be canonical). */
+   if (*path == '/')
+-    SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache, pool));
++    SVN_ERR(dag_node_cache_get(&node, root, path, pool));
+ 
+   if (! node)
+     {
+@@ -1202,8 +1080,7 @@ get_dag(dag_node_t **dag_node_p,
+           path = svn_fs__canonicalize_abspath(path, pool);
+ 
+           /* Try again with the corrected path. */
+-          SVN_ERR(dag_node_cache_get(&node, root, path, needs_lock_cache,
+-                                     pool));
++          SVN_ERR(dag_node_cache_get(&node, root, path, pool));
+         }
+ 
+       if (! node)
+@@ -1281,7 +1158,7 @@ svn_fs_fs__node_id(const svn_fs_id_t **id_p,
+     {
+       dag_node_t *node;
+ 
+-      SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++      SVN_ERR(get_dag(&node, root, path, pool));
+       *id_p = svn_fs_fs__id_copy(svn_fs_fs__dag_get_id(node), pool);
+     }
+   return SVN_NO_ERROR;
+@@ -1296,7 +1173,7 @@ svn_fs_fs__node_created_rev(svn_revnum_t *revision
+ {
+   dag_node_t *node;
+ 
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+   return svn_fs_fs__dag_get_revision(revision, node, pool);
+ }
+ 
+@@ -1311,7 +1188,7 @@ fs_node_created_path(const char **created_path,
+ {
+   dag_node_t *node;
+ 
+-  SVN_ERR(get_dag(&node, root, path, TRUE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+   *created_path = svn_fs_fs__dag_get_created_path(node);
+ 
+   return SVN_NO_ERROR;
+@@ -1375,7 +1252,7 @@ fs_node_prop(svn_string_t **value_p,
+   dag_node_t *node;
+   apr_hash_t *proplist;
+ 
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+   SVN_ERR(svn_fs_fs__dag_get_proplist(&proplist, node, pool));
+   *value_p = NULL;
+   if (proplist)
+@@ -1398,7 +1275,7 @@ fs_node_proplist(apr_hash_t **table_p,
+   apr_hash_t *table;
+   dag_node_t *node;
+ 
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+   SVN_ERR(svn_fs_fs__dag_get_proplist(&table, node, pool));
+   *table_p = table ? table : apr_hash_make(pool);
+ 
+@@ -1515,8 +1392,8 @@ fs_props_changed(svn_boolean_t *changed_p,
+       (SVN_ERR_FS_GENERAL, NULL,
+        _("Cannot compare property value between two different filesystems"));
+ 
+-  SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
+-  SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
++  SVN_ERR(get_dag(&node1, root1, path1, pool));
++  SVN_ERR(get_dag(&node2, root2, path2, pool));
+   return svn_fs_fs__dag_things_different(changed_p, NULL,
+                                          node1, node2);
+ }
+@@ -1529,7 +1406,7 @@ fs_props_changed(svn_boolean_t *changed_p,
+ static svn_error_t *
+ get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool)
+ {
+-  return get_dag(node, root, "/", TRUE, pool);
++  return get_dag(node, root, "/", pool);
+ }
+ 
+ 
+@@ -2193,7 +2070,7 @@ fs_dir_entries(apr_hash_t **table_p,
+   dag_node_t *node;
+ 
+   /* Get the entries for this path in the caller's pool. */
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+   return svn_fs_fs__dag_dir_entries(table_p, node, pool);
+ }
+ 
+@@ -2365,7 +2242,7 @@ copy_helper(svn_fs_root_t *from_root,
+        _("Copy from mutable tree not currently supported"));
+ 
+   /* Get the NODE for FROM_PATH in FROM_ROOT.*/
+-  SVN_ERR(get_dag(&from_node, from_root, from_path, TRUE, pool));
++  SVN_ERR(get_dag(&from_node, from_root, from_path, pool));
+ 
+   /* Build up the parent path from TO_PATH in TO_ROOT.  If the last
+      component does not exist, it's not that big a deal.  We'll just
+@@ -2442,7 +2319,7 @@ copy_helper(svn_fs_root_t *from_root,
+                                             pool));
+ 
+       /* Make a record of this modification in the changes table. */
+-      SVN_ERR(get_dag(&new_node, to_root, to_path, TRUE, pool));
++      SVN_ERR(get_dag(&new_node, to_root, to_path, pool));
+       SVN_ERR(add_change(to_root->fs, txn_id, to_path,
+                          svn_fs_fs__dag_get_id(new_node), kind, FALSE, FALSE,
+                          svn_fs_fs__dag_node_kind(from_node),
+@@ -2553,7 +2430,7 @@ fs_copied_from(svn_revnum_t *rev_p,
+     {
+       /* There is no cached entry, look it up the old-fashioned
+          way. */
+-      SVN_ERR(get_dag(&node, root, path, TRUE, pool));
++      SVN_ERR(get_dag(&node, root, path, pool));
+       SVN_ERR(svn_fs_fs__dag_get_copyfrom_rev(&copyfrom_rev, node));
+       SVN_ERR(svn_fs_fs__dag_get_copyfrom_path(&copyfrom_path, node));
+     }
+@@ -2628,7 +2505,7 @@ fs_file_length(svn_filesize_t *length_p,
+   dag_node_t *file;
+ 
+   /* First create a dag_node_t from the root/path pair. */
+-  SVN_ERR(get_dag(&file, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&file, root, path, pool));
+ 
+   /* Now fetch its length */
+   return svn_fs_fs__dag_file_length(length_p, file, pool);
+@@ -2647,7 +2524,7 @@ fs_file_checksum(svn_checksum_t **checksum,
+ {
+   dag_node_t *file;
+ 
+-  SVN_ERR(get_dag(&file, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&file, root, path, pool));
+   return svn_fs_fs__dag_file_checksum(checksum, file, kind, pool);
+ }
+ 
+@@ -2666,7 +2543,7 @@ fs_file_contents(svn_stream_t **contents,
+   svn_stream_t *file_stream;
+ 
+   /* First create a dag_node_t from the root/path pair. */
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+ 
+   /* Then create a readable stream from the dag_node_t. */
+   SVN_ERR(svn_fs_fs__dag_get_contents(&file_stream, node, pool));
+@@ -2689,7 +2566,7 @@ fs_try_process_file_contents(svn_boolean_t *succes
+                              apr_pool_t *pool)
+ {
+   dag_node_t *node;
+-  SVN_ERR(get_dag(&node, root, path, FALSE, pool));
++  SVN_ERR(get_dag(&node, root, path, pool));
+ 
+   return svn_fs_fs__dag_try_process_file_contents(success, node,
+                                                   processor, baton, pool);
+@@ -3071,8 +2948,8 @@ fs_contents_changed(svn_boolean_t *changed_p,
+         (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2);
+   }
+ 
+-  SVN_ERR(get_dag(&node1, root1, path1, TRUE, pool));
+-  SVN_ERR(get_dag(&node2, root2, path2, TRUE, pool));
++  SVN_ERR(get_dag(&node1, root1, path1, pool));
++  SVN_ERR(get_dag(&node2, root2, path2, pool));
+   return svn_fs_fs__dag_things_different(NULL, changed_p,
+                                          node1, node2);
+ }
+@@ -3092,10 +2969,10 @@ fs_get_file_delta_stream(svn_txdelta_stream_t **st
+   dag_node_t *source_node, *target_node;
+ 
+   if (source_root && source_path)
+-    SVN_ERR(get_dag(&source_node, source_root, source_path, TRUE, pool));
++    SVN_ERR(get_dag(&source_node, source_root, source_path, pool));
+   else
+     source_node = NULL;
+-  SVN_ERR(get_dag(&target_node, target_root, target_path, TRUE, pool));
++  SVN_ERR(get_dag(&target_node, target_root, target_path, pool));
+ 
+   /* Create a delta stream that turns the source into the target.  */
+   return svn_fs_fs__dag_get_file_delta_stream(stream_p, source_node,
+@@ -3588,7 +3465,7 @@ history_prev(void *baton, apr_pool_t *pool)
+ 
+       SVN_ERR(svn_fs_fs__revision_root(&copyroot_root, fs, copyroot_rev,
+                                        pool));
+-      SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, FALSE, pool));
++      SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, pool));
+       copy_dst = svn_fs_fs__dag_get_created_path(node);
+ 
+       /* If our current path was the very destination of the copy,
+@@ -3785,7 +3662,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *r
+       svn_pool_clear(iterpool);
+ 
+       kid_path = svn_fspath__join(this_path, dirent->name, iterpool);
+-      SVN_ERR(get_dag(&kid_dag, root, kid_path, TRUE, iterpool));
++      SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool));
+ 
+       SVN_ERR(svn_fs_fs__dag_has_mergeinfo(&has_mergeinfo, kid_dag));
+       SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down, kid_dag));
+@@ -4031,7 +3908,7 @@ add_descendant_mergeinfo(svn_mergeinfo_catalog_t r
+   dag_node_t *this_dag;
+   svn_boolean_t go_down;
+ 
+-  SVN_ERR(get_dag(&this_dag, root, path, TRUE, scratch_pool));
++  SVN_ERR(get_dag(&this_dag, root, path, scratch_pool));
+   SVN_ERR(svn_fs_fs__dag_has_descendants_with_mergeinfo(&go_down,
+                                                         this_dag));
+   if (go_down)
only in patch2:
unchanged:
--- subversion-1.8.10.orig/debian/patches/CVE-2015-0248
+++ subversion-1.8.10/debian/patches/CVE-2015-0248
@@ -0,0 +1,105 @@
+--- a/subversion/mod_dav_svn/reports/get-location-segments.c
++++ b/subversion/mod_dav_svn/reports/get-location-segments.c
+@@ -181,17 +181,36 @@
+                                   "Not all parameters passed.",
+                                   SVN_DAV_ERROR_NAMESPACE,
+                                   SVN_DAV_ERROR_TAG);
+-  if (SVN_IS_VALID_REVNUM(start_rev)
+-      && SVN_IS_VALID_REVNUM(end_rev)
+-      && (end_rev > start_rev))
++
++  /* No START_REV or PEG_REVISION?  We'll use HEAD. */
++  if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision))
++    {
++      svn_revnum_t youngest;
++
++      serr = svn_fs_youngest_rev(&youngest, resource->info->repos->fs,
++                                 resource->pool);
++      if (serr != NULL)
++        return dav_svn__convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
++                                    "Could not determine youngest revision",
++                                    resource->pool);
++
++      if (!SVN_IS_VALID_REVNUM(start_rev))
++        start_rev = youngest;
++      if (!SVN_IS_VALID_REVNUM(peg_revision))
++        peg_revision = youngest;
++    }
++
++  /* No END_REV?  We'll use 0. */
++  if (!SVN_IS_VALID_REVNUM(end_rev))
++    end_rev = 0;
++
++  if (end_rev > start_rev)
+     return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
+                                   "End revision must not be younger than "
+                                   "start revision",
+                                   SVN_DAV_ERROR_NAMESPACE,
+                                   SVN_DAV_ERROR_TAG);
+-  if (SVN_IS_VALID_REVNUM(peg_revision)
+-      && SVN_IS_VALID_REVNUM(start_rev)
+-      && (start_rev > peg_revision))
++  if (start_rev > peg_revision)
+     return dav_svn__new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
+                                   "Start revision must not be younger than "
+                                   "peg revision",
+--- a/subversion/svnserve/serve.c
++++ b/subversion/svnserve/serve.c
+@@ -2465,9 +2465,30 @@
+ 
+   abs_path = svn_fspath__join(b->fs_path->data, relative_path, pool);
+ 
+-  if (SVN_IS_VALID_REVNUM(start_rev)
+-      && SVN_IS_VALID_REVNUM(end_rev)
+-      && (end_rev > start_rev))
++  SVN_ERR(trivial_auth_request(conn, pool, b));
++  SVN_ERR(log_command(baton, conn, pool, "%s",
++                      svn_log__get_location_segments(abs_path, peg_revision,
++                                                     start_rev, end_rev,
++                                                     pool)));
++
++  /* No START_REV or PEG_REVISION?  We'll use HEAD. */
++  if (!SVN_IS_VALID_REVNUM(start_rev) || !SVN_IS_VALID_REVNUM(peg_revision))
++    {
++      svn_revnum_t youngest;
++
++      SVN_CMD_ERR(svn_fs_youngest_rev(&youngest, b->fs, pool));
++
++      if (!SVN_IS_VALID_REVNUM(start_rev))
++        start_rev = youngest;
++      if (!SVN_IS_VALID_REVNUM(peg_revision))
++        peg_revision = youngest;
++    }
++
++  /* No END_REV?  We'll use 0. */
++  if (!SVN_IS_VALID_REVNUM(end_rev))
++    end_rev = 0;
++
++  if (end_rev > start_rev)
+     {
+       err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                               "Get-location-segments end revision must not be "
+@@ -2475,9 +2496,7 @@
+       return log_fail_and_flush(err, b, conn, pool);
+     }
+ 
+-  if (SVN_IS_VALID_REVNUM(peg_revision)
+-      && SVN_IS_VALID_REVNUM(start_rev)
+-      && (start_rev > peg_revision))
++  if (start_rev > peg_revision)
+     {
+       err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                               "Get-location-segments start revision must not "
+@@ -2485,12 +2504,6 @@
+       return log_fail_and_flush(err, b, conn, pool);
+     }
+ 
+-  SVN_ERR(trivial_auth_request(conn, pool, b));
+-  SVN_ERR(log_command(baton, conn, pool, "%s",
+-                      svn_log__get_location_segments(abs_path, peg_revision,
+-                                                     start_rev, end_rev,
+-                                                     pool)));
+-
+   /* All the parameters are fine - let's perform the query against the
+    * repository. */
+ 
only in patch2:
unchanged:
--- subversion-1.8.10.orig/debian/patches/CVE-2015-0251
+++ subversion-1.8.10/debian/patches/CVE-2015-0251
@@ -0,0 +1,62 @@
+Index: subversion/mod_dav_svn/deadprops.c
+===================================================================
+--- a/subversion/mod_dav_svn/deadprops.c	(revision 1660122)
++++ b/subversion/mod_dav_svn/deadprops.c	(working copy)
+@@ -163,6 +163,23 @@ get_value(dav_db *db, const dav_prop_name *name, s
+ }
+ 
+ 
++static svn_error_t *
++change_txn_prop(svn_fs_txn_t *txn,
++                const char *propname,
++                const svn_string_t *value,
++                apr_pool_t *scratch_pool)
++{
++  if (strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0)
++    return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
++                            "Attempted to modify 'svn:author' property "
++                            "on a transaction");
++
++  SVN_ERR(svn_repos_fs_change_txn_prop(txn, propname, value, scratch_pool));
++
++  return SVN_NO_ERROR;
++}
++
++
+ static dav_error *
+ save_value(dav_db *db, const dav_prop_name *name,
+            const svn_string_t *const *old_value_p,
+@@ -213,9 +230,8 @@ save_value(dav_db *db, const dav_prop_name *name,
+     {
+       if (resource->working)
+         {
+-          serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
+-                                              propname, value,
+-                                              subpool);
++          serr = change_txn_prop(resource->info->root.txn, propname,
++                                 value, subpool);
+         }
+       else
+         {
+@@ -254,8 +270,8 @@ save_value(dav_db *db, const dav_prop_name *name,
+     }
+   else if (resource->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION)
+     {
+-      serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
+-                                          propname, value, subpool);
++      serr = change_txn_prop(resource->info->root.txn, propname,
++                             value, subpool);
+     }
+   else
+     {
+@@ -560,8 +576,8 @@ db_remove(dav_db *db, const dav_prop_name *name)
+   /* Working Baseline or Working (Version) Resource */
+   if (db->resource->baselined)
+     if (db->resource->working)
+-      serr = svn_repos_fs_change_txn_prop(db->resource->info->root.txn,
+-                                          propname, NULL, subpool);
++      serr = change_txn_prop(db->resource->info->root.txn, propname,
++                             NULL, subpool);
+     else
+       /* ### VIOLATING deltaV: you can't proppatch a baseline, it's
+          not a working resource!  But this is how we currently

unblock subversion/1.8.10-6

-- System Information:
Debian Release: 8.0
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)


Reply to: