import logging
import glob
import shutil
+import time
import platform
import gbinder
import tools.config
make_entry("/dev/zero")
make_entry("/dev/null")
make_entry("/dev/full")
- make_entry("/dev/ashmem", check=False)
+ make_entry("/dev/ashmem")
make_entry("/dev/fuse")
make_entry("/dev/ion")
make_entry("/dev/char", options="bind,create=dir,optional 0 0")
make_entry("/dev/pvr_sync")
make_entry("/dev/pmsg0")
make_entry("/dev/dxg")
- make_entry(tools.helpers.gpu.getDriNode(args), "dev/dri/renderD128")
+ render, card = tools.helpers.gpu.getDriNode(args)
+ make_entry(render, "dev/dri/renderD128")
+ make_entry(card, "dev/dri/card0")
for n in glob.glob("/dev/fb*"):
make_entry(n)
# Recursive mount /run to provide necessary host sockets
make_entry("/run", options="rbind,create=dir 0 0")
+ # And /dev/shm
+ make_entry("/dev/shm", options="rbind,create=dir,optional 0 0")
# Necessary sw_sync node for HWC
make_entry("/dev/sw_sync")
return nodes
+LXC_APPARMOR_PROFILE = "lxc-waydroid"
+def get_apparmor_status(args):
+ enabled = False
+ if shutil.which("aa-enabled"):
+ enabled = (tools.helpers.run.user(args, ["aa-enabled", "--quiet"], check=False) == 0)
+ if not enabled and shutil.which("systemctl"):
+ enabled = (tools.helpers.run.user(args, ["systemctl", "is-active", "-q", "apparmor"], check=False) == 0)
+ try:
+ with open("/sys/kernel/security/apparmor/profiles", "r") as f:
+ enabled &= (LXC_APPARMOR_PROFILE in f.read())
+ except:
+ enabled = False
+ return enabled
def set_lxc_config(args):
lxc_path = tools.config.defaults["lxc"] + "/waydroid"
raise OSError("LXC is not installed")
config_paths = tools.config.tools_src + "/data/configs/config_"
seccomp_profile = tools.config.tools_src + "/data/configs/waydroid.seccomp"
- apparmor_profiles = [tools.config.tools_src + "/data/configs/" + "lxc-waydroid",tools.config.tools_src + "/data/configs/" + "android_app",tools.config.tools_src + "/data/configs/" + "adbd"]
- apparmor_profile_dir = "/etc/apparmor.d/"
config_snippets = [ config_paths + "base" ]
- # lxc v1 is a bit special because some options got renamed later
- if lxc_ver == 1:
+ # lxc v1 and v2 are bit special because some options got renamed later
+ if lxc_ver <= 2:
config_snippets.append(config_paths + "1")
else:
- for ver in range(2, 5):
+ for ver in range(3, 5):
snippet = config_paths + str(ver)
if lxc_ver >= ver and os.path.exists(snippet):
config_snippets.append(snippet)
tools.helpers.run.user(args, command)
command = ["cp", "-fpr", seccomp_profile, lxc_path + "/waydroid.seccomp"]
tools.helpers.run.user(args, command)
-
- try:
- command = ["cp", "-i", apparmor_profiles[0], apparmor_profile_dir + "lxc/lxc-waydroid"]
- tools.helpers.run.user(args, command)
- command = ["apparmor_parser", "-r", apparmor_profile_dir + "lxc/lxc-waydroid"]
- tools.helpers.run.user(args, command)
- command = ["cp", "-i", apparmor_profiles[1], apparmor_profile_dir + "android_app"]
- tools.helpers.run.user(args, command)
- command = ["apparmor_parser", "-r", apparmor_profile_dir + "android_app"]
+ if get_apparmor_status(args):
+ command = ["sed", "-i", "-E", "/lxc.aa_profile|lxc.apparmor.profile/ s/unconfined/{}/g".format(LXC_APPARMOR_PROFILE), lxc_path + "/config"]
tools.helpers.run.user(args, command)
- command = ["cp", "-i", apparmor_profiles[2], apparmor_profile_dir + "adbd"]
- tools.helpers.run.user(args, command)
- command = ["apparmor_parser", "-r", apparmor_profile_dir + "adbd"]
- tools.helpers.run.user(args, command)
- except:
- logging.warning("An error has occurred while installing AppArmor profiles. If profiles are not installed, or AppArmor is disabled or not supported on your system, then the container will run without AppArmor protection.")
nodes = generate_nodes_lxc_config(args)
config_nodes_tmp_path = args.work + "/config_nodes"
props.append("sys.use_memfd=true")
egl = tools.helpers.props.host_get(args, "ro.hardware.egl")
- dri = tools.helpers.gpu.getDriNode(args)
+ dri, _ = tools.helpers.gpu.getDriNode(args)
gralloc = find_hal("gralloc")
if not gralloc:
def status(args):
command = ["lxc-info", "-P", tools.config.defaults["lxc"], "-n", "waydroid", "-sH"]
out = subprocess.run(command, stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
- os.chmod(args.log, 0o666)
return out
+def wait_for_running(args):
+ lxc_status = status(args)
+ timeout = 10
+ while lxc_status != "RUNNING" and timeout > 0:
+ lxc_status = status(args)
+ logging.info(
+ "waiting {} seconds for container to start...".format(timeout))
+ timeout = timeout - 1
+ time.sleep(1)
+ if lxc_status != "RUNNING":
+ raise OSError("container failed to start")
+
def start(args):
command = ["lxc-start", "-P", tools.config.defaults["lxc"],
"-F", "-n", "waydroid", "--", "/init"]
tools.helpers.run.user(args, command, output="background")
+ wait_for_running(args)
+ # Workaround lxc-start changing stdout/stderr permissions to 700
+ os.chmod(args.log, 0o666)
def stop(args):
command = ["lxc-stop", "-P",
tools.helpers.run.user(args, command)
def shell(args):
- if status(args) != "RUNNING":
- logging.error("WayDroid container is {}".format(status(args)))
+ state = status(args)
+ if state == "FROZEN":
+ unfreeze(args)
+ elif state != "RUNNING":
+ logging.error("WayDroid container is {}".format(state))
return
command = ["lxc-attach", "-P", tools.config.defaults["lxc"],
"-n", "waydroid", "--"]
if args.COMMAND:
- command.append(args.COMMAND)
+ command.extend(args.COMMAND)
else:
command.append("/system/bin/sh")
subprocess.run(command, env={"PATH": os.environ['PATH'] + ":/system/bin:/vendor/bin"})
+ if state == "FROZEN":
+ freeze(args)
def logcat(args):
- if status(args) != "RUNNING":
- logging.error("WayDroid container is {}".format(status(args)))
+ state = status(args)
+ if state == "FROZEN":
+ unfreeze(args)
+ elif state != "RUNNING":
+ logging.error("WayDroid container is {}".format(state))
return
command = ["lxc-attach", "-P", tools.config.defaults["lxc"],
"-n", "waydroid", "--", "/system/bin/logcat"]
subprocess.run(command)
+ if state == "FROZEN":
+ freeze(args)