Commit 9e0f0430 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nft_flow_offload: reset dst in route object after setting up flow

dst is transferred to the flow object, route object does not own it
anymore.  Reset dst in route object, otherwise if flow_offload_add()
fails, error path releases dst twice, leading to a refcount underflow.

Fixes: a3c90f7a ("netfilter: nf_tables: flow offload expression")
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent bccebf64
...@@ -276,7 +276,7 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table, ...@@ -276,7 +276,7 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
} }
void flow_offload_route_init(struct flow_offload *flow, void flow_offload_route_init(struct flow_offload *flow,
const struct nf_flow_route *route); struct nf_flow_route *route);
int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
void flow_offload_refresh(struct nf_flowtable *flow_table, void flow_offload_refresh(struct nf_flowtable *flow_table,
......
...@@ -87,12 +87,22 @@ static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple) ...@@ -87,12 +87,22 @@ static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
return 0; return 0;
} }
static struct dst_entry *nft_route_dst_fetch(struct nf_flow_route *route,
enum flow_offload_tuple_dir dir)
{
struct dst_entry *dst = route->tuple[dir].dst;
route->tuple[dir].dst = NULL;
return dst;
}
static int flow_offload_fill_route(struct flow_offload *flow, static int flow_offload_fill_route(struct flow_offload *flow,
const struct nf_flow_route *route, struct nf_flow_route *route,
enum flow_offload_tuple_dir dir) enum flow_offload_tuple_dir dir)
{ {
struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple; struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
struct dst_entry *dst = route->tuple[dir].dst; struct dst_entry *dst = nft_route_dst_fetch(route, dir);
int i, j = 0; int i, j = 0;
switch (flow_tuple->l3proto) { switch (flow_tuple->l3proto) {
...@@ -146,7 +156,7 @@ static void nft_flow_dst_release(struct flow_offload *flow, ...@@ -146,7 +156,7 @@ static void nft_flow_dst_release(struct flow_offload *flow,
} }
void flow_offload_route_init(struct flow_offload *flow, void flow_offload_route_init(struct flow_offload *flow,
const struct nf_flow_route *route) struct nf_flow_route *route)
{ {
flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL); flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL);
flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY); flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY);
......
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