diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c index 44b5fc8..6a50ba7 100644 --- a/modules/aaa/mod_auth_digest.c +++ b/modules/aaa/mod_auth_digest.c @@ -261,6 +261,26 @@ static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s) cleanup_tables(NULL); } +/* RMM helper functions that behave like single-step malloc/free. */ + +static void *rmm_malloc(apr_rmm_t *rmm, apr_size_t size) +{ + apr_rmm_off_t offset = apr_rmm_malloc(rmm, size); + + if (!offset) { + return NULL; + } + + return apr_rmm_addr_get(rmm, offset); +} + +static apr_status_t rmm_free(apr_rmm_t *rmm, void *alloc) +{ + apr_rmm_off_t offset = apr_rmm_offset_get(rmm, alloc); + + return apr_rmm_free(rmm, offset); +} + #if APR_HAS_SHARED_MEMORY static int initialize_tables(server_rec *s, apr_pool_t *ctx) @@ -299,8 +319,8 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) return !OK; } - client_list = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*client_list) + - sizeof(client_entry*)*num_buckets)); + client_list = rmm_malloc(client_rmm, sizeof(*client_list) + + sizeof(client_entry *) * num_buckets); if (!client_list) { log_error_and_cleanup("failed to allocate shared memory", -1, s); return !OK; @@ -322,7 +342,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) /* setup opaque */ - opaque_cntr = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*opaque_cntr))); + opaque_cntr = rmm_malloc(client_rmm, sizeof(*opaque_cntr)); if (opaque_cntr == NULL) { log_error_and_cleanup("failed to allocate shared memory", -1, s); return !OK; @@ -339,7 +359,7 @@ static int initialize_tables(server_rec *s, apr_pool_t *ctx) /* setup one-time-nonce counter */ - otn_counter = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(*otn_counter))); + otn_counter = rmm_malloc(client_rmm, sizeof(*otn_counter)); if (otn_counter == NULL) { log_error_and_cleanup("failed to allocate shared memory", -1, s); return !OK; @@ -779,7 +799,7 @@ static client_entry *get_client(unsigned long key, const request_rec *r) * last entry in each bucket and updates the counters. Returns the * number of removed entries. */ -static long gc(void) +static long gc(server_rec *s) { client_entry *entry, *prev; unsigned long num_removed = 0, idx; @@ -789,6 +809,12 @@ static long gc(void) for (idx = 0; idx < client_list->tbl_len; idx++) { entry = client_list->table[idx]; prev = NULL; + + if (!entry) { + /* This bucket is empty. */ + continue; + } + while (entry->next) { /* find last entry */ prev = entry; entry = entry->next; @@ -800,8 +826,16 @@ static long gc(void) client_list->table[idx] = NULL; } if (entry) { /* remove entry */ - apr_rmm_free(client_rmm, apr_rmm_offset_get(client_rmm, entry)); + apr_status_t err; + + err = rmm_free(client_rmm, entry); num_removed++; + + if (err) { + /* Nothing we can really do but log... */ + ap_log_error(APLOG_MARK, APLOG_ERR, err, s, APLOGNO() + "Failed to free auth_digest client allocation"); + } } } @@ -835,16 +869,16 @@ static client_entry *add_client(unsigned long key, client_entry *info, /* try to allocate a new entry */ - entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry))); + entry = rmm_malloc(client_rmm, sizeof(client_entry)); if (!entry) { - long num_removed = gc(); + long num_removed = gc(s); ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01766) "gc'd %ld client entries. Total new clients: " "%ld; Total removed clients: %ld; Total renewed clients: " "%ld", num_removed, client_list->num_created - client_list->num_renewed, client_list->num_removed, client_list->num_renewed); - entry = apr_rmm_addr_get(client_rmm, apr_rmm_malloc(client_rmm, sizeof(client_entry))); + entry = rmm_malloc(client_rmm, sizeof(client_entry)); if (!entry) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01767) "unable to allocate new auth_digest client");