Package: release.debian.org Severity: normal Tags: bookworm X-Debbugs-Cc: python3...@packages.debian.org, d...@debian.org Control: affects -1 + src:python3.11 User: release.debian....@packages.debian.org Usertags: pu
[ Reason ] A use-after-free causing a SEGV was found in python 3.11, affecting the the Zulip chat server. The bug is known to affect python 3.11.0 - 3.11.4. And since being fixed upstream, there have been no known related regressions. [ Impact ] Potential SEGV in python3. Known to be triggered by zulip's CI when running under coverage. [ Tests ] The Python stdlib testsuite is extensive and passes with this patch. There is a stand-alone reproducer that I've manually reproduced the bug with and verified that it's fixed. [ Risks ] The code is pretty straight-forward. It asserts that the f_frame hasn't already been freed before freeing. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable
diff -Nru python3.11-3.11.2/debian/changelog python3.11-3.11.2/debian/changelog --- python3.11-3.11.2/debian/changelog 2023-03-13 08:18:29.000000000 -0400 +++ python3.11-3.11.2/debian/changelog 2024-03-02 16:28:50.000000000 -0400 @@ -1,3 +1,11 @@ +python3.11 (3.11.2-6+deb12u1) bookworm; urgency=medium + + [ Anders Kaseorg ] + * Fix a use-after-free crash when deallocating a frame object + (closes: #1050843). + + -- Stefano Rivera <stefa...@debian.org> Sat, 02 Mar 2024 16:28:50 -0400 + python3.11 (3.11.2-6) unstable; urgency=high [ Stefano Rivera ] diff -Nru python3.11-3.11.2/debian/patches/frame_dealloc-crash.diff python3.11-3.11.2/debian/patches/frame_dealloc-crash.diff --- python3.11-3.11.2/debian/patches/frame_dealloc-crash.diff 1969-12-31 20:00:00.000000000 -0400 +++ python3.11-3.11.2/debian/patches/frame_dealloc-crash.diff 2024-03-02 16:28:50.000000000 -0400 @@ -0,0 +1,54 @@ +Description: Fix use-after-free crash in frame_dealloc + It was possible for the trashcan to delay the deallocation of a + PyFrameObject until after its corresponding _PyInterpreterFrame has + already been freed. So frame_dealloc needs to avoid dereferencing the + f_frame pointer unless it first checks that the pointer still points + to the interpreter frame within the frame object. +Origin: https://github.com/python/cpython/commit/46cae02085311481dc8b1ea9a5110969d9325bc7 +Bug-upstream: https://github.com/python/cpython/issues/106092 +Bug-Debian: https://bugs.debian.org/1050843 +Author: Anders Kaseorg <ande...@mit.edu> +Last-Update: 2023-08-29 +Applied-Upstream: 3.11.5 + +--- + .../2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst | 2 ++ + Objects/frameobject.c | 13 +++++++------ + 2 files changed, 9 insertions(+), 6 deletions(-) + create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst + +--- /dev/null ++++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-18-16-13-51.gh-issue-106092.bObgRM.rst +@@ -0,0 +1,2 @@ ++Fix a segmentation fault caused by a use-after-free bug in ``frame_dealloc`` ++when the trashcan delays the deallocation of a ``PyFrameObject``. +--- a/Objects/frameobject.c ++++ b/Objects/frameobject.c +@@ -851,9 +851,6 @@ + /* It is the responsibility of the owning generator/coroutine + * to have cleared the generator pointer */ + +- assert(f->f_frame->owner != FRAME_OWNED_BY_GENERATOR || +- _PyFrame_GetGenerator(f->f_frame)->gi_frame_state == FRAME_CLEARED); +- + if (_PyObject_GC_IS_TRACKED(f)) { + _PyObject_GC_UNTRACK(f); + } +@@ -861,10 +858,14 @@ + Py_TRASHCAN_BEGIN(f, frame_dealloc); + PyCodeObject *co = NULL; + ++ /* GH-106092: If f->f_frame was on the stack and we reached the maximum ++ * nesting depth for deallocations, the trashcan may have delayed this ++ * deallocation until after f->f_frame is freed. Avoid dereferencing ++ * f->f_frame unless we know it still points to valid memory. */ ++ _PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data; ++ + /* Kill all local variables including specials, if we own them */ +- if (f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) { +- assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data); +- _PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data; ++ if (f->f_frame == frame && frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) { + /* Don't clear code object until the end */ + co = frame->f_code; + frame->f_code = NULL; diff -Nru python3.11-3.11.2/debian/patches/series python3.11-3.11.2/debian/patches/series --- python3.11-3.11.2/debian/patches/series 2023-03-01 05:58:01.000000000 -0400 +++ python3.11-3.11.2/debian/patches/series 2024-03-02 16:28:50.000000000 -0400 @@ -39,3 +39,4 @@ fix-py_compile.diff ntpath-import.diff shutdown-deadlock.diff +frame_dealloc-crash.diff