mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
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
This commit is contained in:
@@ -466,6 +466,7 @@
|
|||||||
* 20140627.1 (2.5.0-dev) add last_backend_conn to util_ldap_connection_t
|
* 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.
|
* 20140627.2 (2.5.0-dev) Added is_name_matchable to proxy_worker_shared.
|
||||||
Added ap_proxy_define_match_worker().
|
Added ap_proxy_define_match_worker().
|
||||||
|
* 20140627.3 (2.5.0-dev) Add ap_copy_scoreboard_worker()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
|
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
|
||||||
@@ -473,7 +474,7 @@
|
|||||||
#ifndef MODULE_MAGIC_NUMBER_MAJOR
|
#ifndef MODULE_MAGIC_NUMBER_MAJOR
|
||||||
#define MODULE_MAGIC_NUMBER_MAJOR 20140627
|
#define MODULE_MAGIC_NUMBER_MAJOR 20140627
|
||||||
#endif
|
#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
|
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
|
||||||
|
@@ -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(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);
|
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,
|
AP_DECLARE(worker_score *) ap_get_scoreboard_worker_from_indexes(int child_num,
|
||||||
int thread_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(process_score *) ap_get_scoreboard_process(int x);
|
||||||
AP_DECLARE(global_score *) ap_get_scoreboard_global(void);
|
AP_DECLARE(global_score *) ap_get_scoreboard_global(void);
|
||||||
|
|
||||||
|
@@ -194,7 +194,7 @@ static int status_handler(request_rec *r)
|
|||||||
long req_time;
|
long req_time;
|
||||||
int short_report;
|
int short_report;
|
||||||
int no_table_report;
|
int no_table_report;
|
||||||
worker_score *ws_record;
|
worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
|
||||||
process_score *ps_record;
|
process_score *ps_record;
|
||||||
char *stat_buffer;
|
char *stat_buffer;
|
||||||
pid_t *pid_buffer, worker_pid;
|
pid_t *pid_buffer, worker_pid;
|
||||||
@@ -306,7 +306,7 @@ static int status_handler(request_rec *r)
|
|||||||
for (j = 0; j < thread_limit; ++j) {
|
for (j = 0; j < thread_limit; ++j) {
|
||||||
int indx = (i * 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;
|
res = ws_record->status;
|
||||||
|
|
||||||
if ((i >= max_servers || j >= threads_per_child)
|
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 (i = 0; i < server_limit; ++i) {
|
||||||
for (j = 0; j < thread_limit; ++j) {
|
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 &&
|
if (ws_record->access_count == 0 &&
|
||||||
(ws_record->status == SERVER_READY ||
|
(ws_record->status == SERVER_READY ||
|
||||||
|
@@ -1242,16 +1242,22 @@ static int lua_ap_scoreboard_process(lua_State *L)
|
|||||||
*/
|
*/
|
||||||
static int lua_ap_scoreboard_worker(lua_State *L)
|
static int lua_ap_scoreboard_worker(lua_State *L)
|
||||||
{
|
{
|
||||||
int i,
|
int i, j;
|
||||||
j;
|
worker_score *ws_record = NULL;
|
||||||
worker_score *ws_record;
|
request_rec *r = NULL;
|
||||||
|
|
||||||
luaL_checktype(L, 1, LUA_TUSERDATA);
|
luaL_checktype(L, 1, LUA_TUSERDATA);
|
||||||
luaL_checktype(L, 2, LUA_TNUMBER);
|
luaL_checktype(L, 2, LUA_TNUMBER);
|
||||||
luaL_checktype(L, 3, 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);
|
i = lua_tointeger(L, 2);
|
||||||
j = lua_tointeger(L, 3);
|
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) {
|
if (ws_record) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
|
@@ -579,6 +579,21 @@ AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh)
|
|||||||
sbh->thread_num);
|
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)
|
AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
|
||||||
{
|
{
|
||||||
if ((x < 0) || (x >= server_limit)) {
|
if ((x < 0) || (x >= server_limit)) {
|
||||||
|
Reference in New Issue
Block a user