diff --git a/DnsResolver/Android.bp b/DnsResolver/Android.bp new file mode 100644 index 0000000000..4779995373 --- /dev/null +++ b/DnsResolver/Android.bp @@ -0,0 +1,54 @@ +// +// Copyright (C) 2023 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +cc_library { + name: "libcom.android.tethering.dns_helper", + version_script: "libcom.android.tethering.dns_helper.map.txt", + stubs: { + versions: [ + "1", + ], + symbol_file: "libcom.android.tethering.dns_helper.map.txt", + }, + defaults: ["netd_defaults"], + header_libs: [ + "bpf_connectivity_headers", + "libcutils_headers", + ], + srcs: [ + "DnsBpfHelper.cpp", + "DnsHelper.cpp", + ], + static_libs: [ + "libmodules-utils-build", + ], + shared_libs: [ + "libbase", + ], + export_include_dirs: ["include"], + header_abi_checker: { + enabled: true, + symbol_file: "libcom.android.tethering.dns_helper.map.txt", + }, + sanitize: { + cfi: true, + }, + apex_available: ["com.android.tethering"], + min_sdk_version: "30", +} diff --git a/DnsResolver/DnsBpfHelper.cpp b/DnsResolver/DnsBpfHelper.cpp new file mode 100644 index 0000000000..fbe4dc30e4 --- /dev/null +++ b/DnsResolver/DnsBpfHelper.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DnsBpfHelper" + +#include "DnsBpfHelper.h" + +#include +#include + +namespace android { +namespace net { + +base::Result DnsBpfHelper::init() { + if (!android::modules::sdklevel::IsAtLeastT()) { + LOG(ERROR) << __func__ << ": Unsupported before Android T."; + return base::Error(EOPNOTSUPP); + } + + auto result = mConfigurationMap.init(CONFIGURATION_MAP_PATH); + if (!result.ok()) { + LOG(ERROR) << __func__ << ": Failed to init configuration_map: " + << strerror(result.error().code()); + return result; + } + + result = mUidOwnerMap.init(UID_OWNER_MAP_PATH); + if (!result.ok()) { + LOG(ERROR) << __func__ << ": Failed to init uid_owner_map: " + << strerror(result.error().code()); + } + return result; +} + +base::Result DnsBpfHelper::isUidNetworkingBlocked(uid_t uid, bool) { + if (is_system_uid(uid)) return false; + if (!mConfigurationMap.isValid() || !mUidOwnerMap.isValid()) { + LOG(ERROR) << __func__ + << ": BPF maps are not ready. Forgot to call ADnsHelper_init?"; + return base::Error(EUNATCH); + } + + auto enabledRules = mConfigurationMap.readValue(UID_RULES_CONFIGURATION_KEY); + if (!enabledRules.ok()) { + LOG(ERROR) << __func__ + << ": Failed to read enabled rules from configuration_map: " + << strerror(enabledRules.error().code()); + return enabledRules.error(); + } + + auto value = mUidOwnerMap.readValue(uid); + uint32_t uidRules = value.ok() ? value.value().rule : 0; + + if (isBlockedByUidRules(enabledRules.value(), uidRules)) return true; + + // TODO: Read data saver settings from bpf maps. For metered network, check penalty box, happy box + // and data saver settings. + + return false; +} + +} // namespace net +} // namespace android diff --git a/DnsResolver/DnsBpfHelper.h b/DnsResolver/DnsBpfHelper.h new file mode 100644 index 0000000000..fdf9b01869 --- /dev/null +++ b/DnsResolver/DnsBpfHelper.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include "bpf/BpfMap.h" +#include "netd.h" + +namespace android { +namespace net { + +class DnsBpfHelper { + public: + DnsBpfHelper() = default; + DnsBpfHelper(const DnsBpfHelper&) = delete; + DnsBpfHelper& operator=(const DnsBpfHelper&) = delete; + + base::Result init(); + base::Result isUidNetworkingBlocked(uid_t uid, bool metered); + + private: + android::bpf::BpfMapRO mConfigurationMap; + android::bpf::BpfMapRO mUidOwnerMap; +}; + +} // namespace net +} // namespace android diff --git a/DnsResolver/DnsHelper.cpp b/DnsResolver/DnsHelper.cpp new file mode 100644 index 0000000000..3372908add --- /dev/null +++ b/DnsResolver/DnsHelper.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "DnsBpfHelper.h" +#include "DnsHelperPublic.h" + +static android::net::DnsBpfHelper sDnsBpfHelper; + +int ADnsHelper_init() { + auto result = sDnsBpfHelper.init(); + if (!result.ok()) return -result.error().code(); + + return 0; +} + +int ADnsHelper_isUidNetworkingBlocked(uid_t uid, bool metered) { + auto result = sDnsBpfHelper.isUidNetworkingBlocked(uid, metered); + if (!result.ok()) return -result.error().code(); + + // bool -> int conversion. + return result.value(); +} diff --git a/DnsResolver/include/DnsHelperPublic.h b/DnsResolver/include/DnsHelperPublic.h new file mode 100644 index 0000000000..7c9fc9e58e --- /dev/null +++ b/DnsResolver/include/DnsHelperPublic.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +__BEGIN_DECLS + +/* + * Perform any required initialization - including opening any required BPF maps. This function + * needs to be called before using other functions of this library. + * + * Returns 0 on success, a negative POSIX error code (see errno.h) on other failures. + */ +int ADnsHelper_init(); + +/* + * The function reads bpf maps and returns whether the given uid has blocked networking or not. The + * function is supported starting from Android T. + * + * |uid| is a Linux/Android UID to be queried. It is a combination of UserID and AppID. + * |metered| indicates whether the uid is currently using a billing network. + * + * Returns 0(false)/1(true) on success, a negative POSIX error code (see errno.h) on other failures. + */ +int ADnsHelper_isUidNetworkingBlocked(uid_t uid, bool metered); + +__END_DECLS diff --git a/DnsResolver/libcom.android.tethering.dns_helper.map.txt b/DnsResolver/libcom.android.tethering.dns_helper.map.txt new file mode 100644 index 0000000000..3c965a212c --- /dev/null +++ b/DnsResolver/libcom.android.tethering.dns_helper.map.txt @@ -0,0 +1,27 @@ +# +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This lists the entry points visible to applications that use the +# libcom.android.tethering.dns_helper library. Other entry points present in +# the library won't be usable. + +LIBCOM_ANDROID_TETHERING_DNS_HELPER { + global: + ADnsHelper_init; # apex + ADnsHelper_isUidNetworkingBlocked; # apex + local: + *; +}; diff --git a/Tethering/Android.bp b/Tethering/Android.bp index e69b872ce1..dd60be7c78 100644 --- a/Tethering/Android.bp +++ b/Tethering/Android.bp @@ -226,6 +226,7 @@ sdk { "com.android.tethering", ], native_shared_libs: [ + "libcom.android.tethering.dns_helper", "libnetd_updatable", ], } diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp index cd8eac88bc..ee44f3ccb4 100644 --- a/Tethering/apex/Android.bp +++ b/Tethering/apex/Android.bp @@ -83,6 +83,7 @@ apex { "libandroid_net_connectivity_com_android_net_module_util_jni", ], native_shared_libs: [ + "libcom.android.tethering.dns_helper", "libcom.android.tethering.connectivity_native", "libnetd_updatable", ], diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp index b3f8ed6160..cdf47e7da5 100644 --- a/bpf_progs/Android.bp +++ b/bpf_progs/Android.bp @@ -45,6 +45,7 @@ cc_library_headers { "com.android.tethering", ], visibility: [ + "//packages/modules/Connectivity/DnsResolver", "//packages/modules/Connectivity/netd", "//packages/modules/Connectivity/service", "//packages/modules/Connectivity/service/native/libs/libclat", diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c index 5759df7a33..f223dd15e5 100644 --- a/bpf_progs/netd.c +++ b/bpf_progs/netd.c @@ -92,7 +92,7 @@ DEFINE_BPF_MAP_NO_NETD(app_uid_stats_map, HASH, uint32_t, StatsValue, APP_STATS_ DEFINE_BPF_MAP_RO_NETD(stats_map_A, HASH, StatsKey, StatsValue, STATS_MAP_SIZE) DEFINE_BPF_MAP_RO_NETD(stats_map_B, HASH, StatsKey, StatsValue, STATS_MAP_SIZE) DEFINE_BPF_MAP_NO_NETD(iface_stats_map, HASH, uint32_t, StatsValue, IFACE_STATS_MAP_SIZE) -DEFINE_BPF_MAP_NO_NETD(uid_owner_map, HASH, uint32_t, UidOwnerValue, UID_OWNER_MAP_SIZE) +DEFINE_BPF_MAP_RO_NETD(uid_owner_map, HASH, uint32_t, UidOwnerValue, UID_OWNER_MAP_SIZE) DEFINE_BPF_MAP_RO_NETD(uid_permission_map, HASH, uint32_t, uint8_t, UID_OWNER_MAP_SIZE) DEFINE_BPF_MAP_NO_NETD(ingress_discard_map, HASH, IngressDiscardKey, IngressDiscardValue, INGRESS_DISCARD_MAP_SIZE)