diff --git a/nfq2/conntrack.c b/nfq2/conntrack.c index a7cfba8..d7156b2 100644 --- a/nfq2/conntrack.c +++ b/nfq2/conntrack.c @@ -353,7 +353,7 @@ void ConntrackPoolDump(const t_conntrack *p) HASH_ITER(hh, p->pool, t, tmp) { taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1)); taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2)); - printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ", + printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%llu ", proto_name(t->conn.l4proto), sa1, t->conn.sport, sa2, t->conn.dport, t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-", diff --git a/nfq2/darkmagic.c b/nfq2/darkmagic.c index 310f7f8..a7778a9 100644 --- a/nfq2/darkmagic.c +++ b/nfq2/darkmagic.c @@ -526,6 +526,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto) break; case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved hdrlen = 8; + if (len < hdrlen) return false; // error fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK); fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG); break; diff --git a/nfq2/lua.c b/nfq2/lua.c index 7fa8c6d..9849369 100644 --- a/nfq2/lua.c +++ b/nfq2/lua.c @@ -1538,6 +1538,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len) break; case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved hdrlen = 8; + if (len < hdrlen) goto end; fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK); fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG); break; diff --git a/nfq2/nfqws.c b/nfq2/nfqws.c index 1443f88..edb44de 100644 --- a/nfq2/nfqws.c +++ b/nfq2/nfqws.c @@ -235,6 +235,7 @@ static int write_pidfile(FILE **Fpid) #ifdef __linux__ +// cookie must point to mod buffer with size RECONSTRUCT_MAX_SIZE static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie) { int id, ilen; @@ -244,8 +245,8 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da uint32_t ifidx_out, ifidx_in; char ifout[IFNAMSIZ], ifin[IFNAMSIZ]; size_t modlen; + uint8_t *mod = (uint8_t*)cookie; uint32_t mark; - uint8_t mod[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16))); ph = nfq_get_msg_packet_hdr(nfa); id = ph ? ntohl(ph->packet_id) : 0; @@ -266,7 +267,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da if (ilen >= 0) { len = ilen; - modlen = sizeof(mod); + modlen = RECONSTRUCT_MAX_SIZE; // there's no space to grow packet in recv blob from nfqueue. it can contain multiple packets with no extra buffer length for modifications. // to support increased sizes use separate mod buffer // this is not a problem because only LUA code can trigger VERDICT_MODIFY (and postnat workaround too, once a connection if first packet is dropped) @@ -300,7 +301,7 @@ static void nfq_deinit(struct nfq_handle **h, struct nfq_q_handle **qh) *h = NULL; } } -static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh) +static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *mod_buffer) { nfq_deinit(h, qh); @@ -330,7 +331,7 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh) } DLOG_CONDUP("binding this socket to queue '%u'\n", params.qnum); - *qh = nfq_create_queue(*h, params.qnum, &nfq_cb, ¶ms); + *qh = nfq_create_queue(*h, params.qnum, &nfq_cb, mod_buffer); if (!*qh) { DLOG_PERROR("nfq_create_queue()"); goto exiterr; @@ -381,7 +382,7 @@ static int nfq_main(void) int res, fd, e; ssize_t rd; FILE *Fpid = NULL; - uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16))); + uint8_t *buf=NULL, *mod=NULL; if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w"))) { @@ -423,7 +424,13 @@ static int nfq_main(void) goto exok; } - if (!nfq_init(&h, &qh)) + if (!(buf = malloc(RECONSTRUCT_MAX_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE))) + { + DLOG_ERR("out of memory\n"); + goto err; + } + + if (!nfq_init(&h, &qh, mod)) goto err; #ifdef HAS_FILTER_SSID @@ -446,7 +453,7 @@ static int nfq_main(void) fd = nfq_fd(h); do { - while ((rd = recv(fd, buf, sizeof(buf), 0)) >= 0) + while ((rd = recv(fd, buf, RECONSTRUCT_MAX_SIZE, 0)) >= 0) { if (bQuit) goto quit; ReloadCheck(); @@ -482,6 +489,8 @@ static int nfq_main(void) exok: res=0; ex: + free(mod); + free(buf); nfq_deinit(&h, &qh); lua_shutdown(); #ifdef HAS_FILTER_SSID @@ -1649,7 +1658,7 @@ static void exithelp(void) *all_protos=0; for (t_l7proto pr=0 ; pr|\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n" " --lua-gc=\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n" "\nMULTI-STRATEGY:\n" - " --new[=]\t\t\t\t\t\t\t; begin new profile. optionally set name\n" + " --new[=]\t\t\t\t\t\t; begin new profile. optionally set name\n" " --skip\t\t\t\t\t\t\t; do not use this profile\n" " --name=\t\t\t\t\t\t; set profile name\n" " --template[=]\t\t\t\t\t; use this profile as template (must be named or will be useless)\n" diff --git a/nfq2/protocol.c b/nfq2/protocol.c index fc7fffc..eab47f1 100644 --- a/nfq2/protocol.c +++ b/nfq2/protocol.c @@ -17,12 +17,15 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t ** { int i; const uint8_t *p1,*p2; + + if (level<1) return false; for (i=1,p2=dom+dlen;idom && *p2!='.'; p2--); if (p2<=dom) return false; } for (p1=p2-1 ; p1>dom && *p1!='.'; p1--); + if (p1