Commit 22d4536d authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: conntrack: handle initial extension alloc via krealloc

krealloc(NULL, ..) is same as kmalloc(), so we can avoid special-casing
the initial allocation after the prealloc removal (we had to use
->alloc_len as the initial allocation size).

This also means we do not zero the preallocated memory anymore; only
offsets[].  Existing code makes sure the new (used) extension space gets
zeroed out.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 23f671a1
...@@ -44,49 +44,24 @@ void __nf_ct_ext_destroy(struct nf_conn *ct) ...@@ -44,49 +44,24 @@ void __nf_ct_ext_destroy(struct nf_conn *ct)
} }
EXPORT_SYMBOL(__nf_ct_ext_destroy); EXPORT_SYMBOL(__nf_ct_ext_destroy);
static void *
nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
{
unsigned int off, len, alloc;
struct nf_ct_ext_type *t;
rcu_read_lock();
t = rcu_dereference(nf_ct_ext_types[id]);
if (!t) {
rcu_read_unlock();
return NULL;
}
off = ALIGN(sizeof(struct nf_ct_ext), t->align);
len = off + t->len;
rcu_read_unlock();
alloc = max(len, NF_CT_EXT_PREALLOC);
*ext = kzalloc(alloc, gfp);
if (!*ext)
return NULL;
(*ext)->offset[id] = off;
(*ext)->len = len;
return (void *)(*ext) + off;
}
void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
{ {
unsigned int newlen, newoff, oldlen, alloc;
struct nf_ct_ext *old, *new; struct nf_ct_ext *old, *new;
int newlen, newoff;
struct nf_ct_ext_type *t; struct nf_ct_ext_type *t;
/* Conntrack must not be confirmed to avoid races on reallocation. */ /* Conntrack must not be confirmed to avoid races on reallocation. */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
old = ct->ext; old = ct->ext;
if (!old)
return nf_ct_ext_create(&ct->ext, id, gfp);
if (old) {
if (__nf_ct_ext_exist(old, id)) if (__nf_ct_ext_exist(old, id))
return NULL; return NULL;
oldlen = old->len;
} else {
oldlen = sizeof(*new);
}
rcu_read_lock(); rcu_read_lock();
t = rcu_dereference(nf_ct_ext_types[id]); t = rcu_dereference(nf_ct_ext_types[id]);
...@@ -95,15 +70,19 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) ...@@ -95,15 +70,19 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
return NULL; return NULL;
} }
newoff = ALIGN(old->len, t->align); newoff = ALIGN(oldlen, t->align);
newlen = newoff + t->len; newlen = newoff + t->len;
rcu_read_unlock(); rcu_read_unlock();
new = __krealloc(old, newlen, gfp); alloc = max(newlen, NF_CT_EXT_PREALLOC);
new = __krealloc(old, alloc, gfp);
if (!new) if (!new)
return NULL; return NULL;
if (new != old) { if (!old) {
memset(new->offset, 0, sizeof(new->offset));
ct->ext = new;
} else if (new != old) {
kfree_rcu(old, rcu); kfree_rcu(old, rcu);
rcu_assign_pointer(ct->ext, new); rcu_assign_pointer(ct->ext, new);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment