mirror of
https://gitlab.postmarketos.org/postmarketOS/pmbootstrap.git
synced 2025-07-25 21:45:11 +03:00
pmbootstrap: unshare PID namespaec
Put ourselves in a new PID namespace so that daemons we might start in the chroot like adbd will be killed on exit. This simplifies "shutdown" since we no longer need to kill these processes. Signed-off-by: Casey Connolly <kcxt@postmarketos.org>
This commit is contained in:
parent
e8a9ce615f
commit
9dc294dbbf
3 changed files with 20 additions and 32 deletions
|
@ -1,37 +1,13 @@
|
||||||
# Copyright 2023 Oliver Smith
|
# Copyright 2023 Oliver Smith
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
from pmb.core.arch import Arch
|
|
||||||
from pmb.helpers import logging
|
from pmb.helpers import logging
|
||||||
import socket
|
|
||||||
from contextlib import closing
|
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.helpers.mount
|
import pmb.helpers.mount
|
||||||
from pmb.core import Chroot, ChrootType
|
from pmb.core import Chroot
|
||||||
from pmb.core.context import get_context
|
from pmb.core.context import get_context
|
||||||
|
|
||||||
|
|
||||||
def kill_adb() -> None:
|
|
||||||
"""
|
|
||||||
Kill adb daemon if it's running.
|
|
||||||
"""
|
|
||||||
port = 5038
|
|
||||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
|
||||||
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
|
||||||
pmb.chroot.root(["adb", "-P", str(port), "kill-server"])
|
|
||||||
|
|
||||||
|
|
||||||
def kill_sccache() -> None:
|
|
||||||
"""
|
|
||||||
Kill sccache daemon if it's running. Unlike ccache it automatically spawns
|
|
||||||
a daemon when you call it and exits after some time of inactivity.
|
|
||||||
"""
|
|
||||||
port = 4226
|
|
||||||
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
|
||||||
if sock.connect_ex(("127.0.0.1", port)) == 0:
|
|
||||||
pmb.chroot.root(["sccache", "--stop-server"])
|
|
||||||
|
|
||||||
|
|
||||||
def shutdown_cryptsetup_device(name: str) -> None:
|
def shutdown_cryptsetup_device(name: str) -> None:
|
||||||
"""
|
"""
|
||||||
:param name: cryptsetup device name, usually "pm_crypt" in pmbootstrap
|
:param name: cryptsetup device name, usually "pm_crypt" in pmbootstrap
|
||||||
|
@ -59,10 +35,6 @@ def shutdown_cryptsetup_device(name: str) -> None:
|
||||||
|
|
||||||
|
|
||||||
def shutdown(only_install_related: bool = False) -> None:
|
def shutdown(only_install_related: bool = False) -> None:
|
||||||
# Stop daemons
|
|
||||||
kill_adb()
|
|
||||||
kill_sccache()
|
|
||||||
|
|
||||||
# Umount installation-related paths (order is important!)
|
# Umount installation-related paths (order is important!)
|
||||||
# pmb.helpers.mount.umount_all(chroot / "mnt/install")
|
# pmb.helpers.mount.umount_all(chroot / "mnt/install")
|
||||||
shutdown_cryptsetup_device("pm_crypt")
|
shutdown_cryptsetup_device("pm_crypt")
|
||||||
|
|
|
@ -27,6 +27,7 @@ BTRFS_SUPER_MAGIC = 0x9123683E
|
||||||
CAP_NET_ADMIN = 12
|
CAP_NET_ADMIN = 12
|
||||||
CAP_SYS_ADMIN = 21
|
CAP_SYS_ADMIN = 21
|
||||||
CLONE_NEWIPC = 0x08000000
|
CLONE_NEWIPC = 0x08000000
|
||||||
|
CLONE_NEWPID = 0x20000000
|
||||||
CLONE_NEWNET = 0x40000000
|
CLONE_NEWNET = 0x40000000
|
||||||
CLONE_NEWNS = 0x00020000
|
CLONE_NEWNS = 0x00020000
|
||||||
CLONE_NEWUSER = 0x10000000
|
CLONE_NEWUSER = 0x10000000
|
||||||
|
|
|
@ -14,9 +14,24 @@ os.environ["SHELL"] = "/bin/sh" if os.path.exists("/bin/sh") else "/bin/bash"
|
||||||
original_uid = os.geteuid()
|
original_uid = os.geteuid()
|
||||||
|
|
||||||
sandbox.acquire_privileges(become_root=False)
|
sandbox.acquire_privileges(become_root=False)
|
||||||
# Unshare mount namespace
|
# Unshare mount and PID namespaces. We create a new PID namespace so
|
||||||
sandbox.unshare(sandbox.CLONE_NEWNS)
|
# that any log-running daemons (e.g. adbd, sccache) will be killed when
|
||||||
# sandbox.seccomp_suppress(chown=True)
|
# pmbootstrap exits
|
||||||
|
sandbox.unshare(sandbox.CLONE_NEWNS | sandbox.CLONE_NEWPID)
|
||||||
|
|
||||||
|
# We are now PID 1 in a new PID namespace. We don't want to run all our
|
||||||
|
# logic as PID 1 since subprocess.Popen() seemingly causes our PID to
|
||||||
|
# change. So we fork now, the child process continues and we just wait
|
||||||
|
# around and propagate the exit code.
|
||||||
|
# This is all kinda hacky, we should integrate this with the acquire_privileges()
|
||||||
|
# implementation since it's already doing similar fork shenanigans, we could
|
||||||
|
# save a call to fork() this way. But for now it's fine.
|
||||||
|
pid = os.fork()
|
||||||
|
if pid > 0:
|
||||||
|
# We are PID 1! let's hang out
|
||||||
|
pid, wstatus = os.waitpid(pid, 0)
|
||||||
|
exitcode = os.waitstatus_to_exitcode(wstatus)
|
||||||
|
os._exit(exitcode)
|
||||||
|
|
||||||
# print("Caps: ")
|
# print("Caps: ")
|
||||||
# with open("/proc/self/status", "rb") as f:
|
# with open("/proc/self/status", "rb") as f:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue