from time to time, conntrackd segfaults in cache.c, function hash(), because it does not check the return value of nfct_get_attr(). For some reason (which I have not investigated), there is no ATTR_ORIG_IPV4_SRC. A gdb dump of *ct after the segfault says the following: (gdb) p *ct $3 = {tuple = {{src = {v4 = 4161143072, v6 = {in6_u = {u6_addr8 = " \001\006ø\023\205\000\001\000\000\000\000\000\000\000\002", u6_addr16 = {288, 63494, 34067, 256, 0, 0, 0, 512}, u6_addr32 = {4161143072, 16811283, 0, 33554432}}}}, dst = { v4 = 4161143072, v6 = {in6_u = {u6_addr8 = " \001\006ø\023\205ÿÿÿÿÿÿÿÿ\000\002", u6_addr16 = {288, 63494, 34067, 65535, 65535, 65535, 65535, 512}, u6_addr32 = {4161143072, 4294935827, 4294967295, 33619967}}}}, l3protonum = 10 '\n', protonum = 6 '\006', l4src = {all = 64727, tcp = {port = 64727}, udp = {port = 64727}, icmp = {type = 215 '×', code = 252 'ü', id = 0}, sctp = {port = 64727}}, l4dst = {all = 53767, tcp = {port = 53767}, udp = {port = 53767}, icmp = {type = 7 '\a', code = 210 'Ò', id = 0}, sctp = {port = 53767}}}, {src = {v4 = 4161143072, v6 = {in6_u = { u6_addr8 = " \001\006ø\023\205ÿÿÿÿÿÿÿÿ\000\002", u6_addr16 = {288, 63494, 34067, 65535, 65535, 65535, 65535, 512}, u6_addr32 = {4161143072, 4294935827, 4294967295, 33619967}}}}, dst = {v4 = 4161143072, v6 = {in6_u = { u6_addr8 = " \001\006ø\023\205\000\001\000\000\000\000\000\000\000\002", u6_addr16 = {288, 63494, 34067, 256, 0, 0, 0, 512}, u6_addr32 = {4161143072, 16811283, 0, 33554432}}}}, l3protonum = 10 '\n', protonum = 6 '\006', l4src = { all = 53767, tcp = {port = 53767}, udp = {port = 53767}, icmp = {type = 7 '\a', code = 210 'Ò', id = 0}, sctp = { port = 53767}}, l4dst = {all = 64727, tcp = {port = 64727}, udp = {port = 64727}, icmp = {type = 215 '×', code = 252 'ü', id = 0}, sctp = {port = 64727}}}, {src = {v4 = 0, v6 = {in6_u = {u6_addr8 = '\0' <repeats 15 times>, u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, u6_addr32 = {0, 0, 0, 0}}}}, dst = {v4 = 0, v6 = {in6_u = { u6_addr8 = '\0' <repeats 15 times>, u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0}, u6_addr32 = {0, 0, 0, 0}}}}, l3protonum = 0 '\0', protonum = 0 '\0', l4src = {all = 0, tcp = {port = 0}, udp = {port = 0}, icmp = {type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}, l4dst = {all = 0, tcp = {port = 0}, udp = {port = 0}, icmp = { type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}}}, timeout = 120, mark = 0, secmark = 0, status = 8, use = 0, id = 0, protoinfo = {tcp = {state = 1 '\001', flags = {{value = 3 '\003', mask = 0 '\0'}, {value = 0 '\0', mask = 0 '\0'}, { value = 0 '\0', mask = 0 '\0'}}}}, counters = {{packets = 0, bytes = 0}, {packets = 0, bytes = 0}, {packets = 0, bytes = 0}}, snat = {min_ip = 0, max_ip = 0, l4min = {all = 0, tcp = {port = 0}, udp = {port = 0}, icmp = {type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}, l4max = {all = 0, tcp = {port = 0}, udp = {port = 0}, icmp = {type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}}, dnat = {min_ip = 0, max_ip = 0, l4min = {all = 0, tcp = {port = 0}, udp = { port = 0}, icmp = {type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}, l4max = {all = 0, tcp = {port = 0}, udp = { port = 0}, icmp = {type = 0 '\0', code = 0 '\0', id = 0}, sctp = {port = 0}}}, set = {1019888, 31}} --- src/cache.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/cache.c b/src/cache.c index 2f0e57a..d0fb210 100644 --- a/src/cache.c +++ b/src/cache.c @@ -29,17 +29,26 @@ static uint32_t hash(const void *data, struct hashtable *table) { + const void *p; unsigned int a, b; const struct us_conntrack *u = data; struct nf_conntrack *ct = u->ct; - a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), sizeof(uint32_t), - ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | - (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); - - b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(uint32_t), - ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | - (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + p = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC); + if (p == NULL) + a = 0; + else + a = jhash(p, sizeof(uint32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + p = nfct_get_attr(ct, ATTR_ORIG_IPV4_DST); + if (p == NULL) + b = 0; + else + b = jhash(p, sizeof(uint32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); /* * Instead of returning hash % table->hashsize (implying a divide) @@ -53,17 +62,26 @@ static uint32_t hash(const void *data, struct hashtable *table) static uint32_t hash6(const void *data, struct hashtable *table) { + const void *p; unsigned int a, b; const struct us_conntrack *u = data; struct nf_conntrack *ct = u->ct; - a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC), sizeof(uint32_t)*4, - ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | - (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); - - b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(uint32_t)*4, - ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | - (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + p = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC); + if (p == NULL) + a = 0; + else + a = jhash(p, sizeof(uint32_t)*4, + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + p = nfct_get_attr(ct, ATTR_ORIG_IPV6_DST); + if (p == NULL) + b = 0; + else + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(uint32_t)*4, + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); return ((uint64_t)jhash_2words(a, b, 0) * table->hashsize) >> 32; } - To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html