diff --git a/app/src/main/jni/netguard/dhcp.c b/app/src/main/jni/netguard/dhcp.c index d8d3194c..afa31d47 100644 --- a/app/src/main/jni/netguard/dhcp.c +++ b/app/src/main/jni/netguard/dhcp.c @@ -53,7 +53,7 @@ int check_dhcp(const struct arguments *args, const struct udp_session *u, // Ack: source: 10.1.10.1 destination: 255.255.255.255 if (request->opcode == 1) { // Discover/request - struct dhcp_packet *response = ng_calloc(500, 1); + struct dhcp_packet *response = ng_calloc(500, 1, "dhcp"); // Hack inet_pton(AF_INET, "10.1.10.1", (void *) &u->saddr); diff --git a/app/src/main/jni/netguard/icmp.c b/app/src/main/jni/netguard/icmp.c index 9f444e1e..e9c7fef5 100644 --- a/app/src/main/jni/netguard/icmp.c +++ b/app/src/main/jni/netguard/icmp.c @@ -83,7 +83,7 @@ void check_icmp_socket(const struct arguments *args, const struct epoll_event *e s->icmp.time = time(NULL); uint16_t blen = (uint16_t) (s->icmp.version == 4 ? ICMP4_MAXMSG : ICMP6_MAXMSG); - uint8_t *buffer = ng_malloc(blen); + uint8_t *buffer = ng_malloc(blen, "icmp socket"); ssize_t bytes = recv(s->socket, buffer, blen, 0); if (bytes < 0) { // Socket error @@ -185,7 +185,7 @@ jboolean handle_icmp(const struct arguments *args, log_android(ANDROID_LOG_INFO, "ICMP new session from %s to %s", source, dest); // Register session - struct ng_session *s = ng_malloc(sizeof(struct ng_session)); + struct ng_session *s = ng_malloc(sizeof(struct ng_session), "icmp session"); s->protocol = (uint8_t) (version == 4 ? IPPROTO_ICMP : IPPROTO_ICMPV6); s->icmp.time = time(NULL); @@ -306,7 +306,7 @@ ssize_t write_icmp(const struct arguments *args, const struct icmp_session *cur, // Build packet if (cur->version == 4) { len = sizeof(struct iphdr) + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "icmp write4"); struct iphdr *ip4 = (struct iphdr *) buffer; if (datalen) memcpy(buffer + sizeof(struct iphdr), data, datalen); @@ -325,7 +325,7 @@ ssize_t write_icmp(const struct arguments *args, const struct icmp_session *cur, ip4->check = ~calc_checksum(0, (uint8_t *) ip4, sizeof(struct iphdr)); } else { len = sizeof(struct ip6_hdr) + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "icmp write6"); struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer; if (datalen) memcpy(buffer + sizeof(struct ip6_hdr), data, datalen); diff --git a/app/src/main/jni/netguard/ip.c b/app/src/main/jni/netguard/ip.c index d8651dae..b35af60b 100644 --- a/app/src/main/jni/netguard/ip.c +++ b/app/src/main/jni/netguard/ip.c @@ -53,7 +53,7 @@ int check_tun(const struct arguments *args, // Check tun read if (ev->events & EPOLLIN) { - uint8_t *buffer = ng_malloc(get_mtu()); + uint8_t *buffer = ng_malloc(get_mtu(), "tun read"); ssize_t length = read(args->tun, buffer, get_mtu()); if (length < 0) { ng_free(buffer); @@ -483,11 +483,11 @@ jint get_uid_sub(const int version, const int protocol, if (c >= uid_cache_size) { if (uid_cache_size == 0) - uid_cache = ng_malloc(sizeof(struct uid_cache_entry)); + uid_cache = ng_malloc(sizeof(struct uid_cache_entry), "uid_cache init"); else uid_cache = ng_realloc(uid_cache, - sizeof(struct uid_cache_entry) * - (uid_cache_size + 1)); + sizeof(struct uid_cache_entry) * + (uid_cache_size + 1), "uid_cache extend"); c = uid_cache_size; uid_cache_size++; } diff --git a/app/src/main/jni/netguard/netguard.c b/app/src/main/jni/netguard/netguard.c index fe0c8100..85c28eb8 100644 --- a/app/src/main/jni/netguard/netguard.c +++ b/app/src/main/jni/netguard/netguard.c @@ -100,7 +100,7 @@ void JNI_OnUnload(JavaVM *vm, void *reserved) { JNIEXPORT jlong JNICALL Java_eu_faircode_netguard_ServiceSinkhole_jni_1init( JNIEnv *env, jobject instance, jint sdk) { - struct context *ctx = ng_calloc(1, sizeof(struct context)); + struct context *ctx = ng_calloc(1, sizeof(struct context), "init"); ctx->sdk = sdk; loglevel = ANDROID_LOG_WARN; @@ -155,7 +155,7 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1run( errno, strerror(errno)); // Get arguments - struct arguments *args = ng_malloc(sizeof(struct arguments)); + struct arguments *args = ng_malloc(sizeof(struct arguments), "arguments"); args->env = env; args->instance = instance; args->tun = tun; @@ -899,19 +899,102 @@ void account_usage(const struct arguments *args, jint version, jint protocol, #endif } -void *ng_malloc(size_t __byte_count) { - return malloc(__byte_count); +struct alloc_record { + const char *tag; + void *ptr; +}; + +int allocs = 0; +int balance = 0; +struct alloc_record *alloc = NULL; +pthread_mutex_t *alock = NULL; + +void ng_add_alloc(void *ptr, const char *tag) { + if (ptr == NULL) + return; + + if (alock == NULL) { + alock = malloc(sizeof(pthread_mutex_t)); + if (pthread_mutex_init(alock, NULL)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_init failed"); + } + + if (pthread_mutex_lock(alock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed"); + + int c = 0; + for (; c < allocs; c++) + if (alloc[c].ptr == NULL) + break; + + if (c >= allocs) { + if (allocs == 0) + alloc = malloc(sizeof(struct alloc_record)); + else + alloc = realloc(alloc, sizeof(struct alloc_record) * (allocs + 1)); + c = allocs; + allocs++; + } + + alloc[c].tag = tag; + alloc[c].ptr = ptr; + balance++; + + if (pthread_mutex_unlock(alock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed"); } -void *ng_calloc(size_t __item_count, size_t __item_size) { - return calloc(__item_count, __item_size); +void ng_delete_alloc(void *ptr) { + if (ptr == NULL) + return; + + if (pthread_mutex_lock(alock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_lock failed"); + + int found = 0; + for (int c = 0; c < allocs; c++) + if (alloc[c].ptr == ptr) { + found = 1; + alloc[c].tag = "[free]"; + alloc[c].ptr = NULL; + break; + } + + if (found == 1) + balance--; + + log_android(found ? ANDROID_LOG_DEBUG : ANDROID_LOG_ERROR, + "alloc/free balance %d records %d found %d", balance, allocs, found); + + int r = 0; + for (int c = 0; c < allocs; c++) + if (alloc[c].ptr != NULL) + log_android(ANDROID_LOG_DEBUG, "holding %d [%s]", ++r, alloc[c].tag); + + if (pthread_mutex_unlock(alock)) + log_android(ANDROID_LOG_ERROR, "pthread_mutex_unlock failed"); } -void *ng_realloc(void *__ptr, size_t __byte_count) { - return realloc(__ptr, __byte_count); +void *ng_malloc(size_t __byte_count, const char *tag) { + void *ptr = malloc(__byte_count); + ng_add_alloc(ptr, tag); + return ptr; +} + +void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag) { + void *ptr = calloc(__item_count, __item_size); + ng_add_alloc(ptr, tag); + return ptr; +} + +void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag) { + ng_delete_alloc(__ptr); + void *ptr = realloc(__ptr, __byte_count); + ng_add_alloc(ptr, tag); + return ptr; } void ng_free(void *__ptr) { + ng_delete_alloc(__ptr); free(__ptr); } - diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h index 0a5c1ce1..7009dd69 100644 --- a/app/src/main/jni/netguard/netguard.h +++ b/app/src/main/jni/netguard/netguard.h @@ -552,10 +552,10 @@ int is_writable(int fd); long long get_ms(); -void *ng_malloc(size_t __byte_count); +void *ng_malloc(size_t __byte_count, const char *tag); -void *ng_calloc(size_t __item_count, size_t __item_size); +void *ng_calloc(size_t __item_count, size_t __item_size, const char *tag); -void *ng_realloc(void *__ptr, size_t __byte_count); +void *ng_realloc(void *__ptr, size_t __byte_count, const char *tag); void ng_free(void *__ptr); diff --git a/app/src/main/jni/netguard/pcap.c b/app/src/main/jni/netguard/pcap.c index f01c2c24..fa5363c0 100644 --- a/app/src/main/jni/netguard/pcap.c +++ b/app/src/main/jni/netguard/pcap.c @@ -42,7 +42,7 @@ void write_pcap_rec(const uint8_t *buffer, size_t length) { size_t plen = (length < pcap_record_size ? length : pcap_record_size); size_t rlen = sizeof(struct pcaprec_hdr_s) + plen; - struct pcaprec_hdr_s *pcap_rec = ng_malloc(rlen); + struct pcaprec_hdr_s *pcap_rec = ng_malloc(rlen, "pcap"); pcap_rec->ts_sec = (guint32_t) ts.tv_sec; pcap_rec->ts_usec = (guint32_t) (ts.tv_nsec / 1000); diff --git a/app/src/main/jni/netguard/tcp.c b/app/src/main/jni/netguard/tcp.c index 8724b467..40488e99 100644 --- a/app/src/main/jni/netguard/tcp.c +++ b/app/src/main/jni/netguard/tcp.c @@ -557,7 +557,7 @@ void check_tcp_socket(const struct arguments *args, uint32_t buffer_size = (send_window > s->tcp.mss ? s->tcp.mss : send_window); - uint8_t *buffer = ng_malloc(buffer_size); + uint8_t *buffer = ng_malloc(buffer_size, "tcp socket"); ssize_t bytes = recv(s->socket, buffer, (size_t) buffer_size, 0); if (bytes < 0) { // Socket error @@ -723,7 +723,7 @@ jboolean handle_tcp(const struct arguments *args, packet, mss, ws, ntohs(tcphdr->window) << ws); // Register session - struct ng_session *s = ng_malloc(sizeof(struct ng_session)); + struct ng_session *s = ng_malloc(sizeof(struct ng_session), "tcp session"); s->protocol = IPPROTO_TCP; s->tcp.time = time(NULL); @@ -760,12 +760,12 @@ jboolean handle_tcp(const struct arguments *args, if (datalen) { log_android(ANDROID_LOG_WARN, "%s SYN data", packet); - s->tcp.forward = ng_malloc(sizeof(struct segment)); + s->tcp.forward = ng_malloc(sizeof(struct segment), "syn segment"); s->tcp.forward->seq = s->tcp.remote_seq; s->tcp.forward->len = datalen; s->tcp.forward->sent = 0; s->tcp.forward->psh = tcphdr->psh; - s->tcp.forward->data = ng_malloc(datalen); + s->tcp.forward->data = ng_malloc(datalen, "syn segment data"); memcpy(s->tcp.forward->data, data, datalen); s->tcp.forward->next = NULL; } @@ -995,12 +995,12 @@ void queue_tcp(const struct arguments *args, log_android(ANDROID_LOG_DEBUG, "%s queuing %u...%u", session, seq - cur->remote_start, seq + datalen - cur->remote_start); - struct segment *n = ng_malloc(sizeof(struct segment)); + struct segment *n = ng_malloc(sizeof(struct segment), "tcp segment"); n->seq = seq; n->len = datalen; n->sent = 0; n->psh = tcphdr->psh; - n->data = ng_malloc(datalen); + n->data = ng_malloc(datalen, "tcp segment"); memcpy(n->data, data, datalen); n->next = s; if (p == NULL) @@ -1019,7 +1019,7 @@ void queue_tcp(const struct arguments *args, s->seq + datalen - cur->remote_start); ng_free(s->data); s->len = datalen; - s->data = ng_malloc(datalen); + s->data = ng_malloc(datalen, "tcp segment smaller"); memcpy(s->data, data, datalen); } else { log_android(ANDROID_LOG_ERROR, "%s segment larger %u..%u < %u", @@ -1028,7 +1028,7 @@ void queue_tcp(const struct arguments *args, s->seq + datalen - cur->remote_start); ng_free(s->data); s->len = datalen; - s->data = ng_malloc(datalen); + s->data = ng_malloc(datalen, "tcp segment larger"); memcpy(s->data, data, datalen); } } @@ -1188,7 +1188,7 @@ ssize_t write_tcp(const struct arguments *args, const struct tcp_session *cur, uint8_t *options; if (cur->version == 4) { len = sizeof(struct iphdr) + sizeof(struct tcphdr) + optlen + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "tcp write4"); struct iphdr *ip4 = (struct iphdr *) buffer; tcp = (struct tcphdr *) (buffer + sizeof(struct iphdr)); options = buffer + sizeof(struct iphdr) + sizeof(struct tcphdr); @@ -1219,7 +1219,7 @@ ssize_t write_tcp(const struct arguments *args, const struct tcp_session *cur, csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo)); } else { len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "tcp write 6"); struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer; tcp = (struct tcphdr *) (buffer + sizeof(struct ip6_hdr)); options = buffer + sizeof(struct ip6_hdr) + sizeof(struct tcphdr); diff --git a/app/src/main/jni/netguard/udp.c b/app/src/main/jni/netguard/udp.c index d7ae7513..347854cd 100644 --- a/app/src/main/jni/netguard/udp.c +++ b/app/src/main/jni/netguard/udp.c @@ -104,7 +104,7 @@ void check_udp_socket(const struct arguments *args, const struct epoll_event *ev if (ev->events & EPOLLIN) { s->udp.time = time(NULL); - uint8_t *buffer = ng_malloc(s->udp.mss); + uint8_t *buffer = ng_malloc(s->udp.mss, "udp recv"); ssize_t bytes = recv(s->socket, buffer, s->udp.mss, 0); if (bytes < 0) { // Socket error @@ -196,7 +196,7 @@ void block_udp(const struct arguments *args, source, ntohs(udphdr->source), dest, ntohs(udphdr->dest)); // Register session - struct ng_session *s = ng_malloc(sizeof(struct ng_session)); + struct ng_session *s = ng_malloc(sizeof(struct ng_session), "udp session block"); s->protocol = IPPROTO_UDP; s->udp.time = time(NULL); @@ -267,7 +267,7 @@ jboolean handle_udp(const struct arguments *args, source, ntohs(udphdr->source), dest, ntohs(udphdr->dest)); // Register session - struct ng_session *s = ng_malloc(sizeof(struct ng_session)); + struct ng_session *s = ng_malloc(sizeof(struct ng_session), "udp session"); s->protocol = IPPROTO_UDP; s->udp.time = time(NULL); @@ -447,7 +447,7 @@ ssize_t write_udp(const struct arguments *args, const struct udp_session *cur, // Build packet if (cur->version == 4) { len = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "udp write4"); struct iphdr *ip4 = (struct iphdr *) buffer; udp = (struct udphdr *) (buffer + sizeof(struct iphdr)); if (datalen) @@ -477,7 +477,7 @@ ssize_t write_udp(const struct arguments *args, const struct udp_session *cur, csum = calc_checksum(0, (uint8_t *) &pseudo, sizeof(struct ippseudo)); } else { len = sizeof(struct ip6_hdr) + sizeof(struct udphdr) + datalen; - buffer = ng_malloc(len); + buffer = ng_malloc(len, "udp write6"); struct ip6_hdr *ip6 = (struct ip6_hdr *) buffer; udp = (struct udphdr *) (buffer + sizeof(struct ip6_hdr)); if (datalen) diff --git a/app/src/main/jni/netguard/util.c b/app/src/main/jni/netguard/util.c index b3eaecec..c81bdfe3 100644 --- a/app/src/main/jni/netguard/util.c +++ b/app/src/main/jni/netguard/util.c @@ -130,7 +130,7 @@ char *hex(const u_int8_t *data, const size_t len) { char hex_str[] = "0123456789ABCDEF"; char *hexout; - hexout = (char *) ng_malloc(len * 3 + 1); // TODO free + hexout = (char *) ng_malloc(len * 3 + 1, "hex"); // TODO free for (size_t i = 0; i < len; i++) { hexout[i * 3 + 0] = hex_str[(data[i] >> 4) & 0x0F];