From 09da6010da6350b2c8d9b322cbbe20e190aa4c7c Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 11 Feb 2016 09:12:00 +0100 Subject: [PATCH] Native limit number of sessions Refs #311 --- app/src/main/jni/netguard/ip.c | 22 +++++++++++++++++++--- app/src/main/jni/netguard/netguard.h | 8 ++++++-- app/src/main/jni/netguard/session.c | 15 ++++++++++----- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/app/src/main/jni/netguard/ip.c b/app/src/main/jni/netguard/ip.c index 6d39c1a6..3a5e288e 100644 --- a/app/src/main/jni/netguard/ip.c +++ b/app/src/main/jni/netguard/ip.c @@ -23,7 +23,9 @@ int max_tun_msg = 0; extern int loglevel; extern FILE *pcap_file; -int check_tun(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds) { +int check_tun(const struct arguments *args, + fd_set *rfds, fd_set *wfds, fd_set *efds, + int sessions, int maxsessions) { // Check tun error if (FD_ISSET(args->tun, efds)) { log_android(ANDROID_LOG_ERROR, "tun %d exception", args->tun); @@ -64,7 +66,7 @@ int check_tun(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set * } // Handle IP from tun - handle_ip(args, buffer, (size_t) length); + handle_ip(args, buffer, (size_t) length, sessions, maxsessions); free(buffer); } @@ -102,7 +104,9 @@ int is_upper_layer(int protocol) { protocol == IPPROTO_ICMPV6); } -void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t length) { +void handle_ip(const struct arguments *args, + const uint8_t *pkt, const size_t length, + int sessions, int maxsessions) { uint8_t protocol; void *saddr; void *daddr; @@ -255,6 +259,18 @@ void handle_ip(const struct arguments *args, const uint8_t *pkt, const size_t le } flags[flen] = 0; + // Limit number of sessions + if (sessions >= maxsessions) { + if ((protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6) || + (protocol == IPPROTO_UDP && !has_udp_session(args, pkt, payload)) || + (protocol == IPPROTO_TCP && syn)) { + log_android(ANDROID_LOG_ERROR, + "%d of max %d sessions, dropping version %d protocol %d", + sessions, maxsessions, protocol, version); + return; + } + } + // Get uid jint uid = -1; if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6 || diff --git a/app/src/main/jni/netguard/netguard.h b/app/src/main/jni/netguard/netguard.h index d2f851ce..8d557384 100644 --- a/app/src/main/jni/netguard/netguard.h +++ b/app/src/main/jni/netguard/netguard.h @@ -302,7 +302,9 @@ int get_tcp_timeout(const struct tcp_session *t, int sessions); int get_selects(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds); -int check_tun(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds); +int check_tun(const struct arguments *args, + fd_set *rfds, fd_set *wfds, fd_set *efds, + int sessions, int maxsessions); void check_icmp_sockets(const struct arguments *args, fd_set *rfds, fd_set *wfds, fd_set *efds); @@ -318,7 +320,9 @@ int is_lower_layer(int protocol); int is_upper_layer(int protocol); -void handle_ip(const struct arguments *args, const uint8_t *buffer, size_t length); +void handle_ip(const struct arguments *args, + const uint8_t *buffer, size_t length, + int sessions, int maxsessions); void init_icmp(const struct arguments *args); diff --git a/app/src/main/jni/netguard/session.c b/app/src/main/jni/netguard/session.c index 1957030a..83fa82ff 100644 --- a/app/src/main/jni/netguard/session.c +++ b/app/src/main/jni/netguard/session.c @@ -59,11 +59,15 @@ void *handle_events(void *a) { // Get SDK version sdk = sdk_int(env); + int maxsessions = 1024; struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim)) log_android(ANDROID_LOG_WARN, "getrlimit error %d: %s", errno, strerror(errno)); - else - log_android(ANDROID_LOG_WARN, "getrlimit soft %d hard %d", rlim.rlim_cur, rlim.rlim_max); + else { + maxsessions = rlim.rlim_cur * 80 / 100; + log_android(ANDROID_LOG_WARN, "getrlimit soft %d hard %d max sessions %d", + rlim.rlim_cur, rlim.rlim_max, maxsessions); + } // Block SIGUSR1 sigemptyset(&blockset); @@ -90,11 +94,12 @@ void *handle_events(void *a) { int isessions = check_icmp_sessions(args); int usessions = check_udp_sessions(args); int tsessions = check_tcp_sessions(args); + int sessions = isessions + usessions + tsessions; // https://bugzilla.mozilla.org/show_bug.cgi?id=1093893 int idle = (tsessions + usessions + tsessions == 0 && sdk >= 16); - log_android(ANDROID_LOG_DEBUG, "sessions ICMP %d UDP %d TCP %d idle %d sdk %d", - isessions, usessions, tsessions, idle, sdk); + log_android(ANDROID_LOG_DEBUG, "sessions ICMP %d UDP %d TCP %d max %d/%d idle %d sdk %d", + isessions, usessions, tsessions, sessions, maxsessions, idle, sdk); // Next event time ts.tv_sec = (sdk < 16 ? 5 : get_select_timeout(isessions, usessions, tsessions)); @@ -154,7 +159,7 @@ void *handle_events(void *a) { // Check upstream int error = 0; - if (check_tun(args, &rfds, &wfds, &efds) < 0) + if (check_tun(args, &rfds, &wfds, &efds, sessions, maxsessions) < 0) error = 1; else { #ifdef PROFILE_EVENTS