--- /tmp/apport 2015-03-31 12:29:05.790845868 -0400 +++ /usr/share/apport/apport 2015-03-31 15:11:38.582548537 -0400 @@ -266,13 +266,79 @@ init_error_log() # apport can't be found, then simply log an entry in the host error log # and exit 0. if len(sys.argv) == 5 and sys.argv[4].isdigit() and sys.argv[4] != sys.argv[1]: - if os.path.exists('/proc/%s/root/%s' % (sys.argv[4], __file__)): - error_log('pid %s (host pid %s) crashed in a container with apport ' - 'support, forwarding' % (sys.argv[1], sys.argv[4])) + if os.path.exists('/proc/%s/root/%s' % (sys.argv[4], __file__)) \ + and os.path.exists("/proc/%s/ns/" % sys.argv[4]): + try: + import lxc + except: + error_log('pid %s crashed in a container without python3-lxc' % sys.argv[4]) + sys.exit(0) + + def list_containers(): + containers = [] + + with open("/proc/net/unix", "r") as fd: + for line in sorted(fd): + fields = line.strip().split(" ") + if len(fields) != 8: + continue + + path = fields[7].split("/") + if path[-1] != "command": + continue + + if len(path) < 2: + continue + + real_path = "/".join(path[:-2]).lstrip("@") + + container = lxc.Container(path[-2], real_path) + if container.controllable and container.state != "STOPPED": + containers.append(container) + + return containers + + + def list_ns(pid): + return [os.readlink("/proc/%s/ns/%s" % (pid, ns)) + for ns in sorted(os.listdir("/proc/%s/ns" % pid))] + + + def get_container(pid): + pid_ns = list_ns(pid) + + for container in list_containers(): + container_ns = list_ns(container.init_pid) + + if container_ns == pid_ns: + return container + + return None + + container = get_container(sys.argv[4]) + if not container: + error_log('pid %s crashed in an unknown container' % sys.argv[4]) + sys.exit(0) + + error_log('pid %s (host pid %s) crashed in container ' + '"%s" (%s), forwarding' % (sys.argv[1], sys.argv[4], + container.name, + container.get_config_path())) + sys.stderr.flush() - os.execv('/usr/sbin/chroot', ('chroot', '/proc/%s/root/' % sys.argv[4], - __file__, sys.argv[1], sys.argv[2], - sys.argv[3])) + + def run_command(cmd): + os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin' + os.environ['HOME'] = '/root' + os.environ['LANG'] = 'en_US.UTF-8' + + return subprocess.call(cmd) + + cmd = [__file__, sys.argv[1], sys.argv[2], sys.argv[3]] + retval = container.attach_wait(run_command, cmd, + env_policy=lxc.LXC_ATTACH_CLEAR_ENV) + + sys.exit(0) else: error_log('pid %s crashed in a container without apport support' % sys.argv[4]) sys.exit(0)