mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
Security: update to LiteSpeed SAPI v7.7 to address an buffer overflow, and some log message tunings.
This commit is contained in:
parent
c68d48de9e
commit
c39f5fe94e
3 changed files with 234 additions and 14 deletions
|
@ -72,7 +72,7 @@
|
||||||
#include "lscriu.c"
|
#include "lscriu.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SAPI_LSAPI_MAX_HEADER_LENGTH 2048
|
#define SAPI_LSAPI_MAX_HEADER_LENGTH LSAPI_RESP_HTTP_HEADER_MAX
|
||||||
|
|
||||||
/* Key for each cache entry is dirname(PATH_TRANSLATED).
|
/* Key for each cache entry is dirname(PATH_TRANSLATED).
|
||||||
*
|
*
|
||||||
|
@ -621,7 +621,7 @@ static int sapi_lsapi_activate()
|
||||||
static sapi_module_struct lsapi_sapi_module =
|
static sapi_module_struct lsapi_sapi_module =
|
||||||
{
|
{
|
||||||
"litespeed",
|
"litespeed",
|
||||||
"LiteSpeed V7.6",
|
"LiteSpeed V7.7",
|
||||||
|
|
||||||
php_lsapi_startup, /* startup */
|
php_lsapi_startup, /* startup */
|
||||||
php_module_shutdown_wrapper, /* shutdown */
|
php_module_shutdown_wrapper, /* shutdown */
|
||||||
|
@ -1768,7 +1768,7 @@ PHP_FUNCTION(litespeed_response_headers)
|
||||||
if ( h->header_len > 0 ) {
|
if ( h->header_len > 0 ) {
|
||||||
p = strchr( h->header, ':' );
|
p = strchr( h->header, ':' );
|
||||||
len = p - h->header;
|
len = p - h->header;
|
||||||
if (( p )&&( len > 0 )) {
|
if (p && len > 0 && len < LSAPI_RESP_HTTP_HEADER_MAX) {
|
||||||
memmove( headerBuf, h->header, len );
|
memmove( headerBuf, h->header, len );
|
||||||
while( len > 0 && (isspace( headerBuf[len-1])) ) {
|
while( len > 0 && (isspace( headerBuf[len-1])) ) {
|
||||||
--len;
|
--len;
|
||||||
|
|
|
@ -126,7 +126,7 @@ enum
|
||||||
LSAPI_STATE_ACCEPTING,
|
LSAPI_STATE_ACCEPTING,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _lsapi_child_status
|
typedef struct lsapi_child_status
|
||||||
{
|
{
|
||||||
int m_pid;
|
int m_pid;
|
||||||
long m_tmStart;
|
long m_tmStart;
|
||||||
|
@ -790,10 +790,10 @@ static int lsapi_load_lve_lib(void)
|
||||||
int uid = getuid();
|
int uid = getuid();
|
||||||
if ( uid )
|
if ( uid )
|
||||||
{
|
{
|
||||||
setreuid( s_uid, uid );
|
if (setreuid( s_uid, uid )) {};
|
||||||
if ( !(*fp_lve_is_available)() )
|
if ( !(*fp_lve_is_available)() )
|
||||||
s_enable_lve = 0;
|
s_enable_lve = 0;
|
||||||
setreuid( uid, s_uid );
|
if (setreuid( uid, s_uid )) {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,7 +898,7 @@ static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char
|
||||||
if ( pReq )
|
if ( pReq )
|
||||||
LSAPI_Write_Stderr_r( pReq, achError, n );
|
LSAPI_Write_Stderr_r( pReq, achError, n );
|
||||||
else
|
else
|
||||||
write( STDERR_FILENO, achError, n );
|
if (write( STDERR_FILENO, achError, n )) {};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2775,6 +2775,9 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
|
||||||
g_prefork_server->m_iMaxIdleChildren = 1;
|
g_prefork_server->m_iMaxIdleChildren = 1;
|
||||||
g_prefork_server->m_iChildrenMaxIdleTime = 300;
|
g_prefork_server->m_iChildrenMaxIdleTime = 300;
|
||||||
g_prefork_server->m_iMaxReqProcessTime = 3600;
|
g_prefork_server->m_iMaxReqProcessTime = 3600;
|
||||||
|
|
||||||
|
setsid();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2830,6 +2833,11 @@ static lsapi_child_status * find_child_status( int pid )
|
||||||
{
|
{
|
||||||
if ( pStatus->m_pid == pid )
|
if ( pStatus->m_pid == pid )
|
||||||
{
|
{
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
memset(pStatus, 0, sizeof( *pStatus ) );
|
||||||
|
pStatus->m_pid = -1;
|
||||||
|
}
|
||||||
if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
|
if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
|
||||||
g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
|
g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
|
||||||
return pStatus;
|
return pStatus;
|
||||||
|
@ -2928,7 +2936,10 @@ static void lsapi_sigchild( int signal )
|
||||||
static int lsapi_init_children_status(void)
|
static int lsapi_init_children_status(void)
|
||||||
{
|
{
|
||||||
int size = 4096;
|
int size = 4096;
|
||||||
int max_children = g_prefork_server->m_iMaxChildren
|
int max_children;
|
||||||
|
if (g_prefork_server->m_pChildrenStatus)
|
||||||
|
return 0;
|
||||||
|
max_children = g_prefork_server->m_iMaxChildren
|
||||||
+ g_prefork_server->m_iExtraChildren;
|
+ g_prefork_server->m_iExtraChildren;
|
||||||
|
|
||||||
char * pBuf;
|
char * pBuf;
|
||||||
|
@ -2949,6 +2960,8 @@ static int lsapi_init_children_status(void)
|
||||||
s_accepting_workers = s_busy_workers + 1;
|
s_accepting_workers = s_busy_workers + 1;
|
||||||
s_global_counter = s_accepting_workers + 1;
|
s_global_counter = s_accepting_workers + 1;
|
||||||
s_avail_pages = (size_t *)(s_global_counter + 1);
|
s_avail_pages = (size_t *)(s_global_counter + 1);
|
||||||
|
|
||||||
|
setsid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3118,8 +3131,6 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||||
|
|
||||||
lsapi_init_children_status();
|
lsapi_init_children_status();
|
||||||
|
|
||||||
setsid();
|
|
||||||
|
|
||||||
act.sa_flags = 0;
|
act.sa_flags = 0;
|
||||||
act.sa_handler = lsapi_sigchild;
|
act.sa_handler = lsapi_sigchild;
|
||||||
sigemptyset(&(act.sa_mask));
|
sigemptyset(&(act.sa_mask));
|
||||||
|
@ -3141,7 +3152,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||||
perror( "Can't set signals" );
|
perror( "Can't set signals" );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s_stop = 0;
|
|
||||||
while( !s_stop )
|
while( !s_stop )
|
||||||
{
|
{
|
||||||
if (s_proc_group_timer_cb != NULL) {
|
if (s_proc_group_timer_cb != NULL) {
|
||||||
|
@ -3219,8 +3230,6 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||||
{
|
{
|
||||||
wait_secs = 0;
|
wait_secs = 0;
|
||||||
child_status = find_child_status( 0 );
|
child_status = find_child_status( 0 );
|
||||||
if ( child_status )
|
|
||||||
memset( child_status, 0, sizeof( *child_status ) );
|
|
||||||
|
|
||||||
sigemptyset( &mask );
|
sigemptyset( &mask );
|
||||||
sigaddset( &mask, SIGCHLD );
|
sigaddset( &mask, SIGCHLD );
|
||||||
|
@ -3312,6 +3321,210 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct sigaction old_term, old_quit, old_int,
|
||||||
|
old_usr1, old_child;
|
||||||
|
|
||||||
|
|
||||||
|
int LSAPI_Postfork_Child(LSAPI_Request * pReq)
|
||||||
|
{
|
||||||
|
int max_children = g_prefork_server->m_iMaxChildren;
|
||||||
|
s_pid = getpid();
|
||||||
|
__sync_lock_test_and_set(&pReq->child_status->m_pid, s_pid);
|
||||||
|
s_worker_status = pReq->child_status;
|
||||||
|
|
||||||
|
setsid();
|
||||||
|
g_prefork_server = NULL;
|
||||||
|
s_ppid = getppid();
|
||||||
|
s_req_processed = 0;
|
||||||
|
s_proc_group_timer_cb = NULL;
|
||||||
|
|
||||||
|
if (pthread_atfork_func)
|
||||||
|
(*pthread_atfork_func)(NULL, NULL, set_skip_write);
|
||||||
|
|
||||||
|
__sync_lock_test_and_set(&s_worker_status->m_state,
|
||||||
|
LSAPI_STATE_CONNECTED);
|
||||||
|
if (s_busy_workers)
|
||||||
|
__sync_add_and_fetch(s_busy_workers, 1);
|
||||||
|
lsapi_set_nblock( pReq->m_fd, 0 );
|
||||||
|
//keep it open if busy_count is used.
|
||||||
|
if (s_busy_workers
|
||||||
|
&& *s_busy_workers > (max_children >> 1))
|
||||||
|
s_keepListener = 1;
|
||||||
|
if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
|
||||||
|
&& pReq->m_fdListen != -1 )
|
||||||
|
{
|
||||||
|
close(pReq->m_fdListen);
|
||||||
|
pReq->m_fdListen = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//init_conn_key( pReq->m_fd );
|
||||||
|
lsapi_notify_pid(pReq->m_fd);
|
||||||
|
s_notified_pid = 1;
|
||||||
|
//if ( s_accept_notify )
|
||||||
|
// return notify_req_received( pReq->m_fd );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
|
||||||
|
{
|
||||||
|
++g_prefork_server->m_iCurChildren;
|
||||||
|
if (pReq->child_status)
|
||||||
|
{
|
||||||
|
time_t curTime = time( NULL );
|
||||||
|
pReq->child_status->m_tmWaitBegin = curTime;
|
||||||
|
pReq->child_status->m_tmStart = curTime;
|
||||||
|
}
|
||||||
|
close(pReq->m_fd);
|
||||||
|
pReq->m_fd = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
|
||||||
|
{
|
||||||
|
time_t lastTime = 0;
|
||||||
|
time_t curTime = 0;
|
||||||
|
fd_set readfds;
|
||||||
|
struct timeval timeout;
|
||||||
|
int wait_secs = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
lsapi_prefork_server * pServer = g_prefork_server;
|
||||||
|
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
lsapi_init_children_status();
|
||||||
|
|
||||||
|
act.sa_flags = 0;
|
||||||
|
act.sa_handler = lsapi_sigchild;
|
||||||
|
sigemptyset(&(act.sa_mask));
|
||||||
|
if (sigaction(SIGCHLD, &act, &old_child))
|
||||||
|
{
|
||||||
|
perror( "Can't set signal handler for SIGCHILD" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up handler to kill children upon exit */
|
||||||
|
act.sa_flags = 0;
|
||||||
|
act.sa_handler = lsapi_cleanup;
|
||||||
|
sigemptyset(&(act.sa_mask));
|
||||||
|
if (sigaction(SIGTERM, &act, &old_term) ||
|
||||||
|
sigaction(SIGINT, &act, &old_int ) ||
|
||||||
|
sigaction(SIGUSR1, &act, &old_usr1) ||
|
||||||
|
sigaction(SIGQUIT, &act, &old_quit))
|
||||||
|
{
|
||||||
|
perror( "Can't set signals" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s_stop = 0;
|
||||||
|
pReq->m_reqState = 0;
|
||||||
|
|
||||||
|
while(!s_stop)
|
||||||
|
{
|
||||||
|
if (s_proc_group_timer_cb != NULL) {
|
||||||
|
s_proc_group_timer_cb(&s_ignore_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
curTime = time(NULL);
|
||||||
|
if (curTime != lastTime)
|
||||||
|
{
|
||||||
|
lastTime = curTime;
|
||||||
|
if (lsapi_parent_dead())
|
||||||
|
break;
|
||||||
|
lsapi_check_child_status(curTime);
|
||||||
|
if (pServer->m_iServerMaxIdle)
|
||||||
|
{
|
||||||
|
if (pServer->m_iCurChildren <= 0)
|
||||||
|
{
|
||||||
|
++wait_secs;
|
||||||
|
if ( wait_secs > pServer->m_iServerMaxIdle )
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wait_secs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
|
||||||
|
*s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
|
||||||
|
// lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
|
||||||
|
// s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(pServer->m_fd, &readfds);
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
|
||||||
|
if (ret == 1 )
|
||||||
|
{
|
||||||
|
int accepting = 0;
|
||||||
|
if (s_accepting_workers)
|
||||||
|
accepting = __sync_add_and_fetch(s_accepting_workers, 0);
|
||||||
|
|
||||||
|
if (pServer->m_iCurChildren > 0
|
||||||
|
&& accepting > 0)
|
||||||
|
{
|
||||||
|
usleep( 400);
|
||||||
|
while(accepting-- > 0)
|
||||||
|
sched_yield();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ret == -1)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
/* perror( "select()" ); */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pServer->m_iCurChildren >=
|
||||||
|
pServer->m_iMaxChildren + pServer->m_iExtraChildren)
|
||||||
|
{
|
||||||
|
lsapi_log("Reached max children process limit: %d, extra: %d,"
|
||||||
|
" current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
|
||||||
|
pServer->m_iMaxChildren, pServer->m_iExtraChildren,
|
||||||
|
pServer->m_iCurChildren,
|
||||||
|
s_busy_workers ? *s_busy_workers : -1);
|
||||||
|
usleep(100000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pReq->m_fd = lsapi_accept(pServer->m_fd);
|
||||||
|
if (pReq->m_fd != -1)
|
||||||
|
{
|
||||||
|
wait_secs = 0;
|
||||||
|
pReq->child_status = find_child_status(0);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((errno == EINTR) || (errno == EAGAIN))
|
||||||
|
continue;
|
||||||
|
perror( "accept() failed" );
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sigaction(SIGCHLD, &old_child, 0);
|
||||||
|
sigaction(SIGTERM, &old_term, 0);
|
||||||
|
sigaction(SIGQUIT, &old_quit, 0);
|
||||||
|
sigaction(SIGINT, &old_int, 0);
|
||||||
|
sigaction(SIGUSR1, &old_usr1, 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void lsapi_perror( const char * pMessage, int err_no )
|
void lsapi_perror( const char * pMessage, int err_no )
|
||||||
{
|
{
|
||||||
lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no,
|
lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no,
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct LSAPI_key_value_pair
|
||||||
int valLen;
|
int valLen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lsapi_child_status;
|
||||||
#define LSAPI_MAX_RESP_HEADERS 1000
|
#define LSAPI_MAX_RESP_HEADERS 1000
|
||||||
|
|
||||||
typedef struct lsapi_request
|
typedef struct lsapi_request
|
||||||
|
@ -91,6 +91,7 @@ typedef struct lsapi_request
|
||||||
char * m_pRespHeaderBuf;
|
char * m_pRespHeaderBuf;
|
||||||
char * m_pRespHeaderBufEnd;
|
char * m_pRespHeaderBufEnd;
|
||||||
char * m_pRespHeaderBufPos;
|
char * m_pRespHeaderBufPos;
|
||||||
|
struct lsapi_child_status * child_status;
|
||||||
|
|
||||||
|
|
||||||
struct iovec * m_pIovec;
|
struct iovec * m_pIovec;
|
||||||
|
@ -395,6 +396,12 @@ void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf);
|
||||||
|
|
||||||
int LSAPI_Inc_Req_Processed(int cnt);
|
int LSAPI_Inc_Req_Processed(int cnt);
|
||||||
|
|
||||||
|
int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq);
|
||||||
|
|
||||||
|
int LSAPI_Postfork_Child(LSAPI_Request * pReq);
|
||||||
|
|
||||||
|
int LSAPI_Postfork_Parent(LSAPI_Request * pReq);
|
||||||
|
|
||||||
#define LSAPI_LOG_LEVEL_BITS 0xff
|
#define LSAPI_LOG_LEVEL_BITS 0xff
|
||||||
#define LSAPI_LOG_FLAG_NONE 0
|
#define LSAPI_LOG_FLAG_NONE 0
|
||||||
#define LSAPI_LOG_FLAG_DEBUG 1
|
#define LSAPI_LOG_FLAG_DEBUG 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue