diff --git a/CMakeLists.txt b/CMakeLists.txt index f411999592b1ea59e74459621ca73c603758e31b..51443b00ede57a36f8da56cd451f1dfe6437914e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,12 @@ pkg_check_modules(LXC lxc REQUIRED) pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED) pkg_check_modules(LIBSYSTEMD libsystemd REQUIRED) +message(STATUS "LXC version: ${LXC_VERSION}") +if (${LXC_VERSION} VERSION_LESS 3.0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_LXC2_SUPPORT") + message(STATUS "Building with LXC 2.x compatibility support") +endif() + option(ENABLE_WAYLAND "Enable wayland support" ON) if (ENABLE_WAYLAND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWAYLAND_SUPPORT") diff --git a/src/anbox/container/lxc_container.cpp b/src/anbox/container/lxc_container.cpp index 2bcec124f05edf9ed7b86223d70a89169825f170..6ab8c261ee4102a6b1170f997ff0b171b7fd1d8e 100644 --- a/src/anbox/container/lxc_container.cpp +++ b/src/anbox/container/lxc_container.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,36 @@ constexpr const std::uint32_t default_container_ip_prefix_length{24}; constexpr const char *default_host_ip_address{"192.168.250.1"}; constexpr const char *default_dns_server{"8.8.8.8"}; +#ifdef ENABLE_LXC2_SUPPORT +constexpr const char *lxc_config_idmap_key{"lxc.id_map"}; +constexpr const char *lxc_config_net_type_key{"lxc.network.type"}; +constexpr const char *lxc_config_net_flags_key{"lxc.network.flags"}; +constexpr const char *lxc_config_net_link_key{"lxc.network.link"}; +constexpr const char *lxc_config_pty_max_key{"lxc.pts"}; +constexpr const char *lxc_config_tty_max_key{"lxc.tty"}; +constexpr const char *lxc_config_uts_name_key{"lxc.utsname"}; +constexpr const char *lxc_config_tty_dir_key{"lxc.devttydir"}; +constexpr const char *lxc_config_init_cmd_key{"lxc.init_cmd"}; +constexpr const char *lxc_config_rootfs_path_key{"lxc.rootfs"}; +constexpr const char *lxc_config_log_level_key{"lxc.loglevel"}; +constexpr const char *lxc_config_log_file_key{"lxc.logfile"}; +constexpr const char *lxc_config_apparmor_profile_key{"lxc.aa_profile"}; +#else +constexpr const char *lxc_config_idmap_key{"lxc.idmap"}; +constexpr const char *lxc_config_net_type_key{"lxc.net.0.type"}; +constexpr const char *lxc_config_net_flags_key{"lxc.net.0.flags"}; +constexpr const char *lxc_config_net_link_key{"lxc.net.0.link"}; +constexpr const char *lxc_config_pty_max_key{"lxc.pty.max"}; +constexpr const char *lxc_config_tty_max_key{"lxc.tty.max"}; +constexpr const char *lxc_config_uts_name_key{"lxc.uts.name"}; +constexpr const char *lxc_config_tty_dir_key{"lxc.tty.dir"}; +constexpr const char *lxc_config_init_cmd_key{"lxc.init.cmd"}; +constexpr const char *lxc_config_rootfs_path_key{"lxc.rootfs.path"}; +constexpr const char *lxc_config_log_level_key{"lxc.log.level"}; +constexpr const char *lxc_config_log_file_key{"lxc.log.file"}; +constexpr const char *lxc_config_apparmor_profile_key{"lxc.apparmor.profile"}; +#endif + constexpr int device_major(__dev_t dev) { return int(((dev >> 8) & 0xfff) | ((dev >> 32) & (0xfffff000))); } @@ -87,19 +118,19 @@ void LxcContainer::setup_id_map() { const auto base_id = unprivileged_uid; const auto max_id = 65536; - set_config_item("lxc.idmap", utils::string_format("u 0 %d %d", base_id, android_system_uid - 1)); - set_config_item("lxc.idmap", utils::string_format("g 0 %d %d", base_id, android_system_uid - 1)); + set_config_item(lxc_config_idmap_key, utils::string_format("u 0 %d %d", base_id, android_system_uid - 1)); + set_config_item(lxc_config_idmap_key, utils::string_format("g 0 %d %d", base_id, android_system_uid - 1)); // We need to bind the user id for the one running the client side // process as he is the owner of various socket files we bind mount // into the container. - set_config_item("lxc.idmap", utils::string_format("u %d %d 1", android_system_uid, creds_.uid())); - set_config_item("lxc.idmap", utils::string_format("g %d %d 1", android_system_uid, creds_.gid())); + set_config_item(lxc_config_idmap_key, utils::string_format("u %d %d 1", android_system_uid, creds_.uid())); + set_config_item(lxc_config_idmap_key, utils::string_format("g %d %d 1", android_system_uid, creds_.gid())); - set_config_item("lxc.idmap", utils::string_format("u %d %d %d", android_system_uid + 1, + set_config_item(lxc_config_idmap_key, utils::string_format("u %d %d %d", android_system_uid + 1, base_id + android_system_uid + 1, max_id - creds_.uid() - 1)); - set_config_item("lxc.idmap", utils::string_format("g %d %d %d", android_system_uid + 1, + set_config_item(lxc_config_idmap_key, utils::string_format("g %d %d %d", android_system_uid + 1, base_id + android_system_uid + 1, max_id - creds_.gid() - 1)); } @@ -110,9 +141,9 @@ void LxcContainer::setup_network() { return; } - set_config_item("lxc.net.0.type", "veth"); - set_config_item("lxc.net.0.flags", "up"); - set_config_item("lxc.net.0.link", "anbox0"); + set_config_item(lxc_config_net_type_key, "veth"); + set_config_item(lxc_config_net_flags_key, "up"); + set_config_item(lxc_config_net_link_key, "anbox0"); // Instead of relying on DHCP we will give Android a static IP configuration // for the virtual ethernet interface LXC creates for us. This will be bridged @@ -271,22 +302,21 @@ void LxcContainer::start(const Configuration &configuration) { set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed"); set_config_item("lxc.autodev", "1"); - set_config_item("lxc.pty.max", "1024"); - set_config_item("lxc.tty.max", "0"); - set_config_item("lxc.uts.name", "anbox"); + set_config_item(lxc_config_pty_max_key, "1024"); + set_config_item(lxc_config_tty_max_key, "0"); + set_config_item(lxc_config_uts_name_key, "anbox"); set_config_item("lxc.group.devices.deny", ""); set_config_item("lxc.group.devices.allow", ""); // We can't move bind-mounts, so don't use /dev/lxc/ - set_config_item("lxc.tty.dir", ""); + set_config_item(lxc_config_tty_dir_key, ""); - set_config_item("lxc.environment", - "PATH=/system/bin:/system/sbin:/system/xbin"); + set_config_item("lxc.environment", "PATH=/system/bin:/system/sbin:/system/xbin"); - set_config_item("lxc.init.cmd", "/anbox-init.sh"); + set_config_item(lxc_config_init_cmd_key, "/anbox-init.sh"); -#if ENABLE_SNAP_CONFINEMENT +#ifdef ENABLE_SNAP_CONFINEMENT // If we're running inside the snap environment snap-confine already created a // cgroup for us we need to use as otherwise presevering a namespace wont help. if (utils::is_env_set("SNAP")) @@ -298,25 +328,28 @@ void LxcContainer::start(const Configuration &configuration) { rootfs_path = SystemConfiguration::instance().combined_rootfs_dir(); DEBUG("Using rootfs path %s", rootfs_path); - set_config_item("lxc.rootfs.path", rootfs_path); + set_config_item(lxc_config_rootfs_path_key, rootfs_path); - set_config_item("lxc.log.level", "0"); + set_config_item(lxc_config_log_level_key, "0"); const auto log_path = SystemConfiguration::instance().log_dir(); - set_config_item("lxc.log.file", utils::string_format("%s/container.log", log_path).c_str()); + set_config_item(lxc_config_log_file_key, utils::string_format("%s/container.log", log_path).c_str()); + +#ifndef ENABLE_LXC2_SUPPORT + // Dump the console output to disk to have a chance to debug early boot problems + set_config_item("lxc.console.logfile", utils::string_format("%s/console.log", log_path).c_str()); + set_config_item("lxc.console.rotate", "1"); +#endif - // Dump the console output to disk to have a chance to debug early boot problems - set_config_item("lxc.console.logfile", utils::string_format("%s/console.log", log_path).c_str()); - set_config_item("lxc.console.rotate", "1"); setup_network(); -#if ENABLE_SNAP_CONFINEMENT +#ifdef ENABLE_SNAP_CONFINEMENT // We take the AppArmor profile snapd has defined for us as part of the // anbox-support interface. The container manager itself runs within a // child profile snap.anbox.container-manager//lxc too. set_config_item("lxc.apparmor.profile", "snap.anbox.container-manager//container"); #else - set_config_item("lxc.apparmor.profile", "unconfined"); + set_config_item(lxc_config_apparmor_profile_key, "unconfined"); #endif if (!privileged_)