Package: libapache2-mod-gnutls
Version: 0.5.6-1
Severity: important
Tags: squeeze sid patch
Hi,
After upgrading our subversion server from lenny to squeeze, our apache server
was segfaulting on almost all https connections. All apache2 children crashed,
see below:
[Sat Feb 26 11:06:20 2011] [notice] child pid 5439 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:25 2011] [notice] child pid 5440 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:26 2011] [notice] child pid 5500 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:27 2011] [notice] child pid 5533 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:27 2011] [notice] child pid 5534 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:29 2011] [notice] child pid 5590 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:30 2011] [notice] child pid 5618 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:30 2011] [notice] child pid 5619 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:32 2011] [notice] child pid 5676 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:33 2011] [notice] child pid 5704 exit signal Segmentation
fault (11)
[Sat Feb 26 11:06:33 2011] [notice] child pid 5705 exit signal Segmentation
fault (11)
The following bug report describes this behaviour and contains a patch:
http://issues.outoforder.cc/view.php?id=106
I've applied the patch to the debian package and this seems to fix this bug.
Please consider applying this patch to the Debian package and a backport for a
squeeze
point release.
According to the bug report, this bug is also fixed in the 0.5.8 upstream
version.
Regards,
Rik
-- System Information:
Debian Release: 6.0
APT prefers squeeze-updates
APT policy: (500, 'squeeze-updates'), (500, 'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 2.6.32-5-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages libapache2-mod-gnutls depends on:
ii libc6 2.11.2-10 Embedded GNU C Library: Shared lib
ii libgnutls26 2.8.6-1 the GNU TLS library - runtime libr
libapache2-mod-gnutls recommends no packages.
libapache2-mod-gnutls suggests no packages.
-- no debconf information
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 3ce8188..7c638fb 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -486,7 +486,12 @@ void mgs_hook_child_init(apr_pool_t * p, server_rec * s)
const char *mgs_hook_http_scheme(const request_rec * r)
{
- mgs_srvconf_rec *sc =
+ mgs_srvconf_rec *sc;
+
+ if (r == NULL)
+ return NULL;
+
+ sc =
(mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,
&gnutls_module);
@@ -500,7 +505,12 @@ const char *mgs_hook_http_scheme(const request_rec * r)
apr_port_t mgs_hook_default_port(const request_rec * r)
{
- mgs_srvconf_rec *sc =
+ mgs_srvconf_rec *sc;
+
+ if (r == NULL)
+ return 0;
+
+ sc =
(mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,
&gnutls_module);
@@ -579,6 +589,9 @@ mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
mgs_srvconf_rec *tsc;
#endif
+ if (session == NULL)
+ return NULL;
+
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
ctxt = gnutls_transport_get_ptr(session);
@@ -693,12 +706,18 @@ static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c)
int mgs_hook_pre_connection(conn_rec * c, void *csd)
{
mgs_handle_t *ctxt;
- mgs_srvconf_rec *sc =
+ mgs_srvconf_rec *sc;
+
+ _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
+
+ if (c == NULL)
+ return DECLINED;
+
+ sc =
(mgs_srvconf_rec *) ap_get_module_config(c->base_server->
module_config,
&gnutls_module);
- _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) {
return DECLINED;
}
@@ -732,13 +751,16 @@ int mgs_hook_fixups(request_rec * r)
mgs_handle_t *ctxt;
int rv = OK;
+ if (r == NULL)
+ return DECLINED;
+
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
apr_table_t *env = r->subprocess_env;
ctxt =
ap_get_module_config(r->connection->conn_config, &gnutls_module);
- if (!ctxt) {
+ if (!ctxt || ctxt->session == NULL) {
return DECLINED;
}
@@ -804,14 +826,19 @@ int mgs_hook_authz(request_rec * r)
{
int rv;
mgs_handle_t *ctxt;
- mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
+ mgs_dirconf_rec *dc;
+
+ if (r == NULL)
+ return DECLINED;
+
+ dc = ap_get_module_config(r->per_dir_config,
&gnutls_module);
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
ctxt =
ap_get_module_config(r->connection->conn_config, &gnutls_module);
- if (!ctxt) {
+ if (!ctxt || ctxt->session == NULL) {
return DECLINED;
}
@@ -875,6 +902,9 @@ mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side,
size_t len;
int ret, i;
+ if (r == NULL)
+ return;
+
apr_table_t *env = r->subprocess_env;
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
@@ -983,6 +1013,9 @@ mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side
const char *tmp;
size_t len;
int ret;
+
+ if (r == NULL)
+ return;
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
apr_table_t *env = r->subprocess_env;
@@ -1052,6 +1085,9 @@ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
} cert;
apr_time_t expiration_time, cur_time;
+ if (r == NULL || ctxt == NULL || ctxt->session == NULL)
+ return HTTP_FORBIDDEN;
+
_gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
cert_list =
gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
diff --git a/src/gnutls_io.c b/src/gnutls_io.c
index 8187da6..ba03fce 100644
--- a/src/gnutls_io.c
+++ b/src/gnutls_io.c
@@ -221,6 +221,10 @@ static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt,
ctxt->input_block = APR_NONBLOCK_READ;
}
}
+
+ if (ctxt->session == NULL) {
+ return APR_EGENERAL;
+ }
while (1) {
@@ -360,7 +364,7 @@ static int gnutls_do_handshake(mgs_handle_t * ctxt)
int errcode;
int maxtries = HANDSHAKE_MAX_TRIES;
- if (ctxt->status != 0) {
+ if (ctxt->status != 0 || ctxt->session == NULL) {
return -1;
}
@@ -441,6 +445,9 @@ tryagain:
int mgs_rehandshake(mgs_handle_t * ctxt)
{
int rv;
+
+ if (ctxt->session == NULL)
+ return -1;
rv = gnutls_rehandshake(ctxt->session);
@@ -565,7 +572,7 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
apr_bucket_copy(bucket, &e);
APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e);
-
+
if ((status = ap_pass_brigade(f->next, tmpb)) != APR_SUCCESS) {
apr_brigade_cleanup(ctxt->output_bb);
return status;
@@ -609,10 +616,14 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
if (len > 0) {
- do {
- ret = gnutls_record_send(ctxt->session, data, len);
+ if (ctxt->session == NULL) {
+ ret = GNUTLS_E_INVALID_REQUEST;
+ } else {
+ do {
+ ret = gnutls_record_send(ctxt->session, data, len);
+ }
+ while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
}
- while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
if (ret < 0) {
/* error sending output */
@@ -674,7 +685,8 @@ ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr,
if (APR_STATUS_IS_EOF(ctxt->input_rc)) {
return 0;
} else {
- gnutls_transport_set_errno(ctxt->session, EINTR);
+ if (ctxt->session)
+ gnutls_transport_set_errno(ctxt->session, EINTR);
return -1;
}
}
@@ -697,7 +709,8 @@ ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr,
if (APR_STATUS_IS_EAGAIN(ctxt->input_rc)
|| APR_STATUS_IS_EINTR(ctxt->input_rc)) {
if (len == 0) {
- gnutls_transport_set_errno(ctxt->session, EINTR);
+ if (ctxt->session)
+ gnutls_transport_set_errno(ctxt->session, EINTR);
return -1;
}