262
262
# Check if we received a valid global PID (kernel >= 3.12). If we do,
263
263
# then compare it with the local PID. If they don't match, it's an
264
# indication that the crash originated from another PID namespace. In that
265
# case, attempt to forward the crash to apport in that namespace. If
266
# apport can't be found, then simply log an entry in the host error log
264
# indication that the crash originated from another PID namespace.
265
# Simply log an entry in the host error log and exit 0.
268
266
if len(sys.argv) == 5 and sys.argv[4].isdigit() and sys.argv[4] != sys.argv[1]:
269
host_pid = sys.argv[4]
271
if os.path.exists('/proc/%s/root/%s' % (host_pid, __file__)) \
272
and os.path.exists('/proc/%s/ns/' % host_pid):
276
error_log('pid %s crashed in a container without python3-lxc' % host_pid)
279
def list_containers():
282
with open('/proc/net/unix', 'r') as fd:
283
for line in sorted(fd):
284
fields = line.strip().split(' ')
288
inode = fields[6].strip()
289
path = fields[7].split('/')
290
if path[-1] != 'command':
296
real_path = '/'.join(path[:-2]).lstrip('@')
298
container = lxc.Container(path[-2], real_path)
300
if not container.controllable:
303
if container.state == 'STOPPED':
307
with open('/proc/%s/status' % container.init_pid) as fd:
309
if line.startswith('PPid:'):
310
ppid = int(line.strip().split(':')[-1].strip())
315
stat = os.stat('/proc/%s' % ppid)
319
for fd in os.listdir('/proc/%s/fd/' % ppid):
320
if os.readlink('/proc/%s/fd/%s' % (ppid, fd)) \
321
== 'socket:[%s]' % inode:
326
containers.append((container, (uid, gid)))
331
return [os.readlink('/proc/%s/ns/%s' % (pid, ns))
332
for ns in sorted(os.listdir('/proc/%s/ns' % pid))]
334
def get_container(pid):
335
pid_ns = list_ns(pid)
337
for container, owner in list_containers():
338
container_ns = list_ns(container.init_pid)
340
if container_ns == pid_ns:
341
return container, owner
345
container, owner = get_container(host_pid)
347
error_log('pid %s crashed in an unknown container' % host_pid)
350
if owner[0] or owner[1]:
351
error_log('pid %s crashed in an untrusted container' % host_pid)
354
error_log('pid %s (host pid %s) crashed in container '
355
'"%s" (%s), forwarding' % (pid, host_pid,
357
container.get_config_path()))
361
def run_command(cmd):
362
os.environ['PATH'] = '/usr/sbin:/usr/bin:/sbin:/bin'
364
return subprocess.call(cmd)
366
cmd = [__file__, sys.argv[1], sys.argv[2], sys.argv[3]]
367
retval = container.attach_wait(run_command, cmd,
368
env_policy=lxc.LXC_ATTACH_CLEAR_ENV)
372
error_log('host pid %s crashed in a container without apport support' %
267
error_log('host pid %s crashed in a container without apport support' %