Patch fmp_scoreboard_proc_oob_v1.patch for FPM related Bug #81026
Patch version 2021-05-31 13:32 UTC
Return to Bug #81026 |
Download this patch
Patch Revisions:
Developer: bukka@php.net
From 61f3c6e4461975f3b24b96a998c7ce789534d0f5 Mon Sep 17 00:00:00 2001
From: Jakub Zelenka <bukka@php.net>
Date: Mon, 31 May 2021 14:26:09 +0100
Subject: [PATCH] Fix bug #81026 (PHP-FPM oob R/W in root process leading to
privilege escalation)
---
sapi/fpm/fpm/fpm_request.c | 6 +++---
sapi/fpm/fpm/fpm_scoreboard.c | 35 +++++++++++++++++++++++++++++++++++
sapi/fpm/fpm/fpm_scoreboard.h | 2 ++
3 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
index 83401f1553..540949b026 100644
--- a/sapi/fpm/fpm/fpm_request.c
+++ b/sapi/fpm/fpm/fpm_request.c
@@ -227,7 +227,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
{
struct fpm_scoreboard_proc_s proc, *proc_p;
- proc_p = fpm_scoreboard_proc_acquire(child->wp->scoreboard, child->scoreboard_i, 1);
+ proc_p = fpm_scoreboard_proc_acquire_from_child(child, 1);
if (!proc_p) {
zlog(ZLOG_WARNING, "failed to acquire scoreboard");
return;
@@ -287,7 +287,7 @@ int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */
struct fpm_scoreboard_proc_s *proc;
/* no need in atomicity here */
- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
+ proc = fpm_scoreboard_proc_get_from_child(child);
if (!proc) {
return 0;
}
@@ -302,7 +302,7 @@ int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /*
if (!tv) return -1;
- proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
+ proc = fpm_scoreboard_proc_get_from_child(child);
if (!proc) {
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
index 328f999f0c..b26e503f9c 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.c
+++ b/sapi/fpm/fpm/fpm_scoreboard.c
@@ -6,6 +6,7 @@
#include <time.h>
#include "fpm_config.h"
+#include "fpm_children.h"
#include "fpm_scoreboard.h"
#include "fpm_shm.h"
#include "fpm_sockets.h"
@@ -184,6 +185,23 @@ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *s
}
/* }}} */
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child) /* {{{*/
+{
+ struct fpm_worker_pool_s *wp = child->wp;
+ struct fpm_scoreboard_proc_s *proc = fpm_scoreboard_proc_get(wp->scoreboard, child->scoreboard_i);
+ ptrdiff_t proc_start = (uintptr_t) wp->scoreboard + sizeof(struct fpm_scoreboard_s);
+ ptrdiff_t proc_end = sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children - 1) * sizeof(struct fpm_scoreboard_proc_s *);
+ uintptr_t proc_position = (uintptr_t) proc;
+
+ if (proc_position < proc_start || proc_position > proc_end) {
+ zlog(ZLOG_WARNING, "failed to get proc from the child scoreboard because the proc pointer is invalid");
+ return NULL;
+ }
+
+ return proc;
+}
+/* }}} */
+
struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */
{
struct fpm_scoreboard_s *s;
@@ -225,6 +243,23 @@ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_
}
/* }}} */
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire_from_child(struct fpm_child_s *child, int nohang) /* {{{ */
+{
+ struct fpm_scoreboard_proc_s *proc;
+
+ proc = fpm_scoreboard_proc_get_from_child(child);
+ if (!proc) {
+ return NULL;
+ }
+
+ if (!fpm_spinlock(&proc->lock, nohang)) {
+ return NULL;
+ }
+
+ return proc;
+}
+/* }}} */
+
void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */
{
if (!proc) {
diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
index 1fecde1d0f..ff7ed1806d 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.h
+++ b/sapi/fpm/fpm/fpm_scoreboard.h
@@ -72,10 +72,12 @@ int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp);
void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int slow_rq, int action, struct fpm_scoreboard_s *scoreboard);
struct fpm_scoreboard_s *fpm_scoreboard_get();
struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index);
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_child_s *child);
struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang);
void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard);
struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang);
+struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire_from_child(struct fpm_child_s *child, int nohang);
void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc);
void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard);
--
2.25.1
|