Skip to content

Commit 49087a6

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
2 parents c03e111 + 29fe06f commit 49087a6

File tree

4 files changed

+132
-75
lines changed

4 files changed

+132
-75
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ PHP NEWS
99
- GD:
1010
. Fixed libpng warning when loading interlaced images. (Brett)
1111

12+
- FPM:
13+
. Fixed bug #76109 (Unsafe access to fpm scoreboard).
14+
(Till Backhaus, Jakub Zelenka)
15+
1216
- Iconv:
1317
. Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb)
1418
. Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb)

sapi/fpm/fpm/fpm_scoreboard.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,63 @@ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
226226
scoreboard->lock = 0;
227227
}
228228

229+
struct fpm_scoreboard_s *fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard, int copy_procs)
230+
{
231+
struct fpm_scoreboard_s *scoreboard_copy;
232+
struct fpm_scoreboard_proc_s *scoreboard_proc_p;
233+
size_t scoreboard_size, scoreboard_nprocs_size;
234+
int i;
235+
void *mem;
236+
237+
if (!scoreboard) {
238+
scoreboard = fpm_scoreboard_get();
239+
}
240+
241+
if (copy_procs) {
242+
scoreboard_size = sizeof(struct fpm_scoreboard_s);
243+
scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * scoreboard->nprocs;
244+
245+
mem = malloc(scoreboard_size + scoreboard_nprocs_size);
246+
} else {
247+
mem = malloc(sizeof(struct fpm_scoreboard_s));
248+
}
249+
250+
if (!mem) {
251+
zlog(ZLOG_ERROR, "scoreboard: failed to allocate memory for copy");
252+
return NULL;
253+
}
254+
255+
scoreboard_copy = mem;
256+
257+
scoreboard = fpm_scoreboard_acquire(scoreboard, FPM_SCOREBOARD_LOCK_NOHANG);
258+
if (!scoreboard) {
259+
free(mem);
260+
zlog(ZLOG_ERROR, "scoreboard: failed to lock (already locked)");
261+
return NULL;
262+
}
263+
264+
*scoreboard_copy = *scoreboard;
265+
266+
if (copy_procs) {
267+
mem += scoreboard_size;
268+
269+
for (i = 0; i < scoreboard->nprocs; i++, mem += sizeof(struct fpm_scoreboard_proc_s)) {
270+
scoreboard_proc_p = fpm_scoreboard_proc_acquire(scoreboard, i, FPM_SCOREBOARD_LOCK_HANG);
271+
scoreboard_copy->procs[i] = *scoreboard_proc_p;
272+
fpm_scoreboard_proc_release(scoreboard_proc_p);
273+
}
274+
}
275+
276+
fpm_scoreboard_release(scoreboard);
277+
278+
return scoreboard_copy;
279+
}
280+
281+
void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard)
282+
{
283+
free(scoreboard);
284+
}
285+
229286
struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */
230287
{
231288
struct fpm_scoreboard_proc_s *proc;

sapi/fpm/fpm/fpm_scoreboard.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#define FPM_SCOREBOARD_ACTION_SET 0
1616
#define FPM_SCOREBOARD_ACTION_INC 1
1717

18+
#define FPM_SCOREBOARD_LOCK_HANG 0
19+
#define FPM_SCOREBOARD_LOCK_NOHANG 1
20+
1821
struct fpm_scoreboard_proc_s {
1922
union {
2023
atomic_t lock;
@@ -87,6 +90,9 @@ void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid);
8790
void fpm_scoreboard_proc_free(struct fpm_child_s *child);
8891
int fpm_scoreboard_proc_alloc(struct fpm_child_s *child);
8992

93+
struct fpm_scoreboard_s *fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard, int copy_procs);
94+
void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard);
95+
9096
#ifdef HAVE_TIMES
9197
float fpm_scoreboard_get_tick(void);
9298
#endif

sapi/fpm/fpm/fpm_status.c

Lines changed: 65 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ int fpm_status_export_to_zval(zval *status)
136136

137137
int fpm_status_handle_request(void) /* {{{ */
138138
{
139-
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
140-
struct fpm_scoreboard_proc_s proc;
139+
struct fpm_scoreboard_s *scoreboard_p;
140+
struct fpm_scoreboard_proc_s *proc;
141141
char *buffer, *time_format, time_buffer[64];
142142
time_t now_epoch;
143143
int full, encode, has_start_time;
@@ -170,9 +170,17 @@ int fpm_status_handle_request(void) /* {{{ */
170170
if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) {
171171
fpm_request_executing();
172172

173+
/* full status ? */
174+
_GET_str = zend_string_init("_GET", sizeof("_GET")-1, 0);
175+
full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL);
176+
short_syntax = short_post = NULL;
177+
full_separator = full_pre = full_syntax = full_post = NULL;
178+
encode = 0;
179+
has_start_time = 1;
180+
173181
scoreboard_p = fpm_scoreboard_get();
174-
if (scoreboard_p->shared) {
175-
scoreboard_p = scoreboard_p->shared;
182+
if (scoreboard_p) {
183+
scoreboard_p = fpm_scoreboard_copy(scoreboard_p->shared ? scoreboard_p->shared : scoreboard_p, full);
176184
}
177185
if (!scoreboard_p) {
178186
zlog(ZLOG_ERROR, "status: unable to find or access status shared memory");
@@ -184,21 +192,9 @@ int fpm_status_handle_request(void) /* {{{ */
184192
return 1;
185193
}
186194

187-
if (!fpm_spinlock(&scoreboard_p->lock, 1)) {
188-
zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool);
189-
SG(sapi_headers).http_response_code = 503;
190-
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1);
191-
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1);
192-
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1);
193-
PUTS("Server busy. Please try again later.");
194-
return 1;
195-
}
196-
/* copy the scoreboard not to bother other processes */
197-
scoreboard = *scoreboard_p;
198-
fpm_unlock(scoreboard_p->lock);
199-
200-
if (scoreboard.idle < 0 || scoreboard.active < 0) {
201-
zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool);
195+
if (scoreboard_p->idle < 0 || scoreboard_p->active < 0) {
196+
fpm_scoreboard_free_copy(scoreboard_p);
197+
zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard_p->pool);
202198
SG(sapi_headers).http_response_code = 500;
203199
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1);
204200
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1);
@@ -214,17 +210,10 @@ int fpm_status_handle_request(void) /* {{{ */
214210

215211
/* handle HEAD */
216212
if (SG(request_info).headers_only) {
213+
fpm_scoreboard_free_copy(scoreboard_p);
217214
return 1;
218215
}
219216

220-
/* full status ? */
221-
_GET_str = zend_string_init("_GET", sizeof("_GET")-1, 0);
222-
full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL);
223-
short_syntax = short_post = NULL;
224-
full_separator = full_pre = full_syntax = full_post = NULL;
225-
encode = 0;
226-
has_start_time = 1;
227-
228217
/* HTML */
229218
if (fpm_php_get_string_from_table(_GET_str, "html")) {
230219
sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1);
@@ -486,37 +475,37 @@ int fpm_status_handle_request(void) /* {{{ */
486475

487476
now_epoch = time(NULL);
488477
if (has_start_time) {
489-
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch));
478+
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard_p->start_epoch));
490479
spprintf(&buffer, 0, short_syntax,
491-
scoreboard.pool,
492-
PM2STR(scoreboard.pm),
480+
scoreboard_p->pool,
481+
PM2STR(scoreboard_p->pm),
493482
time_buffer,
494-
(unsigned long) (now_epoch - scoreboard.start_epoch),
495-
scoreboard.requests,
496-
scoreboard.lq,
497-
scoreboard.lq_max,
498-
scoreboard.lq_len,
499-
scoreboard.idle,
500-
scoreboard.active,
501-
scoreboard.idle + scoreboard.active,
502-
scoreboard.active_max,
503-
scoreboard.max_children_reached,
504-
scoreboard.slow_rq);
483+
(unsigned long) (now_epoch - scoreboard_p->start_epoch),
484+
scoreboard_p->requests,
485+
scoreboard_p->lq,
486+
scoreboard_p->lq_max,
487+
scoreboard_p->lq_len,
488+
scoreboard_p->idle,
489+
scoreboard_p->active,
490+
scoreboard_p->idle + scoreboard_p->active,
491+
scoreboard_p->active_max,
492+
scoreboard_p->max_children_reached,
493+
scoreboard_p->slow_rq);
505494
} else {
506495
spprintf(&buffer, 0, short_syntax,
507-
scoreboard.pool,
508-
PM2STR(scoreboard.pm),
509-
(unsigned long) (now_epoch - scoreboard.start_epoch),
510-
scoreboard.requests,
511-
scoreboard.lq,
512-
scoreboard.lq_max,
513-
scoreboard.lq_len,
514-
scoreboard.idle,
515-
scoreboard.active,
516-
scoreboard.idle + scoreboard.active,
517-
scoreboard.active_max,
518-
scoreboard.max_children_reached,
519-
scoreboard.slow_rq);
496+
scoreboard_p->pool,
497+
PM2STR(scoreboard_p->pm),
498+
(unsigned long) (now_epoch - scoreboard_p->start_epoch),
499+
scoreboard_p->requests,
500+
scoreboard_p->lq,
501+
scoreboard_p->lq_max,
502+
scoreboard_p->lq_len,
503+
scoreboard_p->idle,
504+
scoreboard_p->active,
505+
scoreboard_p->idle + scoreboard_p->active,
506+
scoreboard_p->active_max,
507+
scoreboard_p->max_children_reached,
508+
scoreboard_p->slow_rq);
520509
}
521510

522511
PUTS(buffer);
@@ -547,7 +536,7 @@ int fpm_status_handle_request(void) /* {{{ */
547536
if (!scoreboard_p->procs[i].used) {
548537
continue;
549538
}
550-
proc = scoreboard_p->procs[i];
539+
proc = &scoreboard_p->procs[i];
551540

552541
if (first) {
553542
first = 0;
@@ -559,44 +548,44 @@ int fpm_status_handle_request(void) /* {{{ */
559548

560549
query_string = NULL;
561550
tmp_query_string = NULL;
562-
if (proc.query_string[0] != '\0') {
551+
if (proc->query_string[0] != '\0') {
563552
if (!encode) {
564-
query_string = proc.query_string;
553+
query_string = proc->query_string;
565554
} else {
566-
tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0);
555+
tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc->query_string, strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0);
567556
query_string = ZSTR_VAL(tmp_query_string);
568557
}
569558
}
570559

571560
/* prevent NaN */
572-
if (proc.cpu_duration.tv_sec == 0 && proc.cpu_duration.tv_usec == 0) {
561+
if (proc->cpu_duration.tv_sec == 0 && proc->cpu_duration.tv_usec == 0) {
573562
cpu = 0.;
574563
} else {
575-
cpu = (proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.;
564+
cpu = (proc->last_request_cpu.tms_utime + proc->last_request_cpu.tms_stime + proc->last_request_cpu.tms_cutime + proc->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc->cpu_duration.tv_sec + proc->cpu_duration.tv_usec / 1000000.) * 100.;
576565
}
577566

578-
if (proc.request_stage == FPM_REQUEST_ACCEPTING) {
579-
duration = proc.duration;
567+
if (proc->request_stage == FPM_REQUEST_ACCEPTING) {
568+
duration = proc->duration;
580569
} else {
581-
timersub(&now, &proc.accepted, &duration);
570+
timersub(&now, &proc->accepted, &duration);
582571
}
583-
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc.start_epoch));
572+
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc->start_epoch));
584573
spprintf(&buffer, 0, full_syntax,
585-
(int) proc.pid,
586-
fpm_request_get_stage_name(proc.request_stage),
574+
(int) proc->pid,
575+
fpm_request_get_stage_name(proc->request_stage),
587576
time_buffer,
588-
(unsigned long) (now_epoch - proc.start_epoch),
589-
proc.requests,
577+
(unsigned long) (now_epoch - proc->start_epoch),
578+
proc->requests,
590579
duration.tv_sec * 1000000UL + duration.tv_usec,
591-
proc.request_method[0] != '\0' ? proc.request_method : "-",
592-
proc.request_uri[0] != '\0' ? proc.request_uri : "-",
580+
proc->request_method[0] != '\0' ? proc->request_method : "-",
581+
proc->request_uri[0] != '\0' ? proc->request_uri : "-",
593582
query_string ? "?" : "",
594583
query_string ? query_string : "",
595-
proc.content_length,
596-
proc.auth_user[0] != '\0' ? proc.auth_user : "-",
597-
proc.script_filename[0] != '\0' ? proc.script_filename : "-",
598-
proc.request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.,
599-
proc.request_stage == FPM_REQUEST_ACCEPTING ? proc.memory : 0);
584+
proc->content_length,
585+
proc->auth_user[0] != '\0' ? proc->auth_user : "-",
586+
proc->script_filename[0] != '\0' ? proc->script_filename : "-",
587+
proc->request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.,
588+
proc->request_stage == FPM_REQUEST_ACCEPTING ? proc->memory : 0);
600589
PUTS(buffer);
601590
efree(buffer);
602591

@@ -610,6 +599,7 @@ int fpm_status_handle_request(void) /* {{{ */
610599
}
611600
}
612601

602+
fpm_scoreboard_free_copy(scoreboard_p);
613603
return 1;
614604
}
615605

0 commit comments

Comments
 (0)