Update to 3.14.5
Patch 481 merged upstream (cherry picked from Fedora commit fc230a4cf121ce0218e4f307790abe727664c21f) Resolves: RHEL-180642
This commit is contained in:
parent
073c905275
commit
d83d13bd82
@ -1,587 +0,0 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Pablo Galindo Salgado <Pablogsal@gmail.com>
|
|
||||||
Date: Mon, 13 Apr 2026 23:22:23 +0100
|
|
||||||
Subject: 00481: CVE-2026-5713
|
|
||||||
|
|
||||||
Validate remote debug offset tables on load
|
|
||||||
---
|
|
||||||
...-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst | 2 +
|
|
||||||
Modules/_remote_debugging_module.c | 509 +++++++++++++++++-
|
|
||||||
2 files changed, 505 insertions(+), 6 deletions(-)
|
|
||||||
create mode 100644 Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
|
|
||||||
|
|
||||||
diff --git a/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..ed138a54a8
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/Misc/NEWS.d/next/Security/2026-04-06-13-55-00.gh-issue-148178.Rs7kLm.rst
|
|
||||||
@@ -0,0 +1,2 @@
|
|
||||||
+Hardened :mod:`!_remote_debugging` by validating remote debug offset tables
|
|
||||||
+before using them to size memory reads or interpret remote layouts.
|
|
||||||
diff --git a/Modules/_remote_debugging_module.c b/Modules/_remote_debugging_module.c
|
|
||||||
index a327772258..d756ac326f 100644
|
|
||||||
--- a/Modules/_remote_debugging_module.c
|
|
||||||
+++ b/Modules/_remote_debugging_module.c
|
|
||||||
@@ -20,6 +20,7 @@
|
|
||||||
#include <internal/pycore_interpframe.h> // FRAME_OWNED_BY_CSTACK
|
|
||||||
#include <internal/pycore_llist.h> // struct llist_node
|
|
||||||
#include <internal/pycore_stackref.h> // Py_TAG_BITS
|
|
||||||
+#include <internal/pycore_tstate.h> // _PyThreadStateImpl
|
|
||||||
#include "../Python/remote_debug.h"
|
|
||||||
|
|
||||||
// gh-141784: Python.h header must be included first, before system headers.
|
|
||||||
@@ -41,9 +42,11 @@
|
|
||||||
* TYPE DEFINITIONS AND STRUCTURES
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
-#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset)))
|
|
||||||
+#define GET_MEMBER(type, obj, offset) \
|
|
||||||
+ (*(type *)memcpy(&(type){0}, (const char *)(obj) + (offset), sizeof(type)))
|
|
||||||
#define CLEAR_PTR_TAG(ptr) (((uintptr_t)(ptr) & ~Py_TAG_BITS))
|
|
||||||
-#define GET_MEMBER_NO_TAG(type, obj, offset) (type)(CLEAR_PTR_TAG(*(type*)((char*)(obj) + (offset))))
|
|
||||||
+#define GET_MEMBER_NO_TAG(type, obj, offset) \
|
|
||||||
+ (type)(CLEAR_PTR_TAG(GET_MEMBER(type, obj, offset)))
|
|
||||||
|
|
||||||
/* Size macros for opaque buffers */
|
|
||||||
#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
|
|
||||||
@@ -107,6 +110,486 @@ struct _Py_AsyncioModuleDebugOffsets {
|
|
||||||
} asyncio_thread_state;
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* Treat the remote debug tables as untrusted input and validate every
|
|
||||||
+ * size/offset we later dereference against a fixed local buffer or object
|
|
||||||
+ * layout before the unwinder starts using them. */
|
|
||||||
+#define FIELD_SIZE(type, member) sizeof(((type *)0)->member)
|
|
||||||
+#define PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS (-2)
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_section_size(const char *section_name, uint64_t size)
|
|
||||||
+{
|
|
||||||
+ if (size == 0) {
|
|
||||||
+ PyErr_Format(
|
|
||||||
+ PyExc_RuntimeError,
|
|
||||||
+ "Invalid debug offsets: %s.size must be greater than zero",
|
|
||||||
+ section_name);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_read_size(const char *section_name, uint64_t size, size_t buffer_size)
|
|
||||||
+{
|
|
||||||
+ if (validate_section_size(section_name, size) < 0) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ if (size > buffer_size) {
|
|
||||||
+ PyErr_Format(
|
|
||||||
+ PyExc_RuntimeError,
|
|
||||||
+ "Invalid debug offsets: %s.size=%llu exceeds local buffer size %zu",
|
|
||||||
+ section_name,
|
|
||||||
+ (unsigned long long)size,
|
|
||||||
+ buffer_size);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_span(
|
|
||||||
+ const char *field_name,
|
|
||||||
+ uint64_t offset,
|
|
||||||
+ size_t width,
|
|
||||||
+ uint64_t limit,
|
|
||||||
+ const char *limit_name)
|
|
||||||
+{
|
|
||||||
+ uint64_t span = (uint64_t)width;
|
|
||||||
+ if (span > limit || offset > limit - span) {
|
|
||||||
+ PyErr_Format(
|
|
||||||
+ PyExc_RuntimeError,
|
|
||||||
+ "Invalid debug offsets: %s=%llu with width %zu exceeds %s %llu",
|
|
||||||
+ field_name,
|
|
||||||
+ (unsigned long long)offset,
|
|
||||||
+ width,
|
|
||||||
+ limit_name,
|
|
||||||
+ (unsigned long long)limit);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_alignment(
|
|
||||||
+ const char *field_name,
|
|
||||||
+ uint64_t offset,
|
|
||||||
+ size_t alignment)
|
|
||||||
+{
|
|
||||||
+ if (alignment > 1 && offset % alignment != 0) {
|
|
||||||
+ PyErr_Format(
|
|
||||||
+ PyExc_RuntimeError,
|
|
||||||
+ "Invalid debug offsets: %s=%llu is not aligned to %zu bytes",
|
|
||||||
+ field_name,
|
|
||||||
+ (unsigned long long)offset,
|
|
||||||
+ alignment);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_field(
|
|
||||||
+ const char *field_name,
|
|
||||||
+ uint64_t offset,
|
|
||||||
+ uint64_t reported_size,
|
|
||||||
+ size_t width,
|
|
||||||
+ size_t alignment,
|
|
||||||
+ size_t buffer_size)
|
|
||||||
+{
|
|
||||||
+ if (validate_alignment(field_name, offset, alignment) < 0) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ if (validate_span(field_name, offset, width, reported_size, "reported size") < 0) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return validate_span(field_name, offset, width, buffer_size, "local buffer size");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_fixed_field(
|
|
||||||
+ const char *field_name,
|
|
||||||
+ uint64_t offset,
|
|
||||||
+ size_t width,
|
|
||||||
+ size_t alignment,
|
|
||||||
+ size_t buffer_size)
|
|
||||||
+{
|
|
||||||
+ if (validate_alignment(field_name, offset, alignment) < 0) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ return validate_span(field_name, offset, width, buffer_size, "local buffer size");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define PY_REMOTE_DEBUG_VALIDATE_SECTION(section) \
|
|
||||||
+ do { \
|
|
||||||
+ if (validate_section_size(#section, debug_offsets->section.size) < 0) { \
|
|
||||||
+ return -1; \
|
|
||||||
+ } \
|
|
||||||
+ } while (0)
|
|
||||||
+
|
|
||||||
+#define PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(section, buffer_size) \
|
|
||||||
+ do { \
|
|
||||||
+ if (validate_read_size(#section, debug_offsets->section.size, buffer_size) < 0) { \
|
|
||||||
+ return -1; \
|
|
||||||
+ } \
|
|
||||||
+ } while (0)
|
|
||||||
+
|
|
||||||
+#define PY_REMOTE_DEBUG_VALIDATE_FIELD(section, field, field_size, field_alignment, buffer_size) \
|
|
||||||
+ do { \
|
|
||||||
+ if (validate_field( \
|
|
||||||
+ #section "." #field, \
|
|
||||||
+ debug_offsets->section.field, \
|
|
||||||
+ debug_offsets->section.size, \
|
|
||||||
+ field_size, \
|
|
||||||
+ field_alignment, \
|
|
||||||
+ buffer_size) < 0) { \
|
|
||||||
+ return -1; \
|
|
||||||
+ } \
|
|
||||||
+ } while (0)
|
|
||||||
+
|
|
||||||
+#define PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(section, field, field_size, field_alignment, buffer_size) \
|
|
||||||
+ do { \
|
|
||||||
+ if (validate_fixed_field( \
|
|
||||||
+ #section "." #field, \
|
|
||||||
+ debug_offsets->section.field, \
|
|
||||||
+ field_size, \
|
|
||||||
+ field_alignment, \
|
|
||||||
+ buffer_size) < 0) { \
|
|
||||||
+ return -1; \
|
|
||||||
+ } \
|
|
||||||
+ } while (0)
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_debug_offsets_layout(struct _Py_DebugOffsets *debug_offsets)
|
|
||||||
+{
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(runtime_state);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ runtime_state,
|
|
||||||
+ interpreters_head,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ sizeof(_PyRuntimeState));
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_state);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ threads_head,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ threads_main,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ gil_runtime_state_locked,
|
|
||||||
+ sizeof(int),
|
|
||||||
+ _Alignof(int),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ gil_runtime_state_holder,
|
|
||||||
+ sizeof(PyThreadState *),
|
|
||||||
+ _Alignof(PyThreadState *),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ code_object_generation,
|
|
||||||
+ sizeof(uint64_t),
|
|
||||||
+ _Alignof(uint64_t),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_state,
|
|
||||||
+ tlbc_generation,
|
|
||||||
+ sizeof(uint32_t),
|
|
||||||
+ _Alignof(uint32_t),
|
|
||||||
+ INTERP_STATE_BUFFER_SIZE);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(thread_state, SIZEOF_THREAD_STATE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ thread_state,
|
|
||||||
+ next,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_THREAD_STATE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ thread_state,
|
|
||||||
+ current_frame,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_THREAD_STATE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ thread_state,
|
|
||||||
+ native_thread_id,
|
|
||||||
+ sizeof(unsigned long),
|
|
||||||
+ _Alignof(unsigned long),
|
|
||||||
+ SIZEOF_THREAD_STATE);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ thread_state,
|
|
||||||
+ datastack_chunk,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_THREAD_STATE);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(interpreter_frame);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ previous,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ executable,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ instr_ptr,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ owner,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ stackpointer,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ interpreter_frame,
|
|
||||||
+ tlbc_index,
|
|
||||||
+ sizeof(int32_t),
|
|
||||||
+ _Alignof(int32_t),
|
|
||||||
+ SIZEOF_INTERP_FRAME);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(code_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ qualname,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ filename,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ linetable,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ firstlineno,
|
|
||||||
+ sizeof(int),
|
|
||||||
+ _Alignof(int),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ co_code_adaptive,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ code_object,
|
|
||||||
+ co_tlbc,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_CODE_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(pyobject);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ pyobject,
|
|
||||||
+ ob_type,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_PYOBJECT);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(type_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ type_object,
|
|
||||||
+ tp_flags,
|
|
||||||
+ sizeof(unsigned long),
|
|
||||||
+ _Alignof(unsigned long),
|
|
||||||
+ SIZEOF_TYPE_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(set_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ set_object,
|
|
||||||
+ used,
|
|
||||||
+ sizeof(Py_ssize_t),
|
|
||||||
+ _Alignof(Py_ssize_t),
|
|
||||||
+ SIZEOF_SET_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ set_object,
|
|
||||||
+ mask,
|
|
||||||
+ sizeof(Py_ssize_t),
|
|
||||||
+ _Alignof(Py_ssize_t),
|
|
||||||
+ SIZEOF_SET_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ set_object,
|
|
||||||
+ table,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_SET_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(long_object, SIZEOF_LONG_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ long_object,
|
|
||||||
+ lv_tag,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_LONG_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ long_object,
|
|
||||||
+ ob_digit,
|
|
||||||
+ sizeof(digit),
|
|
||||||
+ _Alignof(digit),
|
|
||||||
+ SIZEOF_LONG_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(bytes_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ bytes_object,
|
|
||||||
+ ob_size,
|
|
||||||
+ sizeof(Py_ssize_t),
|
|
||||||
+ _Alignof(Py_ssize_t),
|
|
||||||
+ SIZEOF_BYTES_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ bytes_object,
|
|
||||||
+ ob_sval,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_BYTES_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(unicode_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ unicode_object,
|
|
||||||
+ length,
|
|
||||||
+ sizeof(Py_ssize_t),
|
|
||||||
+ _Alignof(Py_ssize_t),
|
|
||||||
+ SIZEOF_UNICODE_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ unicode_object,
|
|
||||||
+ asciiobject_size,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_UNICODE_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(gen_object);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ gen_object,
|
|
||||||
+ gi_frame_state,
|
|
||||||
+ sizeof(int8_t),
|
|
||||||
+ _Alignof(int8_t),
|
|
||||||
+ SIZEOF_GEN_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ gen_object,
|
|
||||||
+ gi_iframe,
|
|
||||||
+ FIELD_SIZE(PyGenObject, gi_iframe),
|
|
||||||
+ _Alignof(_PyInterpreterFrame),
|
|
||||||
+ SIZEOF_GEN_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD(
|
|
||||||
+ llist_node,
|
|
||||||
+ next,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_LLIST_NODE);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int
|
|
||||||
+validate_async_debug_offsets_layout(struct _Py_AsyncioModuleDebugOffsets *debug_offsets)
|
|
||||||
+{
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_READ_SECTION(asyncio_task_object, SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_name,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_awaited_by,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_is_task,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_awaited_by_is_set,
|
|
||||||
+ sizeof(char),
|
|
||||||
+ _Alignof(char),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_coro,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_task_object,
|
|
||||||
+ task_node,
|
|
||||||
+ SIZEOF_LLIST_NODE,
|
|
||||||
+ _Alignof(struct llist_node),
|
|
||||||
+ SIZEOF_TASK_OBJ);
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_interpreter_state);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_interpreter_state,
|
|
||||||
+ asyncio_tasks_head,
|
|
||||||
+ SIZEOF_LLIST_NODE,
|
|
||||||
+ _Alignof(struct llist_node),
|
|
||||||
+ sizeof(PyInterpreterState));
|
|
||||||
+
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_SECTION(asyncio_thread_state);
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_thread_state,
|
|
||||||
+ asyncio_running_loop,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ sizeof(_PyThreadStateImpl));
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_thread_state,
|
|
||||||
+ asyncio_running_task,
|
|
||||||
+ sizeof(uintptr_t),
|
|
||||||
+ _Alignof(uintptr_t),
|
|
||||||
+ sizeof(_PyThreadStateImpl));
|
|
||||||
+ PY_REMOTE_DEBUG_VALIDATE_FIELD(
|
|
||||||
+ asyncio_thread_state,
|
|
||||||
+ asyncio_tasks_head,
|
|
||||||
+ SIZEOF_LLIST_NODE,
|
|
||||||
+ _Alignof(struct llist_node),
|
|
||||||
+ sizeof(_PyThreadStateImpl));
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#undef PY_REMOTE_DEBUG_VALIDATE_SECTION
|
|
||||||
+#undef PY_REMOTE_DEBUG_VALIDATE_READ_SECTION
|
|
||||||
+#undef PY_REMOTE_DEBUG_VALIDATE_FIELD
|
|
||||||
+#undef PY_REMOTE_DEBUG_VALIDATE_FIXED_FIELD
|
|
||||||
+#undef FIELD_SIZE
|
|
||||||
+
|
|
||||||
/* ============================================================================
|
|
||||||
* STRUCTSEQ TYPE DEFINITIONS
|
|
||||||
* ============================================================================ */
|
|
||||||
@@ -434,7 +917,7 @@ validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ return validate_debug_offsets_layout(debug_offsets);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic function to iterate through all threads
|
|
||||||
@@ -877,8 +1360,13 @@ read_async_debug(
|
|
||||||
int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, async_debug_addr, size, &unwinder->async_debug_offsets);
|
|
||||||
if (result < 0) {
|
|
||||||
set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read AsyncioDebug offsets");
|
|
||||||
+ return result;
|
|
||||||
}
|
|
||||||
- return result;
|
|
||||||
+ if (validate_async_debug_offsets_layout(&unwinder->async_debug_offsets) < 0) {
|
|
||||||
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid AsyncioDebug offsets");
|
|
||||||
+ return PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
@@ -2054,10 +2542,15 @@ static void *
|
|
||||||
find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < chunks->count; ++i) {
|
|
||||||
+ if (chunks->chunks[i].size <= offsetof(_PyStackChunk, data)) {
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
uintptr_t base = chunks->chunks[i].remote_addr + offsetof(_PyStackChunk, data);
|
|
||||||
size_t payload = chunks->chunks[i].size - offsetof(_PyStackChunk, data);
|
|
||||||
|
|
||||||
- if (remote_ptr >= base && remote_ptr < base + payload) {
|
|
||||||
+ if (payload >= SIZEOF_INTERP_FRAME &&
|
|
||||||
+ remote_ptr >= base &&
|
|
||||||
+ remote_ptr <= base + payload - SIZEOF_INTERP_FRAME) {
|
|
||||||
return (char *)chunks->chunks[i].local_copy + (remote_ptr - chunks->chunks[i].remote_addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2624,7 +3117,11 @@ _remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
|
|
||||||
|
|
||||||
// Try to read async debug offsets, but don't fail if they're not available
|
|
||||||
self->async_debug_offsets_available = 1;
|
|
||||||
- if (read_async_debug(self) < 0) {
|
|
||||||
+ int async_debug_result = read_async_debug(self);
|
|
||||||
+ if (async_debug_result == PY_REMOTE_DEBUG_INVALID_ASYNC_DEBUG_OFFSETS) {
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ if (async_debug_result < 0) {
|
|
||||||
PyErr_Clear();
|
|
||||||
memset(&self->async_debug_offsets, 0, sizeof(self->async_debug_offsets));
|
|
||||||
self->async_debug_offsets_available = 0;
|
|
||||||
@ -46,7 +46,7 @@ URL: https://www.python.org/
|
|||||||
# WARNING When rebasing to a new Python version,
|
# WARNING When rebasing to a new Python version,
|
||||||
# remember to update the python3-docs package as well
|
# remember to update the python3-docs package as well
|
||||||
%global general_version %{pybasever}.5
|
%global general_version %{pybasever}.5
|
||||||
%global prerel rc1
|
#global prerel ...
|
||||||
%global upstream_version %{general_version}%{?prerel}
|
%global upstream_version %{general_version}%{?prerel}
|
||||||
Version: %{general_version}%{?prerel:~%{prerel}}
|
Version: %{general_version}%{?prerel:~%{prerel}}
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
@ -109,7 +109,7 @@ License: Python-2.0.1
|
|||||||
# This needs to be manually updated when we update Python.
|
# This needs to be manually updated when we update Python.
|
||||||
# Explore the sources tarball (you need the version before %%prep is executed):
|
# Explore the sources tarball (you need the version before %%prep is executed):
|
||||||
# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl
|
# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl
|
||||||
%global pip_version 26.1
|
%global pip_version 26.1.1
|
||||||
%global setuptools_version 79.0.1
|
%global setuptools_version 79.0.1
|
||||||
# All of those also include a list of indirect bundled libs:
|
# All of those also include a list of indirect bundled libs:
|
||||||
# pip
|
# pip
|
||||||
@ -434,12 +434,6 @@ Patch475: 00475-cve-2025-15367.patch
|
|||||||
# direct call to the check function.
|
# direct call to the check function.
|
||||||
Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch
|
Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-different-python-version.patch
|
||||||
|
|
||||||
# 00481 # 4c1fd39918651c4559a4835d42b86639a192c2c5
|
|
||||||
# CVE-2026-5713
|
|
||||||
#
|
|
||||||
# Validate remote debug offset tables on load
|
|
||||||
Patch481: 00481-cve-2026-5713.patch
|
|
||||||
|
|
||||||
# (New patches go here ^^^)
|
# (New patches go here ^^^)
|
||||||
#
|
#
|
||||||
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
||||||
@ -1962,6 +1956,10 @@ CheckPython freethreading
|
|||||||
# ======================================================
|
# ======================================================
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Jun 09 2026 Miro Hrončok <mhroncok@redhat.com> - 3.14.5-1
|
||||||
|
- Update to 3.14.5
|
||||||
|
Resolves: RHEL-180642
|
||||||
|
|
||||||
* Tue Jun 09 2026 Miro Hrončok <mhroncok@redhat.com> - 3.14.5~rc1-1
|
* Tue Jun 09 2026 Miro Hrončok <mhroncok@redhat.com> - 3.14.5~rc1-1
|
||||||
- Update to 3.14.5rc1
|
- Update to 3.14.5rc1
|
||||||
- Move back to the generational from the incremental garbage collector
|
- Move back to the generational from the incremental garbage collector
|
||||||
|
|||||||
2
sources
2
sources
@ -1 +1 @@
|
|||||||
SHA512 (Python-3.14.5rc1.tar.xz) = 67ede84d59046e3b413643449a7eced8cefcd908238b8a34d2ac38507d967201695c62c22464f1bfd51669daf306995262279c7bbfc5a25998ed867a3d743b38
|
SHA512 (Python-3.14.5.tar.xz) = efbaf629703cd004f6b7bc75fb16df794185589adaf8807cd45928f212271045a399df3cd9573e47c8708fb5c5002f9d4efe4e41dde4313b81a3e9d73158769f
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user