xfrm: rate limit SA mapping change message to user space
[ Upstream commit 4e484b3e969b52effd95c17f7a86f39208b2ccf4 ] Kernel generates mapping change message, XFRM_MSG_MAPPING, when a source port chage is detected on a input state with UDP encapsulation set. Kernel generates a message for each IPsec packet with new source port. For a high speed flow per packet mapping change message can be excessive, and can overload the user space listener. Introduce rate limiting for XFRM_MSG_MAPPING message to the user space. The rate limiting is configurable via netlink, when adding a new SA or updating it. Use the new attribute XFRMA_MTIMER_THRESH in seconds. v1->v2 change: update xfrm_sa_len() v2->v3 changes: use u32 insted unsigned long to reduce size of struct xfrm_state fix xfrm_ompat size Reported-by: kernel test robot <lkp@intel.com> accept XFRM_MSG_MAPPING only when XFRMA_ENCAP is present Co-developed-by: Thomas Egerer <thomas.egerer@secunet.com> Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com> Signed-off-by: Antony Antony <antony.antony@secunet.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
0b7beb2fea
commit
a0b13335a3
@@ -1557,6 +1557,9 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
|
||||
x->km.seq = orig->km.seq;
|
||||
x->replay = orig->replay;
|
||||
x->preplay = orig->preplay;
|
||||
x->mapping_maxage = orig->mapping_maxage;
|
||||
x->new_mapping = 0;
|
||||
x->new_mapping_sport = 0;
|
||||
|
||||
return x;
|
||||
|
||||
@@ -2208,7 +2211,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
|
||||
}
|
||||
EXPORT_SYMBOL(km_query);
|
||||
|
||||
int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
|
||||
static int __km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
struct xfrm_mgr *km;
|
||||
@@ -2223,6 +2226,24 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (x->mapping_maxage) {
|
||||
if ((jiffies / HZ - x->new_mapping) > x->mapping_maxage ||
|
||||
x->new_mapping_sport != sport) {
|
||||
x->new_mapping_sport = sport;
|
||||
x->new_mapping = jiffies / HZ;
|
||||
ret = __km_new_mapping(x, ipaddr, sport);
|
||||
}
|
||||
} else {
|
||||
ret = __km_new_mapping(x, ipaddr, sport);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(km_new_mapping);
|
||||
|
||||
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 portid)
|
||||
|
Reference in New Issue
Block a user