From 61c8b194c3d175c78316db599fc5f90d38399b5e Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 6 Jun 2019 11:58:22 +0200 Subject: [PATCH] Android Q support --- app/build.gradle | 8 +- app/proguard-rules.pro | 1 + .../eu/faircode/netguard/ServiceSinkhole.java | 20 ++ .../main/java/eu/faircode/netguard/Util.java | 3 + app/src/main/jni/netguard/ip.c | 8 +- app/src/main/jni/netguard/netguard.c | 41 ++++ app/src/main/jni/netguard/netguard.h | 8 + netguard_q.patch | 201 ------------------ tools/addr2line.sh | 2 +- 9 files changed, 84 insertions(+), 208 deletions(-) delete mode 100644 netguard_q.patch diff --git a/app/build.gradle b/app/build.gradle index 2835a4fd..a3952f52 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,14 +5,14 @@ def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { - compileSdkVersion = 28 + compileSdkVersion = 29 defaultConfig { applicationId = "eu.faircode.netguard" - versionName = "2.249" + versionName = "2.250" minSdkVersion 22 - targetSdkVersion 28 - versionCode = 2019060101 + targetSdkVersion 29 + versionCode = 2019060601 archivesBaseName = "NetGuard-v$versionName" externalNativeBuild { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 501b6193..adf6d1ab 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -39,6 +39,7 @@ void logPacket(eu.faircode.netguard.Packet); void dnsResolved(eu.faircode.netguard.ResourceRecord); boolean isDomainBlocked(java.lang.String); + int getUidQ(int, int, java.lang.String, int, java.lang.String, int); eu.faircode.netguard.Allowed isAddressAllowed(eu.faircode.netguard.Packet); void accountUsage(eu.faircode.netguard.Usage); } diff --git a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java index 31fdb4e8..304cd7af 100644 --- a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java +++ b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java @@ -72,6 +72,7 @@ import android.widget.RemoteViews; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.content.ContextCompat; +import androidx.core.os.BuildCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONArray; @@ -1829,6 +1830,25 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS return blocked; } + // Called from native code + @TargetApi(Build.VERSION_CODES.Q) + private int getUidQ(int version, int protocol, String saddr, int sport, String daddr, int dport) { + if (protocol != 6 /* TCP */ && protocol != 17 /* UDP */) + return Process.INVALID_UID; + + ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); + if (cm == null) + return Process.INVALID_UID; + + InetSocketAddress local = new InetSocketAddress(saddr, sport); + InetSocketAddress remote = new InetSocketAddress(daddr, dport); + + Log.i(TAG, "Get uid local=" + local + " remote=" + remote); + int uid = cm.getConnectionOwnerUid(protocol, local, remote); + Log.i(TAG, "Get uid=" + uid); + return uid; + } + private boolean isSupported(int protocol) { return (protocol == 1 /* ICMPv4 */ || protocol == 58 /* ICMPv6 */ || diff --git a/app/src/main/java/eu/faircode/netguard/Util.java b/app/src/main/java/eu/faircode/netguard/Util.java index 6d166aa5..fa21dcad 100644 --- a/app/src/main/java/eu/faircode/netguard/Util.java +++ b/app/src/main/java/eu/faircode/netguard/Util.java @@ -407,6 +407,9 @@ public class Util { } public static boolean canFilter(Context context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + return true; + // https://android-review.googlesource.com/#/c/206710/1/untrusted_app.te File tcp = new File("/proc/net/tcp"); File tcp6 = new File("/proc/net/tcp6"); diff --git a/app/src/main/jni/netguard/ip.c b/app/src/main/jni/netguard/ip.c index df721887..d60d5a95 100644 --- a/app/src/main/jni/netguard/ip.c +++ b/app/src/main/jni/netguard/ip.c @@ -285,8 +285,12 @@ void handle_ip(const struct arguments *args, jint uid = -1; if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6 || (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) || - (protocol == IPPROTO_TCP && syn)) - uid = get_uid(version, protocol, saddr, sport, daddr, dport); + (protocol == IPPROTO_TCP && syn)) { + if (args->ctx->sdk <= 28) // Android 9 Pie + uid = get_uid(version, protocol, saddr, sport, daddr, dport); + else + uid = get_uid_q(args, version, protocol, source, sport, dest, dport); + } log_android(ANDROID_LOG_DEBUG, "Packet v%d %s/%u > %s/%u proto %d flags %s uid %d", diff --git a/app/src/main/jni/netguard/netguard.c b/app/src/main/jni/netguard/netguard.c index a583cd1a..c9780e7b 100644 --- a/app/src/main/jni/netguard/netguard.c +++ b/app/src/main/jni/netguard/netguard.c @@ -625,6 +625,47 @@ jboolean is_domain_blocked(const struct arguments *args, const char *name) { return jallowed; } +static jmethodID midGetUidQ = NULL; + +jint get_uid_q(const struct arguments *args, + jint version, jint protocol, + const char *source, jint sport, + const char *dest, jint dport) { +#ifdef PROFILE_JNI + float mselapsed; + struct timeval start, end; + gettimeofday(&start, NULL); +#endif + + jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance); + + const char *signature = "(IILjava/lang/String;ILjava/lang/String;I)I"; + if (midGetUidQ == NULL) + midGetUidQ = jniGetMethodID(args->env, clsService, "getUidQ", signature); + + jstring jsource = (*args->env)->NewStringUTF(args->env, source); + jstring jdest = (*args->env)->NewStringUTF(args->env, dest); + + jint juid = (*args->env)->CallIntMethod( + args->env, args->instance, midGetUidQ, + version, protocol, jsource, sport, jdest, dport); + jniCheckException(args->env); + + (*args->env)->DeleteLocalRef(args->env, jdest); + (*args->env)->DeleteLocalRef(args->env, jsource); + (*args->env)->DeleteLocalRef(args->env, clsService); + +#ifdef PROFILE_JNI + gettimeofday(&end, NULL); + mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 + + (end.tv_usec - start.tv_usec) / 1000.0; + if (mselapsed > PROFILE_JNI) + log_android(ANDROID_LOG_WARN, "get_uid_q %f", mselapsed); +#endif + + return juid; +} + static jmethodID midIsAddressAllowed = NULL; jfieldID fidRaddr = NULL; jfieldID fidRport = NULL; diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h index 173be260..7ffcdc28 100644 --- a/app/src/main/jni/netguard/netguard.h +++ b/app/src/main/jni/netguard/netguard.h @@ -506,6 +506,14 @@ void dns_resolved(const struct arguments *args, jboolean is_domain_blocked(const struct arguments *args, const char *name); +jint get_uid_q(const struct arguments *args, + jint version, + jint protocol, + const char *source, + jint sport, + const char *dest, + jint dport); + struct allowed *is_address_allowed(const struct arguments *args, jobject objPacket); jobject create_packet(const struct arguments *args, diff --git a/netguard_q.patch b/netguard_q.patch deleted file mode 100644 index 0fd56eaa..00000000 --- a/netguard_q.patch +++ /dev/null @@ -1,201 +0,0 @@ -diff --git a/app/build.gradle b/app/build.gradle -index bcab1ef0..096a6f8a 100644 ---- a/app/build.gradle -+++ b/app/build.gradle -@@ -5,13 +5,13 @@ def keystoreProperties = new Properties() - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) - - android { -- compileSdkVersion = 28 -+ compileSdkVersion = 'android-Q' - - defaultConfig { - applicationId = "eu.faircode.netguard" - versionName = "2.245" - minSdkVersion 22 -- targetSdkVersion 28 -+ targetSdkVersion 'Q' - versionCode = 2019051701 - archivesBaseName = "NetGuard-v$versionName" - -diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro -index 501b6193..adf6d1ab 100644 ---- a/app/proguard-rules.pro -+++ b/app/proguard-rules.pro -@@ -39,6 +39,7 @@ - void logPacket(eu.faircode.netguard.Packet); - void dnsResolved(eu.faircode.netguard.ResourceRecord); - boolean isDomainBlocked(java.lang.String); -+ int getUidQ(int, int, java.lang.String, int, java.lang.String, int); - eu.faircode.netguard.Allowed isAddressAllowed(eu.faircode.netguard.Packet); - void accountUsage(eu.faircode.netguard.Usage); - } -diff --git a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java -index 7587807f..96655af1 100644 ---- a/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java -+++ b/app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java -@@ -72,6 +72,7 @@ import android.widget.RemoteViews; - import androidx.core.app.NotificationCompat; - import androidx.core.app.NotificationManagerCompat; - import androidx.core.content.ContextCompat; -+import androidx.core.os.BuildCompat; - import androidx.localbroadcastmanager.content.LocalBroadcastManager; - - import org.json.JSONArray; -@@ -1829,6 +1830,25 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS - return blocked; - } - -+ // Called from native code -+ @TargetApi(Build.VERSION_CODES.Q) -+ private int getUidQ(int version, int protocol, String saddr, int sport, String daddr, int dport) { -+ if (protocol != 6 /* TCP */ && protocol != 17 /* UDP */) -+ return Process.INVALID_UID; -+ -+ ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); -+ if (cm == null) -+ return Process.INVALID_UID; -+ -+ InetSocketAddress local = new InetSocketAddress(saddr, sport); -+ InetSocketAddress remote = new InetSocketAddress(daddr, dport); -+ -+ Log.i(TAG, "Get uid local=" + local + " remote=" + remote); -+ int uid = cm.getConnectionOwnerUid(protocol, local, remote); -+ Log.i(TAG, "Get uid=" + uid); -+ return uid; -+ } -+ - private boolean isSupported(int protocol) { - return (protocol == 1 /* ICMPv4 */ || - protocol == 59 /* ICMPv6 */ || -@@ -2316,7 +2336,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - - // Native init -- jni_context = jni_init(Build.VERSION.SDK_INT); -+ jni_context = jni_init(BuildCompat.isAtLeastQ() ? 29 : Build.VERSION.SDK_INT); - boolean pcap = prefs.getBoolean("pcap", false); - setPcap(pcap, this); - -diff --git a/app/src/main/java/eu/faircode/netguard/Util.java b/app/src/main/java/eu/faircode/netguard/Util.java -index 6d166aa5..35a0586b 100644 ---- a/app/src/main/java/eu/faircode/netguard/Util.java -+++ b/app/src/main/java/eu/faircode/netguard/Util.java -@@ -58,6 +58,7 @@ import android.widget.TextView; - - import androidx.appcompat.app.AlertDialog; - import androidx.core.net.ConnectivityManagerCompat; -+import androidx.core.os.BuildCompat; - - import java.io.BufferedReader; - import java.io.File; -@@ -407,6 +408,9 @@ public class Util { - } - - public static boolean canFilter(Context context) { -+ if (BuildCompat.isAtLeastQ()) -+ return true; -+ - // https://android-review.googlesource.com/#/c/206710/1/untrusted_app.te - File tcp = new File("/proc/net/tcp"); - File tcp6 = new File("/proc/net/tcp6"); -diff --git a/app/src/main/jni/netguard/ip.c b/app/src/main/jni/netguard/ip.c -index 41d25c50..cd6a50f2 100644 ---- a/app/src/main/jni/netguard/ip.c -+++ b/app/src/main/jni/netguard/ip.c -@@ -281,8 +281,12 @@ void handle_ip(const struct arguments *args, - jint uid = -1; - if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6 || - (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) || -- (protocol == IPPROTO_TCP && syn)) -- uid = get_uid(version, protocol, saddr, sport, daddr, dport); -+ (protocol == IPPROTO_TCP && syn)) { -+ if (args->ctx->sdk <= 28) // Android 9 Pie -+ uid = get_uid(version, protocol, saddr, sport, daddr, dport); -+ else -+ uid = get_uid_q(args, version, protocol, source, sport, dest, dport); -+ } - - log_android(ANDROID_LOG_DEBUG, - "Packet v%d %s/%u > %s/%u proto %d flags %s uid %d", -diff --git a/app/src/main/jni/netguard/netguard.c b/app/src/main/jni/netguard/netguard.c -index a583cd1a..c9780e7b 100644 ---- a/app/src/main/jni/netguard/netguard.c -+++ b/app/src/main/jni/netguard/netguard.c -@@ -625,6 +625,47 @@ jboolean is_domain_blocked(const struct arguments *args, const char *name) { - return jallowed; - } - -+static jmethodID midGetUidQ = NULL; -+ -+jint get_uid_q(const struct arguments *args, -+ jint version, jint protocol, -+ const char *source, jint sport, -+ const char *dest, jint dport) { -+#ifdef PROFILE_JNI -+ float mselapsed; -+ struct timeval start, end; -+ gettimeofday(&start, NULL); -+#endif -+ -+ jclass clsService = (*args->env)->GetObjectClass(args->env, args->instance); -+ -+ const char *signature = "(IILjava/lang/String;ILjava/lang/String;I)I"; -+ if (midGetUidQ == NULL) -+ midGetUidQ = jniGetMethodID(args->env, clsService, "getUidQ", signature); -+ -+ jstring jsource = (*args->env)->NewStringUTF(args->env, source); -+ jstring jdest = (*args->env)->NewStringUTF(args->env, dest); -+ -+ jint juid = (*args->env)->CallIntMethod( -+ args->env, args->instance, midGetUidQ, -+ version, protocol, jsource, sport, jdest, dport); -+ jniCheckException(args->env); -+ -+ (*args->env)->DeleteLocalRef(args->env, jdest); -+ (*args->env)->DeleteLocalRef(args->env, jsource); -+ (*args->env)->DeleteLocalRef(args->env, clsService); -+ -+#ifdef PROFILE_JNI -+ gettimeofday(&end, NULL); -+ mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 + -+ (end.tv_usec - start.tv_usec) / 1000.0; -+ if (mselapsed > PROFILE_JNI) -+ log_android(ANDROID_LOG_WARN, "get_uid_q %f", mselapsed); -+#endif -+ -+ return juid; -+} -+ - static jmethodID midIsAddressAllowed = NULL; - jfieldID fidRaddr = NULL; - jfieldID fidRport = NULL; -diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h -index 173be260..7ffcdc28 100644 ---- a/app/src/main/jni/netguard/netguard.h -+++ b/app/src/main/jni/netguard/netguard.h -@@ -506,6 +506,14 @@ void dns_resolved(const struct arguments *args, - - jboolean is_domain_blocked(const struct arguments *args, const char *name); - -+jint get_uid_q(const struct arguments *args, -+ jint version, -+ jint protocol, -+ const char *source, -+ jint sport, -+ const char *dest, -+ jint dport); -+ - struct allowed *is_address_allowed(const struct arguments *args, jobject objPacket); - - jobject create_packet(const struct arguments *args, -diff --git a/tools/addr2line.sh b/tools/addr2line.sh -index 60b4fd38..240db4fc 100644 ---- a/tools/addr2line.sh -+++ b/tools/addr2line.sh -@@ -1,4 +1,4 @@ - #!/bin/sh - addr2line=/media/marcel/C720/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line --lib=./app/build/intermediates/cmake/release/obj/arm64-v8a/libnetguard.so -+lib=./app/build/intermediates/cmake/debug/obj/arm64-v8a/libnetguard.so - addr2line -C -f -e $lib $1 diff --git a/tools/addr2line.sh b/tools/addr2line.sh index 60b4fd38..240db4fc 100644 --- a/tools/addr2line.sh +++ b/tools/addr2line.sh @@ -1,4 +1,4 @@ #!/bin/sh addr2line=/media/marcel/C720/android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line -lib=./app/build/intermediates/cmake/release/obj/arm64-v8a/libnetguard.so +lib=./app/build/intermediates/cmake/debug/obj/arm64-v8a/libnetguard.so addr2line -C -f -e $lib $1