Version in base suite: 1.8.4.1 Version in overlay suite: 1.8.4.2 Base version: python-apt_1.8.4.2 Target version: python-apt_1.8.4.3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/python-apt/python-apt_1.8.4.2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/python-apt/python-apt_1.8.4.3.dsc debian/changelog | 10 +++++++++ python/arfile.cc | 29 +++++++++++++++++++++----- tests/test_cve_2020_27351.py | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 6 deletions(-) diff -Nru python-apt-1.8.4.2/debian/changelog python-apt-1.8.4.3/debian/changelog --- python-apt-1.8.4.2/debian/changelog 2020-12-01 19:18:12.000000000 +0000 +++ python-apt-1.8.4.3/debian/changelog 2020-12-22 19:38:06.000000000 +0000 @@ -1,3 +1,13 @@ +python-apt (1.8.4.3) buster-security; urgency=high + + * REGRESSION UPDATE: Passing a file descriptor to apt_inst.ArFile or + apt_inst.DebFile caused a segmentation fault (Closes: #977000): + - python/arfile.cc: Fix segmentation fault when opening fd, track lifetime + correctly + * REGRESSION UPDATE: arfile: Collect file<->deb/ar reference cycles + + -- Julian Andres Klode Tue, 22 Dec 2020 20:38:06 +0100 + python-apt (1.8.4.2) buster-security; urgency=high * SECURITY UPDATE: various memory and file descriptor leaks (LP: #1899193) diff -Nru python-apt-1.8.4.2/python/arfile.cc python-apt-1.8.4.3/python/arfile.cc --- python-apt-1.8.4.2/python/arfile.cc 2020-12-01 19:18:12.000000000 +0000 +++ python-apt-1.8.4.3/python/arfile.cc 2020-12-22 19:38:06.000000000 +0000 @@ -152,8 +152,11 @@ 0, // tp_getattro 0, // tp_setattro 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags + Py_TPFLAGS_DEFAULT | // tp_flags + Py_TPFLAGS_HAVE_GC, filefd_doc, // tp_doc + CppTraverse, // tp_traverse + CppClear, // tp_clear }; @@ -435,8 +438,8 @@ else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) { // Clear the error set by PyObject_AsString(). PyErr_Clear(); - self->Fd = CppPyObject_NEW(NULL, &PyFileFd_Type); - self.reset((PyArArchiveObject*) CppPyObject_NEW(file,type)); + self.reset((PyArArchiveObject*) CppPyObject_NEW(NULL,type)); + self->Fd = CppPyObject_NEW(file, &PyFileFd_Type); new (&self->Fd->Object) FileFd(fileno,false); } else { @@ -448,9 +451,23 @@ return self.release(); } +static int ararchive_traverse(PyObject *_self, visitproc visit, void* arg) +{ + PyArArchiveObject *self = (PyArArchiveObject*)_self; + Py_VISIT(self->Fd); + return CppTraverse(self, visit, arg); +} + +static int ararchive_clear(PyObject *_self) +{ + PyArArchiveObject *self = (PyArArchiveObject*)_self; + Py_CLEAR(self->Fd); + return CppClear(self); +} + static void ararchive_dealloc(PyObject *self) { - Py_CLEAR(((PyArArchiveObject *)(self))->Fd); + ararchive_clear(self); CppDeallocPtr(self); } @@ -504,8 +521,8 @@ Py_TPFLAGS_DEFAULT | // tp_flags Py_TPFLAGS_HAVE_GC, ararchive_doc, // tp_doc - CppTraverse, // tp_traverse - CppClear, // tp_clear + ararchive_traverse, // tp_traverse + ararchive_clear, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset (getiterfunc)ararchive_iter, // tp_iter diff -Nru python-apt-1.8.4.2/tests/test_cve_2020_27351.py python-apt-1.8.4.3/tests/test_cve_2020_27351.py --- python-apt-1.8.4.2/tests/test_cve_2020_27351.py 2020-12-01 19:18:12.000000000 +0000 +++ python-apt-1.8.4.3/tests/test_cve_2020_27351.py 2020-12-22 19:38:06.000000000 +0000 @@ -17,8 +17,10 @@ if libdir: sys.path.insert(0, libdir) import apt_inst +import gc import subprocess import tempfile +import warnings @unittest.skipIf( @@ -36,6 +38,51 @@ after = os.listdir("/proc/self/fd") self.assertEqual(before, after) + def test_regression_bug_977000(self): + """opening with a file handle should work correctly""" + with open(self.GOOD_DEB) as good_deb: + apt_inst.DebFile(good_deb).control.extractdata("control") + + def test_regression_bug_977000_2(self): + """file object <-> debfile cycles should be collected by gc.""" + + class Cycle(object): + def __init__(self, fname): + self.file = open(fname) + self.deb = apt_inst.DebFile(self) + + def fileno(self): + return self.file.fileno() + + before = os.listdir("/proc/self/fd") + Cycle(self.GOOD_DEB).deb.control.extractdata("control") + warnings.filterwarnings("ignore", category=Warning) + gc.collect() + warnings.resetwarnings() + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + + def test_regression_bug_977000_2_ar(self): + """file object <-> debfile cycles should be collected by gc.""" + + class Cycle(object): + def __init__(self, fname): + self.file = open(fname) + self.deb = apt_inst.ArArchive(self) + + def fileno(self): + return self.file.fileno() + + before = os.listdir("/proc/self/fd") + Cycle(self.GOOD_DEB).deb.gettar("control.tar.gz", "gzip").extractdata( + "control" + ) + warnings.filterwarnings("ignore", category=Warning) + gc.collect() + warnings.resetwarnings() + after = os.listdir("/proc/self/fd") + self.assertEqual(before, after) + def test_success_a_member(self): """fd should be kept around as long as a tarfile member""" before = os.listdir("/proc/self/fd")