diff --git a/app/src/main/jni/netguard/dhcp.c b/app/src/main/jni/netguard/dhcp.c index afa31d47..f7bf389e 100644 --- a/app/src/main/jni/netguard/dhcp.c +++ b/app/src/main/jni/netguard/dhcp.c @@ -136,7 +136,7 @@ int check_dhcp(const struct arguments *args, const struct udp_session *u, write_udp(args, u, (uint8_t *) response, 500); - ng_free(response); + ng_free(response, __FILE__, __LINE__); } return 0; diff --git a/app/src/main/jni/netguard/icmp.c b/app/src/main/jni/netguard/icmp.c index e9c7fef5..c4fbf0a1 100644 --- a/app/src/main/jni/netguard/icmp.c +++ b/app/src/main/jni/netguard/icmp.c @@ -136,7 +136,7 @@ void check_icmp_socket(const struct arguments *args, const struct epoll_event *e if (write_icmp(args, &s->icmp, buffer, (size_t) bytes) < 0) s->icmp.stop = 1; } - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); } } } @@ -208,7 +208,7 @@ jboolean handle_icmp(const struct arguments *args, // Open UDP socket s->socket = open_icmp_socket(args, &s->icmp); if (s->socket < 0) { - ng_free(s); + ng_free(s, __FILE__, __LINE__); return 0; } @@ -363,7 +363,7 @@ ssize_t write_icmp(const struct arguments *args, const struct icmp_session *cur, } else log_android(ANDROID_LOG_WARN, "ICMP write error %d: %s", errno, strerror(errno)); - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); if (res != len) { log_android(ANDROID_LOG_ERROR, "write %d/%d", res, len); diff --git a/app/src/main/jni/netguard/ip.c b/app/src/main/jni/netguard/ip.c index b35af60b..c87d727e 100644 --- a/app/src/main/jni/netguard/ip.c +++ b/app/src/main/jni/netguard/ip.c @@ -56,7 +56,7 @@ int check_tun(const struct arguments *args, uint8_t *buffer = ng_malloc(get_mtu(), "tun read"); ssize_t length = read(args->tun, buffer, get_mtu()); if (length < 0) { - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); log_android(ANDROID_LOG_ERROR, "tun %d read error %d: %s", args->tun, errno, strerror(errno)); @@ -81,10 +81,10 @@ int check_tun(const struct arguments *args, // Handle IP from tun handle_ip(args, buffer, (size_t) length, epoll_fd, sessions, maxsessions); - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); } else { // tun eof - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); log_android(ANDROID_LOG_ERROR, "tun %d empty read", args->tun); report_exit(args, "tun %d empty read", args->tun); diff --git a/app/src/main/jni/netguard/netguard.c b/app/src/main/jni/netguard/netguard.c index 1f64b355..fd483306 100644 --- a/app/src/main/jni/netguard/netguard.c +++ b/app/src/main/jni/netguard/netguard.c @@ -287,7 +287,7 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1pcap( } (*env)->ReleaseStringUTFChars(env, name_, name); - ng_delete_alloc(name); + ng_delete_alloc(name, __FILE__, __LINE__); } //if (pthread_mutex_unlock(&lock)) @@ -316,9 +316,9 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1socks5(JNIEnv *env, jobject insta (*env)->ReleaseStringUTFChars(env, addr_, addr); (*env)->ReleaseStringUTFChars(env, username_, username); (*env)->ReleaseStringUTFChars(env, password_, password); - ng_delete_alloc(addr); - ng_delete_alloc(username); - ng_delete_alloc(password); + ng_delete_alloc(addr, __FILE__, __LINE__); + ng_delete_alloc(username, __FILE__, __LINE__); + ng_delete_alloc(password, __FILE__, __LINE__); } JNIEXPORT void JNICALL @@ -337,11 +337,11 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1done( log_android(ANDROID_LOG_ERROR, "Close pipe error %d: %s", errno, strerror(errno)); if (uid_cache != NULL) - ng_free(uid_cache); + ng_free(uid_cache, __FILE__, __LINE__); uid_cache_size = 0; uid_cache = NULL; - ng_free(ctx); + ng_free(ctx, __FILE__, __LINE__); } // JNI Util @@ -355,7 +355,7 @@ Java_eu_faircode_netguard_Util_jni_1getprop(JNIEnv *env, jclass type, jstring na __system_property_get(name, value); (*env)->ReleaseStringUTFChars(env, name_, name); - ng_delete_alloc(name); + ng_delete_alloc(name, __FILE__, __LINE__); return (*env)->NewStringUTF(env, value); // Freed by Java } @@ -378,7 +378,7 @@ Java_eu_faircode_netguard_Util_is_1numeric_1address(JNIEnv *env, jclass type, js numeric = (jboolean) (result != NULL); (*env)->ReleaseStringUTFChars(env, ip_, ip); - ng_delete_alloc(ip); + ng_delete_alloc(ip, __FILE__, __LINE__); return numeric; } @@ -403,10 +403,10 @@ void report_exit(const struct arguments *args, const char *fmt, ...) { if (jreason != NULL) { (*args->env)->DeleteLocalRef(args->env, jreason); - ng_delete_alloc(jreason); + ng_delete_alloc(jreason, __FILE__, __LINE__); } (*args->env)->DeleteLocalRef(args->env, cls); - ng_delete_alloc(cls); + ng_delete_alloc(cls, __FILE__, __LINE__); } void report_error(const struct arguments *args, jint error, const char *fmt, ...) { @@ -430,10 +430,10 @@ void report_error(const struct arguments *args, jint error, const char *fmt, ... if (jreason != NULL) { (*args->env)->DeleteLocalRef(args->env, jreason); - ng_delete_alloc(jreason); + ng_delete_alloc(jreason, __FILE__, __LINE__); } (*args->env)->DeleteLocalRef(args->env, cls); - ng_delete_alloc(cls); + ng_delete_alloc(cls, __FILE__, __LINE__); } static jmethodID midProtect = NULL; @@ -466,7 +466,7 @@ int protect_socket(const struct arguments *args, int socket) { } (*args->env)->DeleteLocalRef(args->env, cls); - ng_delete_alloc(cls); + ng_delete_alloc(cls, __FILE__, __LINE__); return 0; } @@ -521,7 +521,7 @@ int jniCheckException(JNIEnv *env) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); (*env)->DeleteLocalRef(env, ex); - ng_delete_alloc(ex); + ng_delete_alloc(ex, __FILE__, __LINE__); return 1; } return 0; @@ -548,8 +548,8 @@ void log_packet(const struct arguments *args, jobject jpacket) { (*args->env)->DeleteLocalRef(args->env, clsService); (*args->env)->DeleteLocalRef(args->env, jpacket); - ng_delete_alloc(clsService); - ng_delete_alloc(jpacket); + ng_delete_alloc(clsService, __FILE__, __LINE__); + ng_delete_alloc(jpacket, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -621,11 +621,11 @@ void dns_resolved(const struct arguments *args, (*args->env)->DeleteLocalRef(args->env, jqname); (*args->env)->DeleteLocalRef(args->env, jrr); (*args->env)->DeleteLocalRef(args->env, clsService); - ng_delete_alloc(jresource); - ng_delete_alloc(janame); - ng_delete_alloc(jqname); - ng_delete_alloc(jrr); - ng_delete_alloc(clsService); + ng_delete_alloc(jresource, __FILE__, __LINE__); + ng_delete_alloc(janame, __FILE__, __LINE__); + ng_delete_alloc(jqname, __FILE__, __LINE__); + ng_delete_alloc(jrr, __FILE__, __LINE__); + ng_delete_alloc(clsService, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -661,8 +661,8 @@ jboolean is_domain_blocked(const struct arguments *args, const char *name) { (*args->env)->DeleteLocalRef(args->env, jname); (*args->env)->DeleteLocalRef(args->env, clsService); - ng_delete_alloc(jname); - ng_delete_alloc(clsService); + ng_delete_alloc(jname, __FILE__, __LINE__); + ng_delete_alloc(clsService, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -707,9 +707,9 @@ jint get_uid_q(const struct arguments *args, (*args->env)->DeleteLocalRef(args->env, jdest); (*args->env)->DeleteLocalRef(args->env, jsource); (*args->env)->DeleteLocalRef(args->env, clsService); - ng_delete_alloc(jdest); - ng_delete_alloc(jsource); - ng_delete_alloc(clsService); + ng_delete_alloc(jdest, __FILE__, __LINE__); + ng_delete_alloc(jsource, __FILE__, __LINE__); + ng_delete_alloc(clsService, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -743,6 +743,7 @@ struct allowed *is_address_allowed(const struct arguments *args, jobject jpacket jobject jallowed = (*args->env)->CallObjectMethod( args->env, args->instance, midIsAddressAllowed, jpacket); + ng_add_alloc(jallowed, "jallowed"); jniCheckException(args->env); if (jallowed != NULL) { @@ -761,21 +762,21 @@ struct allowed *is_address_allowed(const struct arguments *args, jobject jpacket ng_add_alloc(raddr, "raddr"); strcpy(allowed.raddr, raddr); (*args->env)->ReleaseStringUTFChars(args->env, jraddr, raddr); - ng_delete_alloc(raddr); + ng_delete_alloc(raddr, __FILE__, __LINE__); } allowed.rport = (uint16_t) (*args->env)->GetIntField(args->env, jallowed, fidRport); (*args->env)->DeleteLocalRef(args->env, jraddr); - ng_delete_alloc(jraddr); + ng_delete_alloc(jraddr, __FILE__, __LINE__); } (*args->env)->DeleteLocalRef(args->env, jpacket); (*args->env)->DeleteLocalRef(args->env, clsService); (*args->env)->DeleteLocalRef(args->env, jallowed); - ng_delete_alloc(jpacket); - ng_delete_alloc(clsService); - ng_delete_alloc(jallowed); + ng_delete_alloc(jpacket, __FILE__, __LINE__); + ng_delete_alloc(clsService, __FILE__, __LINE__); + ng_delete_alloc(jallowed, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -876,10 +877,10 @@ jobject create_packet(const struct arguments *args, (*env)->DeleteLocalRef(env, jdest); (*env)->DeleteLocalRef(env, jsource); (*env)->DeleteLocalRef(env, jflags); - ng_delete_alloc(jdata); - ng_delete_alloc(jdest); - ng_delete_alloc(jsource); - ng_delete_alloc(jflags); + ng_delete_alloc(jdata, __FILE__, __LINE__); + ng_delete_alloc(jdest, __FILE__, __LINE__); + ng_delete_alloc(jsource, __FILE__, __LINE__); + ng_delete_alloc(jflags, __FILE__, __LINE__); // Caller needs to delete reference to packet #ifdef PROFILE_JNI @@ -957,9 +958,9 @@ void account_usage(const struct arguments *args, jint version, jint protocol, (*args->env)->DeleteLocalRef(args->env, jdaddr); (*args->env)->DeleteLocalRef(args->env, jusage); (*args->env)->DeleteLocalRef(args->env, clsService); - ng_delete_alloc(jdaddr); - ng_delete_alloc(jusage); - ng_delete_alloc(clsService); + ng_delete_alloc(jdaddr, __FILE__, __LINE__); + ng_delete_alloc(jusage, __FILE__, __LINE__); + ng_delete_alloc(clsService, __FILE__, __LINE__); #ifdef PROFILE_JNI gettimeofday(&end, NULL); @@ -1019,7 +1020,7 @@ void ng_add_alloc(void *ptr, const char *tag) { #endif } -void ng_delete_alloc(void *ptr) { +void ng_delete_alloc(void *ptr, const char *file, int line) { #ifdef PROFILE_MEMORY if (ptr == NULL) return; @@ -1041,6 +1042,8 @@ void ng_delete_alloc(void *ptr) { log_android(found ? ANDROID_LOG_DEBUG : ANDROID_LOG_ERROR, "alloc/free balance %d records %d found %d", balance, allocs, found); + if (found == 0) + log_android(ANDROID_LOG_ERROR, "Not found at %s:%d", file, line); if (pthread_mutex_unlock(alock)) log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed"); @@ -1060,14 +1063,14 @@ void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag) { } void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag) { - ng_delete_alloc(__ptr); + ng_delete_alloc(__ptr, NULL, 0); void *ptr = realloc(__ptr, __byte_count); ng_add_alloc(ptr, tag); return ptr; } -void ng_free(void *__ptr) { - ng_delete_alloc(__ptr); +void ng_free(void *__ptr, const char *file, int line) { + ng_delete_alloc(__ptr, file, line); free(__ptr); } diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h index 1a22cebb..65b6c7d1 100644 --- a/app/src/main/jni/netguard/netguard.h +++ b/app/src/main/jni/netguard/netguard.h @@ -36,7 +36,7 @@ #define TAG "NetGuard.JNI" // #define PROFILE_JNI 5 -// #define PROFILE_MEMORY +#define PROFILE_MEMORY #define EPOLL_TIMEOUT 3600 // seconds #define EPOLL_EVENTS 20 @@ -555,7 +555,7 @@ long long get_ms(); void ng_add_alloc(void *ptr, const char *tag); -void ng_delete_alloc(void *ptr); +void ng_delete_alloc(void *ptr, const char *file, int line); void *ng_malloc(size_t __byte_count, const char *tag); @@ -563,6 +563,6 @@ void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag); void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag); -void ng_free(void *__ptr); +void ng_free(void *__ptr, const char *file, int line); void ng_dump(); diff --git a/app/src/main/jni/netguard/pcap.c b/app/src/main/jni/netguard/pcap.c index fa5363c0..134c49d9 100644 --- a/app/src/main/jni/netguard/pcap.c +++ b/app/src/main/jni/netguard/pcap.c @@ -53,7 +53,7 @@ void write_pcap_rec(const uint8_t *buffer, size_t length) { write_pcap(pcap_rec, rlen); - ng_free(pcap_rec); + ng_free(pcap_rec, __FILE__, __LINE__); } void write_pcap(const void *ptr, size_t len) { diff --git a/app/src/main/jni/netguard/session.c b/app/src/main/jni/netguard/session.c index 6713880d..14e032f6 100644 --- a/app/src/main/jni/netguard/session.c +++ b/app/src/main/jni/netguard/session.c @@ -29,7 +29,7 @@ void clear(struct context *ctx) { clear_tcp_data(&s->tcp); struct ng_session *p = s; s = s->next; - ng_free(p); + ng_free(p, __FILE__, __LINE__); } ctx->ng_session = NULL; } @@ -160,7 +160,7 @@ void *handle_events(void *a) { s = s->next; if (c->protocol == IPPROTO_TCP) clear_tcp_data(&c->tcp); - ng_free(c); + ng_free(c, __FILE__, __LINE__); } else { sl = s; s = s->next; @@ -276,7 +276,7 @@ void *handle_events(void *a) { "epoll close error %d: %s", errno, strerror(errno)); // Cleanup - ng_free(args); + ng_free(args, __FILE__, __LINE__); log_android(ANDROID_LOG_WARN, "Stopped events tun=%d", args->tun); return NULL; @@ -337,7 +337,7 @@ void check_allowed(const struct arguments *args) { struct ng_session *c = s; s = s->next; - ng_free(c); + ng_free(c, __FILE__, __LINE__); continue; } diff --git a/app/src/main/jni/netguard/tcp.c b/app/src/main/jni/netguard/tcp.c index 40488e99..a0c76ede 100644 --- a/app/src/main/jni/netguard/tcp.c +++ b/app/src/main/jni/netguard/tcp.c @@ -31,8 +31,8 @@ void clear_tcp_data(struct tcp_session *cur) { while (s != NULL) { struct segment *p = s; s = s->next; - ng_free(p->data); - ng_free(p); + ng_free(p->data, __FILE__, __LINE__); + ng_free(p, __FILE__, __LINE__); } } @@ -328,7 +328,7 @@ void check_tcp_socket(const struct arguments *args, } else { char *h = hex(buffer, (const size_t) bytes); log_android(ANDROID_LOG_INFO, "%s recv SOCKS5 %s", session, h); - ng_free(h); + ng_free(h, __FILE__, __LINE__); if (s->tcp.socks5 == SOCKS5_HELLO && bytes == 2 && buffer[0] == 5) { @@ -395,7 +395,7 @@ void check_tcp_socket(const struct arguments *args, char *h = hex(buffer, sizeof(buffer)); log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 hello: %s", session, h); - ng_free(h); + ng_free(h, __FILE__, __LINE__); ssize_t sent = send(s->socket, buffer, sizeof(buffer), MSG_NOSIGNAL); if (sent < 0) { log_android(ANDROID_LOG_ERROR, "%s send SOCKS5 hello error %d: %s", @@ -418,7 +418,7 @@ void check_tcp_socket(const struct arguments *args, char *h = hex(buffer, len); log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 auth: %s", session, h); - ng_free(h); + ng_free(h, __FILE__, __LINE__); ssize_t sent = send(s->socket, buffer, len, MSG_NOSIGNAL); if (sent < 0) { log_android(ANDROID_LOG_ERROR, @@ -446,7 +446,7 @@ void check_tcp_socket(const struct arguments *args, char *h = hex(buffer, len); log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 connect: %s", session, h); - ng_free(h); + ng_free(h, __FILE__, __LINE__); ssize_t sent = send(s->socket, buffer, len, MSG_NOSIGNAL); if (sent < 0) { log_android(ANDROID_LOG_ERROR, @@ -506,8 +506,8 @@ void check_tcp_socket(const struct arguments *args, struct segment *p = s->tcp.forward; s->tcp.forward = s->tcp.forward->next; - ng_free(p->data); - ng_free(p); + ng_free(p->data, __FILE__, __LINE__); + ng_free(p, __FILE__, __LINE__); } else { log_android(ANDROID_LOG_WARN, "%s partial send %u/%u", @@ -609,7 +609,7 @@ void check_tcp_socket(const struct arguments *args, s->tcp.unconfirmed++; } } - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); } } } @@ -774,7 +774,7 @@ jboolean handle_tcp(const struct arguments *args, s->socket = open_tcp_socket(args, &s->tcp, redirect); if (s->socket < 0) { // Remote might retry - ng_free(s); + ng_free(s, __FILE__, __LINE__); return 0; } @@ -1017,7 +1017,7 @@ void queue_tcp(const struct arguments *args, session, s->seq - cur->remote_start, s->seq + s->len - cur->remote_start, s->seq + datalen - cur->remote_start); - ng_free(s->data); + ng_free(s->data, __FILE__, __LINE__); s->len = datalen; s->data = ng_malloc(datalen, "tcp segment smaller"); memcpy(s->data, data, datalen); @@ -1026,7 +1026,7 @@ void queue_tcp(const struct arguments *args, session, s->seq - cur->remote_start, s->seq + s->len - cur->remote_start, s->seq + datalen - cur->remote_start); - ng_free(s->data); + ng_free(s->data, __FILE__, __LINE__); s->len = datalen; s->data = ng_malloc(datalen, "tcp segment larger"); memcpy(s->data, data, datalen); @@ -1316,7 +1316,7 @@ ssize_t write_tcp(const struct arguments *args, const struct tcp_session *cur, datalen, errno, strerror((errno))); - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); if (res != len) { log_android(ANDROID_LOG_ERROR, "TCP write %d/%d", res, len); diff --git a/app/src/main/jni/netguard/udp.c b/app/src/main/jni/netguard/udp.c index 347854cd..b070c0dc 100644 --- a/app/src/main/jni/netguard/udp.c +++ b/app/src/main/jni/netguard/udp.c @@ -142,7 +142,7 @@ void check_udp_socket(const struct arguments *args, const struct epoll_event *ev s->udp.state = UDP_FINISHING; } } - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); } } } @@ -300,7 +300,7 @@ jboolean handle_udp(const struct arguments *args, // Open UDP socket s->socket = open_udp_socket(args, &s->udp, redirect); if (s->socket < 0) { - ng_free(s); + ng_free(s, __FILE__, __LINE__); return 0; } @@ -538,7 +538,7 @@ ssize_t write_udp(const struct arguments *args, const struct udp_session *cur, } else log_android(ANDROID_LOG_WARN, "UDP write error %d: %s", errno, strerror(errno)); - ng_free(buffer); + ng_free(buffer, __FILE__, __LINE__); if (res != len) { log_android(ANDROID_LOG_ERROR, "write %d/%d", res, len);