diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 957cdb93ff..ddbc226146 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -74,7 +74,8 @@ jobs: -Dopenssl=true \ -Ddbus=false \ -Dandroid-log=true \ - -Dlandlock-monitor=true \ + -Dlandlock-monitor=false \ + -Dinstall-state-dirs=true \ --cross-file aarch64-android-api30.txt meson compile -C build diff --git a/config/init/module/boot-completed.sh.in b/config/init/module/boot-completed.sh.in index 7b9c0b2e04..517c0eb2f7 100644 --- a/config/init/module/boot-completed.sh.in +++ b/config/init/module/boot-completed.sh.in @@ -5,8 +5,3 @@ export LD_LIBRARY_PATH=/system/lib64:/system/lib:@LIBDIR@:/data/sysroot/lib64:/d # lxc-autostart mkdir -p @LOCALSTATEDIR@/lock @LIBEXECDIR@/lxc/lxc-containers start - -while true do - @LXCHOOKDIR@/android-network - sleep 5 -done \ No newline at end of file diff --git a/config/init/monitd/lxc-monitord-android.in b/config/init/monitd/lxc-monitord-android.in deleted file mode 100644 index 6bd141920a..0000000000 --- a/config/init/monitd/lxc-monitord-android.in +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -LD_LIBRARY_PATH=/data/env/lib:/data/env/lib64:/data/lxc/lib @LIBEXECDIR@/lxc/lxc-monitord --daemon & diff --git a/config/init/monitd/lxc-net.monit.in b/config/init/monitd/lxc-net.monit.in deleted file mode 100644 index b304b317ce..0000000000 --- a/config/init/monitd/lxc-net.monit.in +++ /dev/null @@ -1,4 +0,0 @@ -check program lxc-net with path "@LXCHOOKDIR@/android-network" - start program = "@LIBEXECDIR@/lxc/lxc-net start" - stop program = "@LIBEXECDIR@/lxc/lxc-net stop" - if status != 0 then alert diff --git a/config/init/monitd/lxc.monit.in b/config/init/monitd/lxc.monit.in deleted file mode 100644 index 92bf13311d..0000000000 --- a/config/init/monitd/lxc.monit.in +++ /dev/null @@ -1,4 +0,0 @@ -check program lxc-containers with path "@LIBEXECDIR@/lxc/lxc-containers start" - start program = "@LIBEXECDIR@/lxc/lxc-containers start" - stop program = "@LIBEXECDIR@/lxc/lxc-containers stop" - if status != 0 then alert diff --git a/config/init/monitd/meson.build b/config/init/monitd/meson.build deleted file mode 100644 index 8adc92654f..0000000000 --- a/config/init/monitd/meson.build +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: MIT - -if 'monitd' in init_script - monitd_unit_dir = get_option('monitd-unitdir') - if monitd_unit_dir == '' - monitd_unit_dir = lxclibexec - endif - - configure_file( - configuration: conf, - input: 'lxc-net.monit.in', - output: 'lxc-net.monit', - install: true, - install_dir: monitd_unit_dir) - - configure_file( - configuration: conf, - input: 'lxc.monit.in', - output: 'lxc.monit', - install: true, - install_dir: monitd_unit_dir) -endif diff --git a/config/templates/common.conf.d/00-android-network.conf.in b/config/templates/common.conf.d/00-android-network.conf.in deleted file mode 100644 index d42374cd1b..0000000000 --- a/config/templates/common.conf.d/00-android-network.conf.in +++ /dev/null @@ -1,14 +0,0 @@ -# Called before any initialization is done -lxc.hook.pre-start = @LXCHOOKDIR@/android-network -# Called after creating the mount namespace but before mounting anything -# lxc.hook.pre-mount = -# Called after the mounts but before pivot_root -# lxc.hook.mount = -# Called after the identical to mount but only called if using autodev -# lxc.hook.autodev = -# Called in the container right before /sbin/init -# lxc.hook.start = -# Called after the container has been shutdown -# lxc.hook.post-stop = -# Called when cloning a container into a new one -# lxc.hook.clone = diff --git a/config/templates/common.conf.d/meson.build b/config/templates/common.conf.d/meson.build index f09b82e972..c577f372aa 100644 --- a/config/templates/common.conf.d/meson.build +++ b/config/templates/common.conf.d/meson.build @@ -6,10 +6,3 @@ lxc_conf_common_readme = configure_file( output: 'README', install: true, install_dir: lxctemplateconfcommondir) - -lxc_conf_common_readme = configure_file( - configuration: conf, - input: '00-android-network.conf.in', - output: '00-android-network.conf', - install: true, - install_dir: lxctemplateconfcommondir) diff --git a/hooks/android-network.in b/hooks/android-network.in deleted file mode 100755 index 94e54f7e71..0000000000 --- a/hooks/android-network.in +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/sh -# -# SPDX-License-Identifier: MIT -# -# The patch for Android network is a workaround for the -# issue with the Android network stack. - -ip=/system/bin/ip -IPV6_RULE_ENABLE=$(grep -E 'LXC_IPV6_ENABLE="[^"]+"' @LIBEXECDIR@/lxc/lxc-net | sed 's/.*LXC_IPV6_ENABLE="\([^"]*\)".*/\1/') - -if [ "$IPV6_RULE_ENABLE" = "true" ]; then - if ! ${ip} -6 rule list | grep -q "from all lookup main"; then - ${ip} -6 rule add pref 1 from all lookup main - echo "Added v6 rule: pref 3 from all lookup main" - fi - - if ! ${ip} -6 rule list | grep -q "from all lookup default"; then - ${ip} -6 rule add pref 2 from all lookup default - echo "Added v6 rule: pref 2 from all lookup default" - fi -fi - -if ! ${ip} rule list | grep -q "from all lookup main"; then - ${ip} rule add pref 1 from all lookup main - echo "Added v4 rule: pref 1 from all lookup main" -fi - -if ! ${ip} rule list | grep -q "from all lookup default"; then - ${ip} rule add pref 2 from all lookup default - echo "Added v4 rule: pref 2 from all lookup default" -fi - -ipv4_active_interfaces=$(ip route | grep link | grep -v lxcbr0 | awk '{print $3}') -ipv4_gateways=$(ip route list table all | grep 'default via' | grep static | awk '{print $3}') -ipv6_active_interfaces=$(ip -6 addr | grep -B 8 global | grep -v -E 'fe80::|lxcbr0|lo|dummy0' | grep 'state' | awk -F: '{print $2}' | awk '{print $1}' | awk -F'@' '{print $1}') - -ipv4_num_active_interfaces=$(echo "$ipv4_active_interfaces" | wc -l) -ipv4_num_gateways=$(echo "$ipv4_gateways" | wc -l) - -if [ -z "$ipv4_active_interfaces" ] || [ -z "$ipv4_gateways" ]; then - echo "DEBUG: No active v4 interfaces or gateways found. Exiting hook." - if [ "$IPV6_RULE_ENABLE" = "true" ]; then - if [ -z "$ipv6_active_interfaces" ]; then - echo "DEBUG: No active v6 interfaces found. Exiting hook." - exit 0 - fi - fi - exit 0 -fi - -if [ "$ipv4_num_active_interfaces" -ne "$ipv4_num_gateways" ]; then - echo "ERROR: The number of interfaces and gateways for v4 do not match." - exit 1 -fi - -set -- $ipv4_active_interfaces -ipv4_interfaces="$@" - -set -- $ipv6_active_interfaces -ipv6_interfaces="$@" - -set -- $ipv4_gateways -ipv4_gateways="$@" - -i=1 -for ipv4_interface in $ipv4_interfaces; do - ipv4_gateway=$(echo "$ipv4_gateways" | awk "NR==$i") - - if [ $i -gt 1 ]; then - ${ip} route add default via ${ipv4_gateway} dev ${ipv4_interface} metric 10$i - echo "Added default route via ${ipv4_gateway} with metric $i on interface ${ipv4_interface}" - else - ${ip} route add default via ${ipv4_gateway} dev ${ipv4_interface} metric 100 - echo "Added default route via ${ipv4_gateway} on interface ${ipv4_interface}" - fi - i=$((i + 1)) -done - -if [ "$IPV6_RULE_ENABLE" = "true" ]; then - i6=1 - - if ! ${ip} -6 route show | grep -q "fc42:5009:ba4b:5ab0::/64"; then - ${ip} -6 route add fc42:5009:ba4b:5ab0::/64 dev lxcbr0 - echo "Add route to lxcbr0" - fi - - for ipv6_interface in $ipv6_interfaces; do - if [ $i6 -gt 1 ]; then - ${ip} -6 route add default via fe80::1 dev ${ipv6_interface} metric 10$i - echo "Added default route via fe80::1 with metric $i on interface ${ipv6_interface}" - else - ${ip} -6 route add default via fe80::1 dev ${ipv6_interface} metric 100 - echo "Added default route via fe80::1 on interface ${ipv6_interface}" - fi - i6=$((i6 + 1)) - done -else - echo "DEBUG: IPV6_RULE_ENABLE is not enable. Skipping IPv6 route addition." -fi diff --git a/hooks/meson.build b/hooks/meson.build index aeef552951..d789007507 100644 --- a/hooks/meson.build +++ b/hooks/meson.build @@ -50,9 +50,3 @@ hook_programs = configure_file( input: 'ubuntu-cloud-prep', output: 'ubuntu-cloud-prep') install_data(join_paths(project_build_root, 'hooks/ubuntu-cloud-prep'), install_dir: lxchookdir) - -hook_programs = configure_file( - configuration: conf, - input: 'android-network.in', - output: 'android-network') -install_data(join_paths(project_build_root, 'hooks/android-network'), install_dir: lxchookdir) diff --git a/meson.build b/meson.build index 019cd1ed64..4c802bc337 100644 --- a/meson.build +++ b/meson.build @@ -930,7 +930,6 @@ if want_install_init subdir('config/init/common') subdir('config/init/systemd') subdir('config/init/sysvinit') - subdir('config/init/monitd') subdir('config/init/module') subdir('config/sysconfig') endif diff --git a/meson_options.txt b/meson_options.txt index 96cc94874d..f862c41f99 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -15,7 +15,7 @@ option('examples', type: 'boolean', value: true, # was --init-script in autotools option('init-script', type: 'array', - choices: ['systemd', 'sysvinit', 'monitd', 'module'], value: ['module'], + choices: ['systemd', 'sysvinit', 'module'], value: ['module'], description: 'init script') # was --systemd-unidir in autotools @@ -23,11 +23,6 @@ option('init-script', type: 'array', option('systemd-unitdir', type: 'string', value: '', description: 'systemd system unit directory') -# was --monitd-unidir in autotools -# If set to "", the value is taken from the Magisk modules dir. -option('monitd-unitdir', type: 'string', value: '', - description: 'monitd unit directory') - # was --{disable,enable}-liburing in autotools option('io-uring-event-loop', type: 'boolean', value: false, description: 'Enable io-uring based event loop') diff --git a/src/lxc/network.c b/src/lxc/network.c index 79fa21d9df..678c40783a 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -43,6 +43,11 @@ #include "strlcpy.h" #endif +#if IS_BIONIC +#include +#define RT_TABLE_ANDROID_BASE 1000 +#endif + lxc_log_define(network, lxc); typedef int (*netdev_configure_server_cb)(struct lxc_handler *, struct lxc_netdev *); @@ -189,6 +194,129 @@ static int lxc_ipv6_dest_del(int ifindex, struct in6_addr *dest, unsigned int ne return lxc_ip_route_dest(RTM_DELROUTE, AF_INET6, ifindex, dest, netmask); } +#if IS_BIONIC +static int lxc_ip_rule_entry(int family, void *src, unsigned int src_len, + void *dst, unsigned int dst_len, + uint32_t table, uint32_t fwmark, uint32_t fwmask, + uint32_t priority, uint8_t type) +{ + call_cleaner(nlmsg_free) struct nlmsg *answer = NULL, *nlmsg = NULL; + struct nl_handler nlh = NL_HANDLER_INIT; + call_cleaner(netlink_close) struct nl_handler *nlh_ptr = &nlh; + int addrlen, err; + struct rtmsg *rt; + + addrlen = family == AF_INET ? sizeof(struct in_addr) + : sizeof(struct in6_addr); + + err = netlink_open(nlh_ptr, NETLINK_ROUTE); + if (err) + return err; + + nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); + if (!nlmsg) + return -ENOMEM; + + answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); + if (!answer) + return -ENOMEM; + + nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + nlmsg->nlmsghdr->nlmsg_type = RTM_NEWRULE; + + rt = nlmsg_reserve(nlmsg, sizeof(struct rtmsg)); + if (!rt) + return -ENOMEM; + + rt->rtm_family = family; + rt->rtm_table = RT_TABLE_UNSPEC; + rt->rtm_protocol = RTPROT_BOOT; + rt->rtm_scope = RT_SCOPE_UNIVERSE; + rt->rtm_type = RTN_UNICAST; + rt->rtm_src_len = src_len; + rt->rtm_dst_len = dst_len; + rt->rtm_tos = 0; + + if (src && src_len > 0) { + if (nla_put_buffer(nlmsg, RTA_SRC, src, addrlen)) + return -EINVAL; + } + + if (dst && dst_len > 0) { + if (nla_put_buffer(nlmsg, RTA_DST, dst, addrlen)) + return -EINVAL; + } + + if (table != 0) { + if (nla_put_u32(nlmsg, RTA_TABLE, table)) + return -EINVAL; + } + + if (fwmark != 0) { + if (nla_put_u32(nlmsg, RTA_MARK, fwmark)) + return -EINVAL; + } + + if (priority != 0) { + if (nla_put_u32(nlmsg, RTA_PRIORITY, priority)) + return -EINVAL; + } + + err = netlink_transaction(nlh_ptr, nlmsg, answer); + + if (err == -EEXIST) + return 0; + + return err; +} + +static int lxc_ipv4_entry_add(uint32_t table, uint32_t priority) +{ + return lxc_ip_rule_entry(AF_INET, NULL, 0, NULL, 0, table, 0, 0, priority, RTN_UNICAST); +} + +static int lxc_ipv6_entry_add(uint32_t table, uint32_t priority) +{ + return lxc_ip_rule_entry(AF_INET6, NULL, 0, NULL, 0, table, 0, 0, priority, RTN_UNICAST); +} + +static int setup_host_route_rules(void) +{ + struct ifaddrs *ifaddr = NULL, *ifa; + int tables[] = {RT_TABLE_MAIN, RT_TABLE_DEFAULT}; + int ret = 0; + unsigned ifindex = 0; + + if (getifaddrs(&ifaddr) == -1) + return -1; + + for (int i = 0; i < 2; i++) { + if ((ret = lxc_ipv4_entry_add(tables[i], 100 + i)) || + (ret = lxc_ipv6_entry_add(tables[i], 100 + i))) { + log_error_errno(-1, -EINVAL, "Failed to setup rules for table %d", tables[i]); + goto out; + } + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_name || !(ifa->ifa_flags & IFF_UP)) + continue; + + ifindex = if_nametoindex(ifa->ifa_name); + if (ifindex > 0) { + if ((ret = lxc_ipv4_entry_add(RT_TABLE_ANDROID_BASE + ifindex, 102)) || + (ret = lxc_ipv6_entry_add(RT_TABLE_ANDROID_BASE + ifindex, 102))) + goto out; + } + } + +out: + if (ifaddr) + freeifaddrs(ifaddr); + return ret; +} +#endif /* IS_BIONIC */ + static int setup_ipv4_routes(struct lxc_netdev *netdev) { int ifindex = netdev->priv.veth_attr.ifindex; @@ -782,6 +910,16 @@ static int netdev_configure_server_veth(struct lxc_handler *handler, struct lxc_ goto out_delete; } +#if IS_BIONIC + /* setup ip rules on the host tables */ + if (setup_host_route_rules()) { + ERROR("Failed to setup host rules for network device \"%s\"", veth1); + goto out_delete; + } + + DEBUG("Added route rules for all UP netdev"); +#endif + if (netdev->priv.veth_attr.mode == VETH_MODE_ROUTER) { /* sleep for a short period of time to work around a bug that intermittently prevents IP neighbour proxy entries from being added using lxc_ip_neigh_proxy below. When the issue occurs the entries