diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-08 13:51:27 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-08 13:51:27 +0000 |
commit | 4040c179ebe4248b19e9a52b21a268c67154ab64 (patch) | |
tree | c8faaef4211326b843bf0fa8cb3fa63cf5fd1ae2 | |
parent | 92e0137a95c459b7319bc3d94f8b6f1b86a61176 (diff) | |
parent | e5a18b52cafa9dfa25a2b06e8c200628e34005c7 (diff) | |
download | net-android13-mainline-go-sdkext-release.tar.gz |
Snap for 8756029 from e5a18b52cafa9dfa25a2b06e8c200628e34005c7 to mainline-go-sdkext-releaseaml_go_sdk_330810000android13-mainline-go-sdkext-release
Change-Id: Idf14605a2a4b8e6f1c2c01d6005aa521dcd87514
22 files changed, 541 insertions, 305 deletions
diff --git a/common/Android.bp b/common/Android.bp index d13f9387..31a72625 100644 --- a/common/Android.bp +++ b/common/Android.bp @@ -111,7 +111,6 @@ java_library { name: "net-utils-device-common-bpf", srcs: [ "device/com/android/net/module/util/BpfBitmap.java", - "device/com/android/net/module/util/BpfDump.java", "device/com/android/net/module/util/BpfMap.java", "device/com/android/net/module/util/BpfUtils.java", "device/com/android/net/module/util/HexDump.java", @@ -119,6 +118,7 @@ java_library { "device/com/android/net/module/util/JniUtil.java", "device/com/android/net/module/util/Struct.java", "device/com/android/net/module/util/TcUtils.java", + "device/com/android/net/module/util/bpf/*.java", ], sdk_version: "module_current", min_sdk_version: "29", @@ -232,9 +232,7 @@ java_library { ":net-utils-framework-common-srcs", ], sdk_version: "module_current", - min_sdk_version: "29", libs: [ - "androidx.annotation_annotation", "framework-annotations-lib", "framework-connectivity.stubs.module_lib", "framework-connectivity-t.stubs.module_lib", diff --git a/common/device/com/android/net/module/util/BpfDump.java b/common/device/com/android/net/module/util/BpfDump.java deleted file mode 100644 index fec225c1..00000000 --- a/common/device/com/android/net/module/util/BpfDump.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2022 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 com.android.net.module.util; - -import android.util.Base64; - -import androidx.annotation.NonNull; - -/** - * The classes and the methods for BPF dump utilization. - */ -public class BpfDump { - // Using "," as a separator between base64 encoded key and value is safe because base64 - // characters are [0-9a-zA-Z/=+]. - public static final String BASE64_DELIMITER = ","; - - /** - * Encode BPF key and value into a base64 format string which uses the delimiter ',': - * <base64 encoded key>,<base64 encoded value> - */ - public static <K extends Struct, V extends Struct> String toBase64EncodedString( - @NonNull final K key, @NonNull final V value) { - final byte[] keyBytes = key.writeToBytes(); - final String keyBase64Str = Base64.encodeToString(keyBytes, Base64.DEFAULT) - .replace("\n", ""); - final byte[] valueBytes = value.writeToBytes(); - final String valueBase64Str = Base64.encodeToString(valueBytes, Base64.DEFAULT) - .replace("\n", ""); - - return keyBase64Str + BASE64_DELIMITER + valueBase64Str; - } - - // TODO: add a helper to dump bpf map content with the map name, the header line - // (ex: "BPF ingress map: iif nat64Prefix v6Addr -> v4Addr oif"), a lambda that - // knows how to dump each line, and the PrintWriter. -} diff --git a/common/device/com/android/net/module/util/bpf/ClatEgress4Key.java b/common/device/com/android/net/module/util/bpf/ClatEgress4Key.java new file mode 100644 index 00000000..12200ec6 --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/ClatEgress4Key.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.Inet4Address; + +/** Key type for clat egress IPv4 maps. */ +public class ClatEgress4Key extends Struct { + @Field(order = 0, type = Type.U32) + public final long iif; // The input interface index + + @Field(order = 1, type = Type.Ipv4Address) + public final Inet4Address local4; // The source IPv4 address + + public ClatEgress4Key(final long iif, final Inet4Address local4) { + this.iif = iif; + this.local4 = local4; + } +} diff --git a/common/device/com/android/net/module/util/bpf/ClatEgress4Value.java b/common/device/com/android/net/module/util/bpf/ClatEgress4Value.java new file mode 100644 index 00000000..c10cb4da --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/ClatEgress4Value.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.Inet6Address; + +/** Value type for clat egress IPv4 maps. */ +public class ClatEgress4Value extends Struct { + @Field(order = 0, type = Type.U32) + public final long oif; // The output interface to redirect to + + @Field(order = 1, type = Type.Ipv6Address) + public final Inet6Address local6; // The full 128-bits of the source IPv6 address + + @Field(order = 2, type = Type.Ipv6Address) + public final Inet6Address pfx96; // The destination /96 nat64 prefix, bottom 32 bits must be 0 + + @Field(order = 3, type = Type.U8, padding = 3) + public final short oifIsEthernet; // Whether the output interface requires ethernet header + + public ClatEgress4Value(final long oif, final Inet6Address local6, final Inet6Address pfx96, + final short oifIsEthernet) { + this.oif = oif; + this.local6 = local6; + this.pfx96 = pfx96; + this.oifIsEthernet = oifIsEthernet; + } +} diff --git a/common/device/com/android/net/module/util/bpf/ClatIngress6Key.java b/common/device/com/android/net/module/util/bpf/ClatIngress6Key.java new file mode 100644 index 00000000..1e2f4e06 --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/ClatIngress6Key.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.Inet6Address; + +/** Key type for clat ingress IPv6 maps. */ +public class ClatIngress6Key extends Struct { + @Field(order = 0, type = Type.U32) + public final long iif; // The input interface index + + @Field(order = 1, type = Type.Ipv6Address) + public final Inet6Address pfx96; // The source /96 nat64 prefix, bottom 32 bits must be 0 + + @Field(order = 2, type = Type.Ipv6Address) + public final Inet6Address local6; // The full 128-bits of the destination IPv6 address + + public ClatIngress6Key(final long iif, final Inet6Address pfx96, final Inet6Address local6) { + this.iif = iif; + this.pfx96 = pfx96; + this.local6 = local6; + } +} diff --git a/common/device/com/android/net/module/util/bpf/ClatIngress6Value.java b/common/device/com/android/net/module/util/bpf/ClatIngress6Value.java new file mode 100644 index 00000000..bfec44fa --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/ClatIngress6Value.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.Inet4Address; + +/** Value type for clat ingress IPv6 maps. */ +public class ClatIngress6Value extends Struct { + @Field(order = 0, type = Type.U32) + public final long oif; // The output interface to redirect to (0 means don't redirect) + + @Field(order = 1, type = Type.Ipv4Address) + public final Inet4Address local4; // The destination IPv4 address + + public ClatIngress6Value(final long oif, final Inet4Address local4) { + this.oif = oif; + this.local4 = local4; + } +} diff --git a/common/device/com/android/net/module/util/bpf/Tether4Key.java b/common/device/com/android/net/module/util/bpf/Tether4Key.java new file mode 100644 index 00000000..638576f0 --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/Tether4Key.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 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 com.android.net.module.util.bpf; + +import android.net.MacAddress; + +import androidx.annotation.NonNull; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.Objects; + +/** Key type for downstream & upstream IPv4 forwarding maps. */ +public class Tether4Key extends Struct { + @Field(order = 0, type = Type.U32) + public final long iif; + + @Field(order = 1, type = Type.EUI48) + public final MacAddress dstMac; + + @Field(order = 2, type = Type.U8, padding = 1) + public final short l4proto; + + @Field(order = 3, type = Type.ByteArray, arraysize = 4) + public final byte[] src4; + + @Field(order = 4, type = Type.ByteArray, arraysize = 4) + public final byte[] dst4; + + @Field(order = 5, type = Type.UBE16) + public final int srcPort; + + @Field(order = 6, type = Type.UBE16) + public final int dstPort; + + public Tether4Key(final long iif, @NonNull final MacAddress dstMac, final short l4proto, + final byte[] src4, final byte[] dst4, final int srcPort, + final int dstPort) { + Objects.requireNonNull(dstMac); + + this.iif = iif; + this.dstMac = dstMac; + this.l4proto = l4proto; + this.src4 = src4; + this.dst4 = dst4; + this.srcPort = srcPort; + this.dstPort = dstPort; + } + + @Override + public String toString() { + try { + return String.format( + "iif: %d, dstMac: %s, l4proto: %d, src4: %s, dst4: %s, " + + "srcPort: %d, dstPort: %d", + iif, dstMac, l4proto, + Inet4Address.getByAddress(src4), Inet4Address.getByAddress(dst4), + Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort)); + } catch (UnknownHostException | IllegalArgumentException e) { + return String.format("Invalid IP address", e); + } + } +} diff --git a/common/device/com/android/net/module/util/bpf/Tether4Value.java b/common/device/com/android/net/module/util/bpf/Tether4Value.java new file mode 100644 index 00000000..de98766e --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/Tether4Value.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 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 com.android.net.module.util.bpf; + +import android.net.MacAddress; + +import androidx.annotation.NonNull; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +/** Value type for downstream & upstream IPv4 forwarding maps. */ +public class Tether4Value extends Struct { + @Field(order = 0, type = Type.U32) + public final long oif; + + // The ethhdr struct which is defined in uapi/linux/if_ether.h + @Field(order = 1, type = Type.EUI48) + public final MacAddress ethDstMac; + @Field(order = 2, type = Type.EUI48) + public final MacAddress ethSrcMac; + @Field(order = 3, type = Type.UBE16) + public final int ethProto; // Packet type ID field. + + @Field(order = 4, type = Type.U16) + public final int pmtu; + + @Field(order = 5, type = Type.ByteArray, arraysize = 16) + public final byte[] src46; + + @Field(order = 6, type = Type.ByteArray, arraysize = 16) + public final byte[] dst46; + + @Field(order = 7, type = Type.UBE16) + public final int srcPort; + + @Field(order = 8, type = Type.UBE16) + public final int dstPort; + + // TODO: consider using U64. + @Field(order = 9, type = Type.U63) + public final long lastUsed; + + public Tether4Value(final long oif, @NonNull final MacAddress ethDstMac, + @NonNull final MacAddress ethSrcMac, final int ethProto, final int pmtu, + final byte[] src46, final byte[] dst46, final int srcPort, + final int dstPort, final long lastUsed) { + Objects.requireNonNull(ethDstMac); + Objects.requireNonNull(ethSrcMac); + + this.oif = oif; + this.ethDstMac = ethDstMac; + this.ethSrcMac = ethSrcMac; + this.ethProto = ethProto; + this.pmtu = pmtu; + this.src46 = src46; + this.dst46 = dst46; + this.srcPort = srcPort; + this.dstPort = dstPort; + this.lastUsed = lastUsed; + } + + @Override + public String toString() { + try { + return String.format( + "oif: %d, ethDstMac: %s, ethSrcMac: %s, ethProto: %d, pmtu: %d, " + + "src46: %s, dst46: %s, srcPort: %d, dstPort: %d, " + + "lastUsed: %d", + oif, ethDstMac, ethSrcMac, ethProto, pmtu, + InetAddress.getByAddress(src46), InetAddress.getByAddress(dst46), + Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort), + lastUsed); + } catch (UnknownHostException | IllegalArgumentException e) { + return String.format("Invalid IP address", e); + } + } +} diff --git a/common/device/com/android/net/module/util/bpf/TetherStatsKey.java b/common/device/com/android/net/module/util/bpf/TetherStatsKey.java new file mode 100644 index 00000000..c6d595be --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/TetherStatsKey.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2020 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** The key of BpfMap which is used for tethering stats. */ +public class TetherStatsKey extends Struct { + @Field(order = 0, type = Type.U32) + public final long ifindex; // upstream interface index + + public TetherStatsKey(final long ifindex) { + this.ifindex = ifindex; + } + + // TODO: remove equals, hashCode and toString once aosp/1536721 is merged. + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + + if (!(obj instanceof TetherStatsKey)) return false; + + final TetherStatsKey that = (TetherStatsKey) obj; + + return ifindex == that.ifindex; + } + + @Override + public int hashCode() { + return Long.hashCode(ifindex); + } + + @Override + public String toString() { + return String.format("ifindex: %d", ifindex); + } +} diff --git a/common/device/com/android/net/module/util/bpf/TetherStatsValue.java b/common/device/com/android/net/module/util/bpf/TetherStatsValue.java new file mode 100644 index 00000000..028d217a --- /dev/null +++ b/common/device/com/android/net/module/util/bpf/TetherStatsValue.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2020 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 com.android.net.module.util.bpf; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** The key of BpfMap which is used for tethering stats. */ +public class TetherStatsValue extends Struct { + // Use the signed long variable to store the uint64 stats from stats BPF map. + // U63 is enough for each data element even at 5Gbps for ~468 years. + // 2^63 / (5 * 1000 * 1000 * 1000) * 8 / 86400 / 365 = 468. + @Field(order = 0, type = Type.U63) + public final long rxPackets; + @Field(order = 1, type = Type.U63) + public final long rxBytes; + @Field(order = 2, type = Type.U63) + public final long rxErrors; + @Field(order = 3, type = Type.U63) + public final long txPackets; + @Field(order = 4, type = Type.U63) + public final long txBytes; + @Field(order = 5, type = Type.U63) + public final long txErrors; + + public TetherStatsValue(final long rxPackets, final long rxBytes, final long rxErrors, + final long txPackets, final long txBytes, final long txErrors) { + this.rxPackets = rxPackets; + this.rxBytes = rxBytes; + this.rxErrors = rxErrors; + this.txPackets = txPackets; + this.txBytes = txBytes; + this.txErrors = txErrors; + } + + // TODO: remove equals, hashCode and toString once aosp/1536721 is merged. + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + + if (!(obj instanceof TetherStatsValue)) return false; + + final TetherStatsValue that = (TetherStatsValue) obj; + + return rxPackets == that.rxPackets + && rxBytes == that.rxBytes + && rxErrors == that.rxErrors + && txPackets == that.txPackets + && txBytes == that.txBytes + && txErrors == that.txErrors; + } + + @Override + public int hashCode() { + return Long.hashCode(rxPackets) ^ Long.hashCode(rxBytes) ^ Long.hashCode(rxErrors) + ^ Long.hashCode(txPackets) ^ Long.hashCode(txBytes) ^ Long.hashCode(txErrors); + } + + @Override + public String toString() { + return String.format("rxPackets: %s, rxBytes: %s, rxErrors: %s, txPackets: %s, " + + "txBytes: %s, txErrors: %s", rxPackets, rxBytes, rxErrors, txPackets, + txBytes, txErrors); + } +} diff --git a/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java b/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java index 4a617941..88f8c9d3 100644 --- a/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java +++ b/common/device/com/android/net/module/util/ip/IpNeighborMonitor.java @@ -22,7 +22,6 @@ import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH; import static com.android.net.module.util.netlink.NetlinkConstants.hexify; import static com.android.net.module.util.netlink.NetlinkConstants.stringForNlMsgType; -import android.annotation.NonNull; import android.net.MacAddress; import android.os.Handler; import android.system.ErrnoException; @@ -81,17 +80,15 @@ public class IpNeighborMonitor extends NetlinkMonitor { * An event about a neighbor. */ public static class NeighborEvent { - public final long elapsedMs; - public final short msgType; - public final int ifindex; - @NonNull - public final InetAddress ip; - public final short nudState; - @NonNull - public final MacAddress macAddr; - - public NeighborEvent(long elapsedMs, short msgType, int ifindex, @NonNull InetAddress ip, - short nudState, @NonNull MacAddress macAddr) { + final long elapsedMs; + final short msgType; + final int ifindex; + final InetAddress ip; + final short nudState; + final MacAddress macAddr; + + public NeighborEvent(long elapsedMs, short msgType, int ifindex, InetAddress ip, + short nudState, MacAddress macAddr) { this.elapsedMs = elapsedMs; this.msgType = msgType; this.ifindex = ifindex; @@ -104,7 +101,7 @@ public class IpNeighborMonitor extends NetlinkMonitor { return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateConnected(nudState); } - public boolean isValid() { + boolean isValid() { return (msgType != RTM_DELNEIGH) && StructNdMsg.isNudStateValid(nudState); } diff --git a/common/framework/com/android/net/module/util/LocationPermissionChecker.java b/common/framework/com/android/net/module/util/LocationPermissionChecker.java index cd1f31cb..e4ce9e80 100644 --- a/common/framework/com/android/net/module/util/LocationPermissionChecker.java +++ b/common/framework/com/android/net/module/util/LocationPermissionChecker.java @@ -30,8 +30,6 @@ import android.os.Build; import android.os.UserHandle; import android.util.Log; -import androidx.annotation.RequiresApi; - import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; @@ -43,7 +41,6 @@ import java.lang.annotation.RetentionPolicy; * * @hide */ -@RequiresApi(Build.VERSION_CODES.R) public class LocationPermissionChecker { private static final String TAG = "LocationPermissionChecker"; diff --git a/common/native/bpf_headers/include/bpf/BpfMap.h b/common/native/bpf_headers/include/bpf/BpfMap.h index 47256fa0..297b2001 100644 --- a/common/native/bpf_headers/include/bpf/BpfMap.h +++ b/common/native/bpf_headers/include/bpf/BpfMap.h @@ -50,8 +50,10 @@ class BpfMap { // (later on, for testing, we still make available a copy assignment operator) BpfMap<Key, Value>(const BpfMap<Key, Value>&) = delete; - private: - void abortOnKeyOrValueSizeMismatch() { + protected: + // flag must be within BPF_OBJ_FLAG_MASK, ie. 0, BPF_F_RDONLY, BPF_F_WRONLY + BpfMap<Key, Value>(const char* pathname, uint32_t flags) { + mMapFd.reset(mapRetrieve(pathname, flags)); if (!mMapFd.ok()) abort(); if (isAtLeastKernelVersion(4, 14, 0)) { if (bpfGetFdKeySize(mMapFd) != sizeof(Key)) abort(); @@ -59,13 +61,6 @@ class BpfMap { } } - protected: - // flag must be within BPF_OBJ_FLAG_MASK, ie. 0, BPF_F_RDONLY, BPF_F_WRONLY - BpfMap<Key, Value>(const char* pathname, uint32_t flags) { - mMapFd.reset(mapRetrieve(pathname, flags)); - abortOnKeyOrValueSizeMismatch(); - } - public: explicit BpfMap<Key, Value>(const char* pathname) : BpfMap<Key, Value>(pathname, 0) {} @@ -122,11 +117,14 @@ class BpfMap { if (!mMapFd.ok()) { return ErrnoErrorf("Pinned map not accessible or does not exist: ({})", path); } - // Normally we should return an error here instead of calling abort, - // but this cannot happen at runtime without a massive code bug (K/V type mismatch) - // and as such it's better to just blow the system up and let the developer fix it. - // Crashes are much more likely to be noticed than logs and missing functionality. - abortOnKeyOrValueSizeMismatch(); + if (isAtLeastKernelVersion(4, 14, 0)) { + // Normally we should return an error here instead of calling abort, + // but this cannot happen at runtime without a massive code bug (K/V type mismatch) + // and as such it's better to just blow the system up and let the developer fix it. + // Crashes are much more likely to be noticed than logs and missing functionality. + if (bpfGetFdKeySize(mMapFd) != sizeof(Key)) abort(); + if (bpfGetFdValueSize(mMapFd) != sizeof(Value)) abort(); + } return {}; } @@ -204,7 +202,11 @@ class BpfMap { // check BpfMap.isValid() and look at errno and see why systemcall() failed. [[clang::reinitializes]] void reset(int fd) { mMapFd.reset(fd); - if (mMapFd.ok()) abortOnKeyOrValueSizeMismatch(); + if ((fd >= 0) && isAtLeastKernelVersion(4, 14, 0)) { + if (bpfGetFdKeySize(mMapFd) != sizeof(Key)) abort(); + if (bpfGetFdValueSize(mMapFd) != sizeof(Value)) abort(); + if (bpfGetFdMapFlags(mMapFd) != 0) abort(); // TODO: fix for BpfMapRO + } } #endif diff --git a/common/native/bpf_headers/include/bpf/bpf_helpers.h b/common/native/bpf_headers/include/bpf/bpf_helpers.h index 236318d6..ae3ad2c9 100644 --- a/common/native/bpf_headers/include/bpf/bpf_helpers.h +++ b/common/native/bpf_headers/include/bpf/bpf_helpers.h @@ -30,16 +30,6 @@ // Android T / 13 Beta 3 (api level 33) - added support for 'netd_shared' #define BPFLOADER_T_BETA3_VERSION 13u -// v0.18 added support for shared and pindir, but still ignores selinux_content -// v0.19 added support for selinux_content along with the required selinux changes -// and should be available starting with Android T Beta 4 -// -// Android T / 13 (api level 33) - support for shared/selinux_context/pindir -#define BPFLOADER_T_VERSION 19u - -// BpfLoader v0.25+ support obj@ver.o files -#define BPFLOADER_OBJ_AT_VER_VERSION 25u - /* For mainline module use, you can #define BPFLOADER_{MIN/MAX}_VER * before #include "bpf_helpers.h" to change which bpfloaders will * process the resulting .o file. @@ -182,39 +172,20 @@ static int (*bpf_map_delete_elem_unsafe)(const struct bpf_map_def* map, return bpf_map_delete_elem_unsafe(&the_map, k); \ }; -#ifndef DEFAULT_BPF_MAP_SELINUX_CONTEXT -#define DEFAULT_BPF_MAP_SELINUX_CONTEXT "" -#endif - -#ifndef DEFAULT_BPF_MAP_PIN_SUBDIR -#define DEFAULT_BPF_MAP_PIN_SUBDIR "" -#endif - -#ifndef DEFAULT_BPF_MAP_UID -#define DEFAULT_BPF_MAP_UID AID_ROOT -#elif BPFLOADER_MIN_VER < 21u -#error "Bpf Map UID must be left at default of AID_ROOT for BpfLoader prior to v0.21" -#endif - #define DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, usr, grp, md) \ - DEFINE_BPF_MAP_EXT(the_map, TYPE, KeyType, ValueType, num_entries, usr, grp, md, \ - DEFAULT_BPF_MAP_SELINUX_CONTEXT, DEFAULT_BPF_MAP_PIN_SUBDIR, false) + DEFINE_BPF_MAP_EXT(the_map, TYPE, KeyType, ValueType, num_entries, usr, grp, md, "", "", false) #define DEFINE_BPF_MAP(the_map, TYPE, KeyType, ValueType, num_entries) \ - DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \ - DEFAULT_BPF_MAP_UID, AID_ROOT, 0600) + DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, AID_ROOT, AID_ROOT, 0600) #define DEFINE_BPF_MAP_GWO(the_map, TYPE, KeyType, ValueType, num_entries, gid) \ - DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \ - DEFAULT_BPF_MAP_UID, gid, 0620) + DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, AID_ROOT, gid, 0620) #define DEFINE_BPF_MAP_GRO(the_map, TYPE, KeyType, ValueType, num_entries, gid) \ - DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \ - DEFAULT_BPF_MAP_UID, gid, 0640) + DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, AID_ROOT, gid, 0640) #define DEFINE_BPF_MAP_GRW(the_map, TYPE, KeyType, ValueType, num_entries, gid) \ - DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \ - DEFAULT_BPF_MAP_UID, gid, 0660) + DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, AID_ROOT, gid, 0660) static int (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read; static int (*bpf_probe_read_str)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_str; @@ -243,18 +214,9 @@ static long (*bpf_get_current_comm)(void* buf, uint32_t buf_size) = (void*) BPF_ SECTION(SECTION_NAME) \ int the_prog -#ifndef DEFAULT_BPF_PROG_SELINUX_CONTEXT -#define DEFAULT_BPF_PROG_SELINUX_CONTEXT "" -#endif - -#ifndef DEFAULT_BPF_PROG_PIN_SUBDIR -#define DEFAULT_BPF_PROG_PIN_SUBDIR "" -#endif - #define DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \ opt) \ - DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, opt, \ - DEFAULT_BPF_PROG_SELINUX_CONTEXT, DEFAULT_BPF_PROG_PIN_SUBDIR) + DEFINE_BPF_PROG_EXT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, opt, "", "") // Programs (here used in the sense of functions/sections) marked optional are allowed to fail // to load (for example due to missing kernel patches). diff --git a/common/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h b/common/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h index d5b76701..4b29c448 100644 --- a/common/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h +++ b/common/native/bpf_syscall_wrappers/include/BpfSyscallWrappers.h @@ -150,12 +150,8 @@ inline int detachSingleProgram(bpf_attach_type type, const BPF_FD_TYPE prog_fd, }); } -// BPF_OBJ_GET_INFO_BY_FD requires 4.14+ kernel -// -// Note: some fields are only defined in newer kernels (ie. the map_info struct grows -// over time), so we need to check that the field we're interested in is actually -// supported/returned by the running kernel. We do this by checking it is fully -// within the bounds of the struct size as reported by the kernel. +// requires 4.14+ kernel + #define DEFINE_BPF_GET_FD_INFO(NAME, FIELD) \ inline int bpfGetFd ## NAME(const BPF_FD_TYPE map_fd) { \ struct bpf_map_info map_info = {}; \ diff --git a/common/native/netjniutils/Android.bp b/common/native/netjniutils/Android.bp index 22fd1fa4..d8e6a04c 100644 --- a/common/native/netjniutils/Android.bp +++ b/common/native/netjniutils/Android.bp @@ -19,9 +19,6 @@ package { cc_library_static { name: "libnetjniutils", srcs: ["netjniutils.cpp"], - static_libs: [ - "libmodules-utils-build", - ], header_libs: ["jni_headers"], shared_libs: ["liblog"], export_header_lib_headers: ["jni_headers"], diff --git a/common/native/netjniutils/netjniutils.cpp b/common/native/netjniutils/netjniutils.cpp index 8b7f903f..210c6c3a 100644 --- a/common/native/netjniutils/netjniutils.cpp +++ b/common/native/netjniutils/netjniutils.cpp @@ -15,7 +15,6 @@ #define LOG_TAG "netjniutils" #include "netjniutils/netjniutils.h" -#include <android-modules-utils/sdk_level.h> #include <dlfcn.h> #include <stdbool.h> @@ -30,6 +29,27 @@ namespace netjniutils { namespace { +bool IsAtLeastS() { + // TODO(b/158749603#comment19): move to android::modules::sdklevel::IsAtLeastS(). + int api_level = android_get_device_api_level(); + + // Guarded check for branches that do not have __ANDROID_API_S__. +#ifdef __ANDROID_API_S__ + if (api_level >= __ANDROID_API_S__) { + return true; + } +#endif + + if (api_level < __ANDROID_API_R__) { + return false; + } + + // Device looks like R or above, check codename as it could be (S or above). + static constexpr const char* kCodenameProperty = "ro.build.version.codename"; + char codename[PROP_VALUE_MAX] = { 0 }; + return (__system_property_get(kCodenameProperty, codename) > 0 && + codename[0] >= 'S' && codename[1] == '\0'); +} int GetNativeFileDescriptorWithoutNdk(JNIEnv* env, jobject javaFd) { // Prior to Android S, we need to find the descriptor field in the FileDescriptor class. The @@ -72,8 +92,7 @@ int GetNativeFileDescriptorWithNdk(JNIEnv* env, jobject javaFd) { } // namespace int GetNativeFileDescriptor(JNIEnv* env, jobject javaFd) { - static const bool preferNdkFileDescriptorApi = []() -> bool - { return android::modules::sdklevel::IsAtLeastS(); }(); + static const bool preferNdkFileDescriptorApi = []() -> bool { return IsAtLeastS(); }(); if (preferNdkFileDescriptorApi) { return GetNativeFileDescriptorWithNdk(env, javaFd); } else { diff --git a/common/netd/libnetdutils/include/netdutils/NetNativeTestBase.h b/common/netd/libnetdutils/include/netdutils/NetNativeTestBase.h deleted file mode 100644 index c8b30c62..00000000 --- a/common/netd/libnetdutils/include/netdutils/NetNativeTestBase.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2022 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 <android-base/format.h> -#include <android-base/logging.h> -#include "gtest/gtest.h" - -using ::testing::TestInfo; -using ::testing::UnitTest; - -#define DBG 1 - -/* - * Test base class for net native tests to support common usage. - */ -class NetNativeTestBase : public ::testing::Test { - public: - // TODO: update the logging when gtest supports logging the life cycle on each test. - NetNativeTestBase() { - if (DBG) LOG(INFO) << getTestCaseLog(true); - } - ~NetNativeTestBase() { - if (DBG) LOG(INFO) << getTestCaseLog(false); - } - - std::string getTestCaseLog(bool running) { - const TestInfo* const test_info = UnitTest::GetInstance()->current_test_info(); - return fmt::format("{}: {}#{}", (running ? "started" : "finished"), - test_info->test_suite_name(), test_info->name()); - } -}; diff --git a/common/tests/unit/src/com/android/net/module/util/BpfDumpTest.java b/common/tests/unit/src/com/android/net/module/util/BpfDumpTest.java deleted file mode 100644 index b166b4a4..00000000 --- a/common/tests/unit/src/com/android/net/module/util/BpfDumpTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2022 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 com.android.net.module.util; - -import static org.junit.Assert.assertEquals; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class BpfDumpTest { - @Test - public void testToBase64EncodedString() { - final Struct.U32 key = new Struct.U32(123); - final Struct.U32 value = new Struct.U32(456); - - // Verified in python: - // import base64 - // print(base64.b64encode(b'\x7b\x00\x00\x00')) # key: ewAAAA== - // print(base64.b64encode(b'\xc8\x01\x00\x00')) # value: yAEAAA== - assertEquals("7B000000", HexDump.toHexString(key.writeToBytes())); - assertEquals("C8010000", HexDump.toHexString(value.writeToBytes())); - assertEquals("ewAAAA==,yAEAAA==", BpfDump.toBase64EncodedString(key, value)); - } -} diff --git a/common/tests/unit/src/com/android/net/module/util/SharedLogTest.java b/common/tests/unit/src/com/android/net/module/util/SharedLogTest.java index aa1bfee4..446e8819 100644 --- a/common/tests/unit/src/com/android/net/module/util/SharedLogTest.java +++ b/common/tests/unit/src/com/android/net/module/util/SharedLogTest.java @@ -17,8 +17,6 @@ package com.android.net.module.util; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import androidx.test.filters.SmallTest; @@ -29,24 +27,16 @@ import org.junit.runner.RunWith; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; @RunWith(AndroidJUnit4.class) @SmallTest public class SharedLogTest { private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}"; private static final String TIMESTAMP = "HH:MM:SS"; - private static final String TAG = "top"; @Test public void testBasicOperation() { - final SharedLog logTop = new SharedLog(TAG); - assertTrue(TAG.equals(logTop.getTag())); - + final SharedLog logTop = new SharedLog("top"); logTop.mark("first post!"); final SharedLog logLevel2a = logTop.forSubComponent("twoA"); @@ -58,10 +48,8 @@ public class SharedLogTest { final SharedLog logLevel3 = logLevel2a.forSubComponent("three"); logTop.log("still logging"); - logLevel2b.e(new Exception("Got another exception")); - logLevel3.i("3 >> 2"); + logLevel3.log("3 >> 2"); logLevel2a.mark("ok: last post"); - logTop.logf("finished!"); final String[] expected = { " - MARK first post!", @@ -71,53 +59,29 @@ public class SharedLogTest { " - [twoB] ERROR Wait, here's one: Test", " - [twoA] WARN second post?", " - still logging", - " - [twoB] ERROR java.lang.Exception: Got another exception", " - [twoA.three] 3 >> 2", " - [twoA] MARK ok: last post", - " - finished!", }; // Verify the logs are all there and in the correct order. - assertDumpLogs(expected, logTop); + verifyLogLines(expected, logTop); // In fact, because they all share the same underlying LocalLog, // every subcomponent SharedLog's dump() is identical. - assertDumpLogs(expected, logLevel2a); - assertDumpLogs(expected, logLevel2b); - assertDumpLogs(expected, logLevel3); - } - - private static void assertDumpLogs(String[] expected, SharedLog log) { - verifyLogLines(expected, dump(log)); - verifyLogLines(reverse(expected), reverseDump(log)); - } - - private static String dump(SharedLog log) { - return getSharedLogString(pw -> log.dump(null /* fd */, pw, null /* args */)); + verifyLogLines(expected, logLevel2a); + verifyLogLines(expected, logLevel2b); + verifyLogLines(expected, logLevel3); } - private static String reverseDump(SharedLog log) { - return getSharedLogString(pw -> log.reverseDump(pw)); - } - - private static String[] reverse(String[] ary) { - final List<String> ls = new ArrayList<>(Arrays.asList(ary)); - Collections.reverse(ls); - return ls.toArray(new String[ary.length]); - } - - private static String getSharedLogString(Consumer<PrintWriter> functor) { + private static void verifyLogLines(String[] expected, SharedLog log) { final ByteArrayOutputStream ostream = new ByteArrayOutputStream(); final PrintWriter pw = new PrintWriter(ostream, true); - functor.accept(pw); + log.dump(null, pw, null); final String dumpOutput = ostream.toString(); - assertNotNull(dumpOutput); - assertFalse("".equals(dumpOutput)); - return dumpOutput; - } + assertTrue(dumpOutput != null); + assertTrue(!"".equals(dumpOutput)); - private static void verifyLogLines(String[] expected, String gottenLogs) { - final String[] lines = gottenLogs.split("\n"); + final String[] lines = dumpOutput.split("\n"); assertEquals(expected.length, lines.length); for (int i = 0; i < expected.length; i++) { diff --git a/common/testutils/devicetests/com/android/testutils/ContextUtils.kt b/common/testutils/devicetests/com/android/testutils/ContextUtils.kt index 936b5682..814a75b4 100644 --- a/common/testutils/devicetests/com/android/testutils/ContextUtils.kt +++ b/common/testutils/devicetests/com/android/testutils/ContextUtils.kt @@ -53,15 +53,3 @@ fun mockContextAsUser(context: Context, functor: ((Context, UserHandle) -> Unit) asUserContext }.`when`(context).createContextAsUser(any(UserHandle::class.java), anyInt() /* flags */) } - -/** - * Helper function to mock the desired system service. - * - * @param context the mock context to set up the getSystemService and getSystemServiceName. - * @param clazz the system service class that intents to mock. - * @param service the system service name that intents to mock. - */ -fun <T> mockService(context: Context, clazz: Class<T>, name: String, service: T) { - doReturn(service).`when`(context).getSystemService(name) - doReturn(name).`when`(context).getSystemServiceName(clazz) -}
\ No newline at end of file diff --git a/common/testutils/devicetests/com/android/testutils/TestPermissionUtil.kt b/common/testutils/devicetests/com/android/testutils/TestPermissionUtil.kt index a4dbd9ad..f557f186 100644 --- a/common/testutils/devicetests/com/android/testutils/TestPermissionUtil.kt +++ b/common/testutils/devicetests/com/android/testutils/TestPermissionUtil.kt @@ -19,7 +19,6 @@ package com.android.testutils import androidx.test.platform.app.InstrumentationRegistry -import com.android.modules.utils.build.SdkLevel import com.android.testutils.ExceptionUtils.ThrowingRunnable import com.android.testutils.ExceptionUtils.ThrowingSupplier @@ -32,23 +31,6 @@ import com.android.testutils.ExceptionUtils.ThrowingSupplier */ fun <T> runAsShell(vararg permissions: String, task: () -> T): T { val autom = InstrumentationRegistry.getInstrumentation().uiAutomation - - // Calls to adoptShellPermissionIdentity do not nest, and dropShellPermissionIdentity drops all - // permissions. Thus, nesting calls will almost certainly cause test bugs, On S+, where we can - // detect this, refuse to do it. - // - // TODO: when R is deprecated, we could try to make this work instead. - // - Get the list of previously-adopted permissions. - // - Adopt the union of the previously-adopted and newly-requested permissions. - // - Run the task. - // - Adopt the previously-adopted permissions, dropping the ones just adopted. - // - // This would allow tests (and utility classes, such as the TestCarrierConfigReceiver attempted - // in aosp/2106007) to call runAsShell even within a test that has already adopted permissions. - if (SdkLevel.isAtLeastS() && !autom.getAdoptedShellPermissions().isNullOrEmpty()) { - throw IllegalStateException("adoptShellPermissionIdentity calls must not be nested") - } - autom.adoptShellPermissionIdentity(*permissions) try { return task() |