diff -u apport-2.20.1/NEWS apport-2.20.1/NEWS --- apport-2.20.1/NEWS +++ apport-2.20.1/NEWS @@ -9,6 +9,8 @@ characters with dots, not just a few known invalid ones. (LP: #1566975) * problem_report.py: Instead of AssertionError, raise a ValueError for invalid key names and TypeError for invalid kinds of values. Thanks Barry Warsaw. + * data/apport: Introduce support for non-positional arguments so we can + easily extend core_pattern in the future (LP: #1732962) 2.20.1 (2016-03-31) ------------------- diff -u apport-2.20.1/data/apport apport-2.20.1/data/apport --- apport-2.20.1/data/apport +++ apport-2.20.1/data/apport @@ -15,7 +15,7 @@ import sys, os, os.path, subprocess, time, traceback, pwd, io import signal, inspect, grp, fcntl, socket, atexit, array, struct -import errno +import errno, argparse import apport, apport.fileutils @@ -350,6 +350,47 @@ return False +def parse_arguments(): + parser = argparse.ArgumentParser(epilog=""" + Alternatively, the following command line is understood for legacy hosts: + [global pid] + """) + + # TODO: Use type=int + parser.add_argument("-p", "--pid", help="process id (%%p)") + parser.add_argument("-s", "--signal-number", help="signal number (%%s)") + parser.add_argument("-c", "--core-ulimit", help="core ulimit (%%c)") + parser.add_argument("-d", "--dump-mode", help="dump mode (%%d)") + parser.add_argument("-P", "--global-pid", nargs='?', help="pid in root namespace (%%P)") + parser.add_argument("-E", "--executable-path", nargs='?', help="path of executable (%%E)") + + options, rest = parser.parse_known_args() + + if options.pid is not None: + for arg in rest: + error_log("Unknown argument: %s", arg) + + elif len(rest) in (4, 5, 6): + # Translate legacy command line + options.pid = rest[0] + options.signal_number = rest[1] + options.core_ulimit = rest[2] + options.dump_mode = rest[3] + try: + options.global_pid = rest[4] + except IndexError: + options.global_pid = None + try: + options.exe_path = rest[5].replace('!', '/') + except IndexError: + options.exe_path = None + else: + parser.print_usage() + sys.exit(1) + + return options + + ################################################################# # # main @@ -398,16 +439,7 @@ error_log('Received a bad number of arguments from forwarder, received %d, expected 5, aborting.' % len(sys.argv)) sys.exit(1) -# Normal startup -if len(sys.argv) not in (5, 6, 7): - try: - print('Usage: %s [global pid] [exe path]' % sys.argv[0]) - print('The core dump is read from stdin.') - except IOError: - # sys.stderr might not actually exist, expecially not when being called - # from the kernel - pass - sys.exit(1) +options = parse_arguments() init_error_log() @@ -415,8 +447,8 @@ # then compare it with the local PID. If they don't match, it's an # indication that the crash originated from another PID namespace. # Simply log an entry in the host error log and exit 0. -if len(sys.argv) >= 6: - host_pid = int(sys.argv[5]) +if options.global_pid is not None: + host_pid = int(options.global_pid) if not is_same_ns(host_pid, "pid") and not is_same_ns(host_pid, "mnt"): # If the crash came from a container, don't attempt to handle @@ -426,7 +458,7 @@ # forward the process information there. if not os.path.exists('/proc/%d/root/run/apport.socket' % host_pid): error_log('host pid %s crashed in a container without apport support' % - host_pid) + options.global_pid) sys.exit(0) proc_host_pid_fd = os.open('/proc/%d' % host_pid, os.O_RDONLY | os.O_PATH | os.O_DIRECTORY) @@ -499,7 +531,7 @@ sock.connect('/run/apport.socket') except Exception as e: error_log('host pid %s crashed in a container with a broken apport' % - sys.argv[5]) + options.global_pid) sys.exit(0) # Send all arguments except for the first (exec path) and last (global pid) @@ -530,14 +562,17 @@ # sandbox will use container namespaces as a security measure but are # still otherwise host processes. When that's the case, we need to keep # handling those crashes locally using the global pid. - sys.argv[1] = str(host_pid) + options.pid = str(host_pid) check_lock() try: setup_signals() - (pid, signum, core_ulimit, dump_mode) = sys.argv[1:5] + pid = options.pid + signum = options.signal_number + core_ulimit = options.core_ulimit + dump_mode = options.dump_mode get_pid_info(pid) @@ -598,10 +633,8 @@ # We already need this here to figure out the ExecutableName (for scripts, # etc). - if len(sys.argv) >= 7: - exec_path = sys.argv[6].replace('!', '/') - if os.path.exists(exec_path): - info['ExecutablePath'] = exec_path + if options.exe_path is not None and os.path.exists(options.exe_path): + info['ExecutablePath'] = options.exe_path euid = os.geteuid() egid = os.getegid() diff -u apport-2.20.1/debian/changelog apport-2.20.1/debian/changelog --- apport-2.20.1/debian/changelog +++ apport-2.20.1/debian/changelog @@ -1,3 +1,10 @@ +apport (2.20.1-0ubuntu2.25) xenial; urgency=medium + + * data/apport: Introduce support for non-positional arguments so we can + easily extend core_pattern in the future (LP: #1732962) + + -- Matthieu Clemenceau Fri, 21 Aug 2020 10:24:13 -0500 + apport (2.20.1-0ubuntu2.24) xenial-security; urgency=medium * SECURITY UPDATE: information disclosure issue (LP: #1885633) diff -u apport-2.20.1/etc/init.d/apport apport-2.20.1/etc/init.d/apport --- apport-2.20.1/etc/init.d/apport +++ apport-2.20.1/etc/init.d/apport @@ -50,7 +50,12 @@ rm -f /var/lib/pm-utils/resume-hang.log fi - echo "|$AGENT %p %s %c %d %P %E" > /proc/sys/kernel/core_pattern + # Old compatibility mode, switch later to second one + if true; then + echo "|$AGENT %p %s %c %d %P %E" > /proc/sys/kernel/core_pattern + else + echo "|$AGENT -p%p -s%s -c%c -d%d -P%P -E%E" > /proc/sys/kernel/core_pattern + fi echo 2 > /proc/sys/fs/suid_dumpable } diff -u apport-2.20.1/use-local apport-2.20.1/use-local --- apport-2.20.1/use-local +++ apport-2.20.1/use-local @@ -7 +7 @@ -echo "|$(readlink -f $(dirname $0)/data/apport) %p %s %c %d %P" > /proc/sys/kernel/core_pattern +echo "|$(readlink -f $(dirname $0)/data/apport) -p%p -s%s -c%c -d%d -P%P" | tee /proc/sys/kernel/core_pattern