diff options
author | Joe Orton <jorton@apache.org> | 2014-07-14 19:26:00 +0000 |
---|---|---|
committer | Joe Orton <jorton@apache.org> | 2014-07-14 19:26:00 +0000 |
commit | b2605d20c42fe882a42f55d059286f64927ac30d (patch) | |
tree | 65c09cc1dc1875766ff9c4257749972813417ee5 | |
parent | 5b6b58bbf228de54e6222d6bd5eef46f0a16f2f9 (diff) | |
download | httpd-b2605d20c42fe882a42f55d059286f64927ac30d.tar.gz |
SECURITY (CVE-2014-0226): Fix a race condition in scoreboard handling,
which could lead to a heap buffer overflow. Thanks to Marek Kroemeke
working with HP's Zero Day Initiative for reporting this.
* include/scoreboard.h: Add ap_copy_scoreboard_worker.
* server/scoreboard.c (ap_copy_scoreboard_worker): New function.
* modules/generators/mod_status.c (status_handler): Use it.
* modules/lua/lua_request.c (lua_ap_scoreboard_worker): Likewise.
Reviewed by: trawick, jorton, covener, jim
Submitted by: jorton, covener
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1610491 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | include/ap_mmn.h | 3 | ||||
-rw-r--r-- | include/scoreboard.h | 17 | ||||
-rw-r--r-- | modules/generators/mod_status.c | 6 | ||||
-rw-r--r-- | modules/lua/lua_request.c | 14 | ||||
-rw-r--r-- | server/scoreboard.c | 15 |
5 files changed, 47 insertions, 8 deletions
diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 0f5485f315..4c82c364dc 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -466,6 +466,7 @@ * 20140627.1 (2.5.0-dev) add last_backend_conn to util_ldap_connection_t * 20140627.2 (2.5.0-dev) Added is_name_matchable to proxy_worker_shared. Added ap_proxy_define_match_worker(). + * 20140627.3 (2.5.0-dev) Add ap_copy_scoreboard_worker() */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -473,7 +474,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20140627 #endif -#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/scoreboard.h b/include/scoreboard.h index d2be9c87a7..c41d7d3f0b 100644 --- a/include/scoreboard.h +++ b/include/scoreboard.h @@ -183,8 +183,25 @@ AP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status); AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh); + +/** Return a pointer to the worker_score for a given child, thread pair. + * @param child_num The child number. + * @param thread_num The thread number. + * @return A pointer to the worker_score structure. + * @deprecated This function is deprecated, use ap_copy_scoreboard_worker instead. */ AP_DECLARE(worker_score *) ap_get_scoreboard_worker_from_indexes(int child_num, int thread_num); + +/** Copy the contents of a worker scoreboard entry. The contents of + * the worker_score structure are copied verbatim into the dest + * structure, which must have sizeof(worker_score). + * @param dest Output parameter. + * @param child_num The child number. + * @param thread_num The thread number. + */ +AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, + int child_num, int thread_num); + AP_DECLARE(process_score *) ap_get_scoreboard_process(int x); AP_DECLARE(global_score *) ap_get_scoreboard_global(void); diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c index fe832b32d0..6bcf592b57 100644 --- a/modules/generators/mod_status.c +++ b/modules/generators/mod_status.c @@ -194,7 +194,7 @@ static int status_handler(request_rec *r) long req_time; int short_report; int no_table_report; - worker_score *ws_record; + worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record); process_score *ps_record; char *stat_buffer; pid_t *pid_buffer, worker_pid; @@ -306,7 +306,7 @@ static int status_handler(request_rec *r) for (j = 0; j < thread_limit; ++j) { int indx = (i * thread_limit) + j; - ws_record = ap_get_scoreboard_worker_from_indexes(i, j); + ap_copy_scoreboard_worker(ws_record, i, j); res = ws_record->status; if ((i >= max_servers || j >= threads_per_child) @@ -637,7 +637,7 @@ static int status_handler(request_rec *r) for (i = 0; i < server_limit; ++i) { for (j = 0; j < thread_limit; ++j) { - ws_record = ap_get_scoreboard_worker_from_indexes(i, j); + ap_copy_scoreboard_worker(ws_record, i, j); if (ws_record->access_count == 0 && (ws_record->status == SERVER_READY || diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index 445e3caf1f..1e97fb5438 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -1242,16 +1242,22 @@ static int lua_ap_scoreboard_process(lua_State *L) */ static int lua_ap_scoreboard_worker(lua_State *L) { - int i, - j; - worker_score *ws_record; + int i, j; + worker_score *ws_record = NULL; + request_rec *r = NULL; luaL_checktype(L, 1, LUA_TUSERDATA); luaL_checktype(L, 2, LUA_TNUMBER); luaL_checktype(L, 3, LUA_TNUMBER); + + r = ap_lua_check_request_rec(L, 1); + if (!r) return 0; + i = lua_tointeger(L, 2); j = lua_tointeger(L, 3); - ws_record = ap_get_scoreboard_worker_from_indexes(i, j); + ws_record = apr_palloc(r->pool, sizeof *ws_record); + + ap_copy_scoreboard_worker(ws_record, i, j); if (ws_record) { lua_newtable(L); diff --git a/server/scoreboard.c b/server/scoreboard.c index ba0ef6a3ee..befb2bcdc2 100644 --- a/server/scoreboard.c +++ b/server/scoreboard.c @@ -579,6 +579,21 @@ AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh) sbh->thread_num); } +AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, + int child_num, + int thread_num) +{ + worker_score *ws = ap_get_scoreboard_worker_from_indexes(child_num, thread_num); + + memcpy(dest, ws, sizeof *ws); + + /* For extra safety, NUL-terminate the strings returned, though it + * should be true those last bytes are always zero anyway. */ + dest->client[sizeof(dest->client) - 1] = '\0'; + dest->request[sizeof(dest->request) - 1] = '\0'; + dest->vhost[sizeof(dest->vhost) - 1] = '\0'; +} + AP_DECLARE(process_score *) ap_get_scoreboard_process(int x) { if ((x < 0) || (x >= server_limit)) { |