mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-13 17:46:47 +07:00
netfilter: xt_connlimit: honor conntrack zone if available
Currently all the conntrack lookups are done using default zone. In case the skb has a ct attached (e.g. template) we should use this zone for lookups instead. This makes connlimit work with connections assigned to other zones. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
8225161545
commit
e59ea3df3f
@ -134,6 +134,7 @@ static bool add_hlist(struct hlist_head *head,
|
|||||||
static unsigned int check_hlist(struct net *net,
|
static unsigned int check_hlist(struct net *net,
|
||||||
struct hlist_head *head,
|
struct hlist_head *head,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
|
u16 zone,
|
||||||
bool *addit)
|
bool *addit)
|
||||||
{
|
{
|
||||||
const struct nf_conntrack_tuple_hash *found;
|
const struct nf_conntrack_tuple_hash *found;
|
||||||
@ -147,8 +148,7 @@ static unsigned int check_hlist(struct net *net,
|
|||||||
|
|
||||||
/* check the saved connections */
|
/* check the saved connections */
|
||||||
hlist_for_each_entry_safe(conn, n, head, node) {
|
hlist_for_each_entry_safe(conn, n, head, node) {
|
||||||
found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE,
|
found = nf_conntrack_find_get(net, zone, &conn->tuple);
|
||||||
&conn->tuple);
|
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
hlist_del(&conn->node);
|
hlist_del(&conn->node);
|
||||||
kmem_cache_free(connlimit_conn_cachep, conn);
|
kmem_cache_free(connlimit_conn_cachep, conn);
|
||||||
@ -201,7 +201,7 @@ static unsigned int
|
|||||||
count_tree(struct net *net, struct rb_root *root,
|
count_tree(struct net *net, struct rb_root *root,
|
||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
const union nf_inet_addr *addr, const union nf_inet_addr *mask,
|
const union nf_inet_addr *addr, const union nf_inet_addr *mask,
|
||||||
u8 family)
|
u8 family, u16 zone)
|
||||||
{
|
{
|
||||||
struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES];
|
struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES];
|
||||||
struct rb_node **rbnode, *parent;
|
struct rb_node **rbnode, *parent;
|
||||||
@ -229,7 +229,7 @@ count_tree(struct net *net, struct rb_root *root,
|
|||||||
} else {
|
} else {
|
||||||
/* same source network -> be counted! */
|
/* same source network -> be counted! */
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
count = check_hlist(net, &rbconn->hhead, tuple, &addit);
|
count = check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
|
||||||
|
|
||||||
tree_nodes_free(root, gc_nodes, gc_count);
|
tree_nodes_free(root, gc_nodes, gc_count);
|
||||||
if (!addit)
|
if (!addit)
|
||||||
@ -245,7 +245,7 @@ count_tree(struct net *net, struct rb_root *root,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* only used for GC on hhead, retval and 'addit' ignored */
|
/* only used for GC on hhead, retval and 'addit' ignored */
|
||||||
check_hlist(net, &rbconn->hhead, tuple, &addit);
|
check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
|
||||||
if (hlist_empty(&rbconn->hhead))
|
if (hlist_empty(&rbconn->hhead))
|
||||||
gc_nodes[gc_count++] = rbconn;
|
gc_nodes[gc_count++] = rbconn;
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ static int count_them(struct net *net,
|
|||||||
const struct nf_conntrack_tuple *tuple,
|
const struct nf_conntrack_tuple *tuple,
|
||||||
const union nf_inet_addr *addr,
|
const union nf_inet_addr *addr,
|
||||||
const union nf_inet_addr *mask,
|
const union nf_inet_addr *mask,
|
||||||
u_int8_t family)
|
u_int8_t family, u16 zone)
|
||||||
{
|
{
|
||||||
struct rb_root *root;
|
struct rb_root *root;
|
||||||
int count;
|
int count;
|
||||||
@ -306,7 +306,7 @@ static int count_them(struct net *net,
|
|||||||
|
|
||||||
spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
|
spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
|
||||||
|
|
||||||
count = count_tree(net, root, tuple, addr, mask, family);
|
count = count_tree(net, root, tuple, addr, mask, family, zone);
|
||||||
|
|
||||||
spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
|
spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
|
||||||
|
|
||||||
@ -324,13 +324,16 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|||||||
enum ip_conntrack_info ctinfo;
|
enum ip_conntrack_info ctinfo;
|
||||||
const struct nf_conn *ct;
|
const struct nf_conn *ct;
|
||||||
unsigned int connections;
|
unsigned int connections;
|
||||||
|
u16 zone = NF_CT_DEFAULT_ZONE;
|
||||||
|
|
||||||
ct = nf_ct_get(skb, &ctinfo);
|
ct = nf_ct_get(skb, &ctinfo);
|
||||||
if (ct != NULL)
|
if (ct != NULL) {
|
||||||
tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
||||||
else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
|
zone = nf_ct_zone(ct);
|
||||||
par->family, &tuple))
|
} else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
|
||||||
|
par->family, &tuple)) {
|
||||||
goto hotdrop;
|
goto hotdrop;
|
||||||
|
}
|
||||||
|
|
||||||
if (par->family == NFPROTO_IPV6) {
|
if (par->family == NFPROTO_IPV6) {
|
||||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||||
@ -343,7 +346,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|||||||
}
|
}
|
||||||
|
|
||||||
connections = count_them(net, info->data, tuple_ptr, &addr,
|
connections = count_them(net, info->data, tuple_ptr, &addr,
|
||||||
&info->mask, par->family);
|
&info->mask, par->family, zone);
|
||||||
if (connections == 0)
|
if (connections == 0)
|
||||||
/* kmalloc failed, drop it entirely */
|
/* kmalloc failed, drop it entirely */
|
||||||
goto hotdrop;
|
goto hotdrop;
|
||||||
|
Loading…
Reference in New Issue
Block a user