From fbb3854aeab0142e4b65b1fc64c87b0854411ab3 Mon Sep 17 00:00:00 2001 From: Benjamin Drung Date: Wed, 19 Apr 2023 13:18:48 +0200 Subject: [PATCH] apport: Write coredump at beginning and quit To reproduce bug #2015857 write the coredump at the beginning and quit. Allow slowing down the writing to trigger the bug. Bug: https://launchpad.net/bugs/2015857 Signed-off-by: Benjamin Drung --- data/apport | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/data/apport b/data/apport index 89b73c742..08237f6e7 100755 --- a/data/apport +++ b/data/apport @@ -37,6 +37,7 @@ import subprocess import sys import time import traceback +import typing import apport.fileutils import apport.report @@ -727,6 +728,50 @@ def parse_arguments(args: list[str]): return options +def write_coredump_to_file( + coredump_path: str, coredump_fd: int, slowdown: float +) -> None: + """Write coredump to given file.""" + assert isinstance(crash_uid, int) + logger = logging.getLogger() + coredump_file = os.open( + coredump_path, + os.O_WRONLY | os.O_CREAT | os.O_EXCL, + mode=0o400, + dir_fd=cwd, + ) + + written = 0 + while True: + block = os.read(coredump_fd, 1048576) + size = len(block) + if size == 0: + break + written += size + if os.write(coredump_file, block) != size: + logger.error("aborting core dump writing, could not write") + os.close(coredump_file) + os.unlink(coredump_path, dir_fd=cwd) + return + time.sleep(slowdown) + + # Make sure the user can read it + os.fchown(coredump_file, crash_uid, -1) + os.close(coredump_file) + logger.warning( + "Wrote %s bytes of core to %s", f"{written:,}", coredump_path + ) + + +def get_core_path( + options: argparse.Namespace, timestamp: typing.Optional[int] = None +) -> str: + """Get the path to the core file.""" + return apport.fileutils.get_core_path( + options.pid, options.executable_path, crash_uid, timestamp + )[1] + + def main(args: list[str]) -> int: init_error_log() logging.basicConfig(format=LOG_FORMAT) @@ -744,6 +789,18 @@ def main(args: list[str]) -> int: start_apport() return 0 + get_pid_info(options.pid) + logging.getLogger(__name__).error( + "called for pid %s, signal %s, core limit %s, dump mode %s", + options.pid, + options.signal_number, + options.core_ulimit, + options.dump_mode, + ) + write_coredump_to_file(get_core_path(options), sys.stdin.fileno(), 0.001) + # pylint: disable=unreachable + return 0 + # Check if we received a valid global PID (kernel >= 3.12). If we do, # then compare it with the local PID. If they don't match, it's an # indication that the crash originated from another PID namespace. -- 2.37.2