diff -Nru apport-2.20.11/apport/hookutils.py apport-2.20.11/apport/hookutils.py --- apport-2.20.11/apport/hookutils.py 2021-04-26 15:45:36.000000000 -0400 +++ apport-2.20.11/apport/hookutils.py 2021-05-12 06:46:16.000000000 -0400 @@ -79,8 +79,14 @@ instead of failing. ''' try: - with open(path, 'rb') as f: - contents = f.read().strip() + # make sure the file isn't a FIFO or symlink + fd = os.open(path, os.O_NOFOLLOW | os.O_RDONLY | os.O_NONBLOCK) + st = os.fstat(fd) + if stat.S_ISREG(st.st_mode): + with os.fdopen(fd, 'rb') as f: + contents = f.read().strip() + else: + return 'Error: could not open file!' if force_unicode: return contents.decode('UTF-8', errors='replace') try: diff -Nru apport-2.20.11/backends/packaging-apt-dpkg.py apport-2.20.11/backends/packaging-apt-dpkg.py --- apport-2.20.11/backends/packaging-apt-dpkg.py 2020-06-24 12:02:11.000000000 -0400 +++ apport-2.20.11/backends/packaging-apt-dpkg.py 2021-05-12 06:46:16.000000000 -0400 @@ -424,7 +424,7 @@ allows filtering. ''' dpkg = subprocess.Popen(['dpkg-query', '-W', '--showformat=${Conffiles}', - package], stdout=subprocess.PIPE) + '--', package], stdout=subprocess.PIPE) out = dpkg.communicate()[0].decode() if dpkg.returncode != 0: diff -Nru apport-2.20.11/data/whoopsie-upload-all apport-2.20.11/data/whoopsie-upload-all --- apport-2.20.11/data/whoopsie-upload-all 2020-09-30 14:26:32.000000000 -0400 +++ apport-2.20.11/data/whoopsie-upload-all 2021-05-12 06:46:16.000000000 -0400 @@ -14,6 +14,7 @@ # the full text of the license. import os +import stat import sys import time import subprocess @@ -113,11 +114,14 @@ # write updated report, we use os.open and os.fdopen as # /proc/sys/fs/protected_regular is set to 1 (LP: #1848064) - fd = os.open(report, os.O_WRONLY | os.O_APPEND) - with os.fdopen(fd, 'wb') as f: - os.chmod(report, 0) - r.write(f, only_new=True) - os.chmod(report, 0o640) + # make sure the file isn't a FIFO or symlink + fd = os.open(report, os.O_NOFOLLOW | os.O_WRONLY | os.O_APPEND | os.O_NONBLOCK) + st = os.fstat(fd) + if stat.S_ISREG(st.st_mode): + with os.fdopen(fd, 'wb') as f: + os.fchmod(fd, 0) + r.write(f, only_new=True) + os.fchmod(fd, 0o640) # now tell whoopsie to upload the report print('Marking %s for whoopsie upload' % report) diff -Nru apport-2.20.11/debian/changelog apport-2.20.11/debian/changelog --- apport-2.20.11/debian/changelog 2021-04-26 15:45:36.000000000 -0400 +++ apport-2.20.11/debian/changelog 2021-05-12 06:46:16.000000000 -0400 @@ -1,3 +1,24 @@ +apport (2.20.11-0ubuntu50.7) groovy-security; urgency=medium + + * SECURITY UPDATE: Multiple arbitrary file reads (LP: #1917904) + - apport/hookutils.py: don't follow symlinks and make sure the file + isn't a FIFO in read_file(). + - test/test_hookutils.py: added symlink tests. + - CVE-2021-32547, CVE-2021-32548, CVE-2021-32549, CVE-2021-32550, + CVE-2021-32551, CVE-2021-32552, CVE-2021-32553, CVE-2021-32554, + CVE-2021-32555 + * SECURITY UPDATE: info disclosure via modified config files spoofing + (LP: #1917904) + - backends/packaging-apt-dpkg.py: properly terminate arguments in + get_modified_conffiles. + - CVE-2021-32556 + * SECURITY UPDATE: arbitrary file write (LP: #1917904) + - data/whoopsie-upload-all: don't follow symlinks and make sure the + file isn't a FIFO in process_report(). + - CVE-2021-32557 + + -- Marc Deslauriers Wed, 12 May 2021 06:46:16 -0400 + apport (2.20.11-0ubuntu50.6) groovy; urgency=medium * data/general-hooks/ubuntu.py: tag bugs from Raspberry Pi images and RISCV diff -Nru apport-2.20.11/test/test_hookutils.py apport-2.20.11/test/test_hookutils.py --- apport-2.20.11/test/test_hookutils.py 2020-06-01 19:47:57.000000000 -0400 +++ apport-2.20.11/test/test_hookutils.py 2021-05-12 06:46:16.000000000 -0400 @@ -1,5 +1,5 @@ # coding: UTF-8 -import unittest, tempfile, locale, subprocess, re, shutil, os.path, sys +import unittest, tempfile, locale, subprocess, re, shutil, os, sys import apport.hookutils @@ -93,6 +93,14 @@ self.assertEqual(list(report), ['.nonexisting']) self.assertTrue(report['.nonexisting'].startswith('Error: ')) + # symlink + link = os.path.join(self.workdir, 'symlink') + os.symlink('/etc/passwd', link) + report = {} + apport.hookutils.attach_file(report, link, 'Symlink') + self.assertEqual(list(report), ['Symlink']) + self.assertTrue(report['Symlink'].startswith('Error: ')) + # existing key report = {} apport.hookutils.attach_file(report, '/etc/passwd') @@ -137,6 +145,14 @@ self.assertEqual(list(report), ['Passwd']) self.assertEqual(report['Passwd'], passwd_contents) + # symlink + link = os.path.join(self.workdir, 'symlink') + os.symlink('/etc/passwd', link) + report = {} + apport.hookutils.attach_file_if_exists(report, link, 'Symlink') + self.assertEqual(list(report), ['Symlink']) + self.assertTrue(report['Symlink'].startswith('Error: ')) + # nonexisting file report = {} apport.hookutils.attach_file_if_exists(report, '/nonexisting')