Merge branch 'PHP-8.1' into PHP-8.2

* PHP-8.1:
  Fix Windows shmget() wrt. IPC_PRIVATE
This commit is contained in:
Christoph M. Becker 2022-12-13 15:48:58 +01:00
commit 9089e15940
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
2 changed files with 36 additions and 0 deletions

3
NEWS
View file

@ -58,6 +58,9 @@ PHP NEWS
- SQLite3:
. Fixed bug #81742 (open_basedir bypass in SQLite3 by using file URI). (cmb)
- TSRM:
. Fixed Windows shmget() wrt. IPC_PRIVATE. (Tyson Andre)
08 Dec 2022, PHP 8.2.0
- CLI:

View file

@ -30,6 +30,7 @@
#include "tsrm_win32.h"
#include "zend_virtual_cwd.h"
#include "win32/ioutil.h"
#include "win32/winutil.h"
#ifdef ZTS
static ts_rsrc_id win32_globals_id;
@ -610,6 +611,22 @@ TSRM_API int pclose(FILE *stream)
#define SEGMENT_PREFIX "TSRM_SHM_SEGMENT:"
#define INT_MIN_AS_STRING "-2147483648"
#define TSRM_BASE_SHM_KEY_ADDRESS 0x20000000
/* Returns a number between 0x2000_0000 and 0x3fff_ffff. On Windows, key_t is int. */
static key_t tsrm_choose_random_shm_key(key_t prev_key) {
unsigned char buf[4];
if (php_win32_get_random_bytes(buf, 4) != SUCCESS) {
return prev_key + 2;
}
uint32_t n =
((uint32_t)(buf[0]) << 24) |
(((uint32_t)buf[1]) << 16) |
(((uint32_t)buf[2]) << 8) |
(((uint32_t)buf[3]));
return (n & 0x1fffffff) + TSRM_BASE_SHM_KEY_ADDRESS;
}
TSRM_API int shmget(key_t key, size_t size, int flags)
{/*{{{*/
shm_pair *shm;
@ -621,6 +638,9 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
snprintf(shm_segment, sizeof(shm_segment), SEGMENT_PREFIX "%d", key);
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
} else {
/* IPC_PRIVATE always creates a new segment even if IPC_CREAT flag isn't passed. */
flags |= IPC_CREAT;
}
if (!shm_handle) {
@ -649,6 +669,19 @@ TSRM_API int shmget(key_t key, size_t size, int flags)
}
}
if (key == IPC_PRIVATE) {
/* This should call shm_get with a brand new key id that isn't used yet. See https://man7.org/linux/man-pages/man2/shmget.2.html
* Because extensions such as shmop/sysvshm can be used in userland to attach to shared memory segments, use unpredictable high positive numbers to avoid accidentally conflicting with userland. */
key = tsrm_choose_random_shm_key(TSRM_BASE_SHM_KEY_ADDRESS);
for (shm_pair *ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
if (ptr->descriptor && ptr->descriptor->shm_perm.key == key) {
key = tsrm_choose_random_shm_key(key);
ptr = TWG(shm);
continue;
}
}
}
shm = shm_get(key, NULL);
if (!shm) {
CloseHandle(shm_handle);