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 2019/01/07 15:04:16 UTC
svn commit: r1850651 - /subversion/trunk/subversion/mod_dav_svn/repos.c
Author: stsp
Date: Mon Jan 7 15:04:15 2019
New Revision: 1850651
URL: http://svn.apache.org/viewvc?rev=1850651&view=rev
Log:
Fix a use-after-free in mod_dav_svn's logging of FS warnings.
The FS warning callback could be called with a request context that had
already been deallocated. This resulted in a crash during 'make check'
with ra_serf on OpenBSD. The problem was even documented in a comment:
/* ### hmm. the FS is cleaned up at request cleanup time. "r" might
### not really be valid. we should probably put the FS into a
### subpool to ensure it gets cleaned before the request.
### is there a good way to create and use a subpool for all
### of our functions ... ??
*/
Rather than putting the FS into a subpool, the solution implemented with this
commit installs a pre-cleanup handler on the request pool, which switches the
logging context from the request to its associated connection. This avoids the
use-after-free at the cost of a less precise logging context.
Suggested by: stefan2
https://svn.haxx.se/dev/archive-2018-12/0145.shtml
* subversion/mod_dav_svn/repos.c
(log_warning): Rename to ...
(log_warning_req): ... this.
(log_warning_conn): New logging helper which uses a connection context.
(cleanup_req_logging_baton, cleanup_req_logging): New APR pool cleanup
handler which switches FS logging context from a request to a connection.
(get_resource): Install aforementioned pool cleanup handler.
Modified:
subversion/trunk/subversion/mod_dav_svn/repos.c
Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1850651&r1=1850650&r2=1850651&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Mon Jan 7 15:04:15 2019
@@ -1225,25 +1225,32 @@ create_private_resource(const dav_resour
return &comb->res;
}
-
-static void log_warning(void *baton, svn_error_t *err)
+static void log_warning_req(void *baton, svn_error_t *err)
{
request_rec *r = baton;
const char *continuation = "";
- /* ### hmm. the FS is cleaned up at request cleanup time. "r" might
- ### not really be valid. we should probably put the FS into a
- ### subpool to ensure it gets cleaned before the request.
+ /* Not showing file/line so no point in tracing */
+ err = svn_error_purge_tracing(err);
+ while (err)
+ {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+ continuation, err->message);
+ continuation = "-";
+ err = err->child;
+ }
+}
- ### is there a good way to create and use a subpool for all
- ### of our functions ... ??
- */
+static void log_warning_conn(void *baton, svn_error_t *err)
+{
+ conn_rec *c = baton;
+ const char *continuation = "";
/* Not showing file/line so no point in tracing */
err = svn_error_purge_tracing(err);
while (err)
{
- ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c, "%s%s",
continuation, err->message);
continuation = "-";
err = err->child;
@@ -1547,6 +1554,24 @@ cleanup_fs_access(void *data)
return APR_SUCCESS;
}
+/* Context for cleanup handler. */
+struct cleanup_req_logging_baton
+{
+ svn_fs_t *fs;
+ conn_rec *connection;
+};
+
+static apr_status_t
+cleanup_req_logging(void *data)
+{
+ struct cleanup_req_logging_baton *baton = data;
+
+ /* The request about to be freed. Log future warnings with a connection
+ * context instead of a request context. */
+ svn_fs_set_warning_func(baton->fs, log_warning_conn, baton->connection);
+
+ return APR_SUCCESS;
+}
/* Helper func to construct a special 'parentpath' private resource. */
static dav_error *
@@ -2180,6 +2205,7 @@ get_resource(request_rec *r,
int had_slash;
dav_locktoken_list *ltl;
struct cleanup_fs_access_baton *cleanup_baton;
+ struct cleanup_req_logging_baton *cleanup_req_logging_baton;
void *userdata;
apr_hash_t *fs_config;
@@ -2486,7 +2512,7 @@ get_resource(request_rec *r,
repos->fs = svn_repos_fs(repos->repos);
/* capture warnings during cleanup of the FS */
- svn_fs_set_warning_func(repos->fs, log_warning, r);
+ svn_fs_set_warning_func(repos->fs, log_warning_req, r);
/* if an authenticated username is present, attach it to the FS */
if (r->user)
@@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
apr_pool_cleanup_null);
+ /* We must degrade the logging context when the request is freed. */
+ cleanup_req_logging_baton =
+ apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
+ cleanup_req_logging_baton->fs = repos->fs;
+ cleanup_req_logging_baton->connection = r->connection;
+ apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
+ cleanup_req_logging);
+
/* Create an access context based on the authenticated username. */
serr = svn_fs_create_access(&access_ctx, r->user, r->pool);
if (serr)
Re: svn commit: r1850651 -
/subversion/trunk/subversion/mod_dav_svn/repos.c
Posted by Stefan Sperling <st...@elego.de>.
On Thu, Aug 15, 2019 at 09:36:48PM +0300, Sergey Raevskiy wrote:
> Hi!
>
> I've attached a patch with fix. Log message:
> [[[
> * subversion/mod_dav_svn/repos.c
> (get_resource): Following up on r1850651: Set cleanup handler for
> FS warning logging regardless of presence of R->USER.
>
> Patch by: sergey.raevskiy{_AT_}visualsvn.com
> ]]]
Thank you Sergey!
I can confirm FSFS/serf tests still pass with this patch on an OpenBSD
System. Which means the original use-after-free issue remains fixed.
Committed in r1865266.
Regards,
Stefan
Re: svn commit: r1850651 - /subversion/trunk/subversion/mod_dav_svn/repos.c
Posted by Sergey Raevskiy <Se...@visualsvn.com>.
Hi!
I've attached a patch with fix. Log message:
[[[
* subversion/mod_dav_svn/repos.c
(get_resource): Following up on r1850651: Set cleanup handler for
FS warning logging regardless of presence of R->USER.
Patch by: sergey.raevskiy{_AT_}visualsvn.com
]]]
On Thu, Aug 15, 2019 at 8:25 PM Stefan Sperling <st...@apache.org> wrote:
>
> On Thu, Aug 15, 2019 at 08:14:43PM +0300, Sergey Raevskiy wrote:
> > > /* if an authenticated username is present, attach it to the FS */
> > > if (r->user)
> > > @@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
> > > apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
> > > apr_pool_cleanup_null);
> > >
> > > + /* We must degrade the logging context when the request is freed. */
> > > + cleanup_req_logging_baton =
> > > + apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
> > > + cleanup_req_logging_baton->fs = repos->fs;
> > > + cleanup_req_logging_baton->connection = r->connection;
> > > + apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
> > > + cleanup_req_logging);
> >
> > Is it intended to set-up this cleanup handler only if R->USER is specified?
>
> Thanks Sergey!
>
> Good question. Looking back at this patch, this looks like an accident.
>
> Were you planning on writing a fix?
Re: svn commit: r1850651 -
/subversion/trunk/subversion/mod_dav_svn/repos.c
Posted by Stefan Sperling <st...@apache.org>.
On Thu, Aug 15, 2019 at 08:14:43PM +0300, Sergey Raevskiy wrote:
> > /* if an authenticated username is present, attach it to the FS */
> > if (r->user)
> > @@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
> > apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
> > apr_pool_cleanup_null);
> >
> > + /* We must degrade the logging context when the request is freed. */
> > + cleanup_req_logging_baton =
> > + apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
> > + cleanup_req_logging_baton->fs = repos->fs;
> > + cleanup_req_logging_baton->connection = r->connection;
> > + apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
> > + cleanup_req_logging);
>
> Is it intended to set-up this cleanup handler only if R->USER is specified?
Thanks Sergey!
Good question. Looking back at this patch, this looks like an accident.
Were you planning on writing a fix?
Re: svn commit: r1850651 - /subversion/trunk/subversion/mod_dav_svn/repos.c
Posted by Sergey Raevskiy <Se...@visualsvn.com>.
> /* if an authenticated username is present, attach it to the FS */
> if (r->user)
> @@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
> apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
> apr_pool_cleanup_null);
>
> + /* We must degrade the logging context when the request is freed. */
> + cleanup_req_logging_baton =
> + apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
> + cleanup_req_logging_baton->fs = repos->fs;
> + cleanup_req_logging_baton->connection = r->connection;
> + apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
> + cleanup_req_logging);
Is it intended to set-up this cleanup handler only if R->USER is specified?
On Mon, Jan 7, 2019 at 6:04 PM <st...@apache.org> wrote:
>
> Author: stsp
> Date: Mon Jan 7 15:04:15 2019
> New Revision: 1850651
>
> URL: http://svn.apache.org/viewvc?rev=1850651&view=rev
> Log:
> Fix a use-after-free in mod_dav_svn's logging of FS warnings.
>
> The FS warning callback could be called with a request context that had
> already been deallocated. This resulted in a crash during 'make check'
> with ra_serf on OpenBSD. The problem was even documented in a comment:
>
> /* ### hmm. the FS is cleaned up at request cleanup time. "r" might
> ### not really be valid. we should probably put the FS into a
> ### subpool to ensure it gets cleaned before the request.
> ### is there a good way to create and use a subpool for all
> ### of our functions ... ??
> */
>
> Rather than putting the FS into a subpool, the solution implemented with this
> commit installs a pre-cleanup handler on the request pool, which switches the
> logging context from the request to its associated connection. This avoids the
> use-after-free at the cost of a less precise logging context.
>
> Suggested by: stefan2
> https://svn.haxx.se/dev/archive-2018-12/0145.shtml
>
> * subversion/mod_dav_svn/repos.c
> (log_warning): Rename to ...
> (log_warning_req): ... this.
> (log_warning_conn): New logging helper which uses a connection context.
> (cleanup_req_logging_baton, cleanup_req_logging): New APR pool cleanup
> handler which switches FS logging context from a request to a connection.
> (get_resource): Install aforementioned pool cleanup handler.
>
> Modified:
> subversion/trunk/subversion/mod_dav_svn/repos.c
>
> Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
> URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=1850651&r1=1850650&r2=1850651&view=diff
> ==============================================================================
> --- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
> +++ subversion/trunk/subversion/mod_dav_svn/repos.c Mon Jan 7 15:04:15 2019
> @@ -1225,25 +1225,32 @@ create_private_resource(const dav_resour
> return &comb->res;
> }
>
> -
> -static void log_warning(void *baton, svn_error_t *err)
> +static void log_warning_req(void *baton, svn_error_t *err)
> {
> request_rec *r = baton;
> const char *continuation = "";
>
> - /* ### hmm. the FS is cleaned up at request cleanup time. "r" might
> - ### not really be valid. we should probably put the FS into a
> - ### subpool to ensure it gets cleaned before the request.
> + /* Not showing file/line so no point in tracing */
> + err = svn_error_purge_tracing(err);
> + while (err)
> + {
> + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
> + continuation, err->message);
> + continuation = "-";
> + err = err->child;
> + }
> +}
>
> - ### is there a good way to create and use a subpool for all
> - ### of our functions ... ??
> - */
> +static void log_warning_conn(void *baton, svn_error_t *err)
> +{
> + conn_rec *c = baton;
> + const char *continuation = "";
>
> /* Not showing file/line so no point in tracing */
> err = svn_error_purge_tracing(err);
> while (err)
> {
> - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
> + ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c, "%s%s",
> continuation, err->message);
> continuation = "-";
> err = err->child;
> @@ -1547,6 +1554,24 @@ cleanup_fs_access(void *data)
> return APR_SUCCESS;
> }
>
> +/* Context for cleanup handler. */
> +struct cleanup_req_logging_baton
> +{
> + svn_fs_t *fs;
> + conn_rec *connection;
> +};
> +
> +static apr_status_t
> +cleanup_req_logging(void *data)
> +{
> + struct cleanup_req_logging_baton *baton = data;
> +
> + /* The request about to be freed. Log future warnings with a connection
> + * context instead of a request context. */
> + svn_fs_set_warning_func(baton->fs, log_warning_conn, baton->connection);
> +
> + return APR_SUCCESS;
> +}
>
> /* Helper func to construct a special 'parentpath' private resource. */
> static dav_error *
> @@ -2180,6 +2205,7 @@ get_resource(request_rec *r,
> int had_slash;
> dav_locktoken_list *ltl;
> struct cleanup_fs_access_baton *cleanup_baton;
> + struct cleanup_req_logging_baton *cleanup_req_logging_baton;
> void *userdata;
> apr_hash_t *fs_config;
>
> @@ -2486,7 +2512,7 @@ get_resource(request_rec *r,
> repos->fs = svn_repos_fs(repos->repos);
>
> /* capture warnings during cleanup of the FS */
> - svn_fs_set_warning_func(repos->fs, log_warning, r);
> + svn_fs_set_warning_func(repos->fs, log_warning_req, r);
>
> /* if an authenticated username is present, attach it to the FS */
> if (r->user)
> @@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
> apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
> apr_pool_cleanup_null);
>
> + /* We must degrade the logging context when the request is freed. */
> + cleanup_req_logging_baton =
> + apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
> + cleanup_req_logging_baton->fs = repos->fs;
> + cleanup_req_logging_baton->connection = r->connection;
> + apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
> + cleanup_req_logging);
> +
> /* Create an access context based on the authenticated username. */
> serr = svn_fs_create_access(&access_ctx, r->user, r->pool);
> if (serr)
>
>