Commit 5663b854 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

This is fixing up the use without proper initialization in patch 5/5

-o-

Hi,

The following patchset contains Netfilter fixes for net:

1) Missing #ifdef CONFIG_IP6_NF_IPTABLES in recent xt_socket fix.

2) Fix incorrect flow action array size in nf_tables.

3) Unregister flowtable hooks from netns exit path.

4) Fix missing limit object release, from Florian Westphal.

5) Memleak in nf_tables object update path, also from Florian.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b6ad6261 dad3bdee
...@@ -905,9 +905,9 @@ struct nft_expr_ops { ...@@ -905,9 +905,9 @@ struct nft_expr_ops {
int (*offload)(struct nft_offload_ctx *ctx, int (*offload)(struct nft_offload_ctx *ctx,
struct nft_flow_rule *flow, struct nft_flow_rule *flow,
const struct nft_expr *expr); const struct nft_expr *expr);
bool (*offload_action)(const struct nft_expr *expr);
void (*offload_stats)(struct nft_expr *expr, void (*offload_stats)(struct nft_expr *expr,
const struct flow_stats *stats); const struct flow_stats *stats);
u32 offload_flags;
const struct nft_expr_type *type; const struct nft_expr_type *type;
void *data; void *data;
}; };
......
...@@ -67,8 +67,6 @@ struct nft_flow_rule { ...@@ -67,8 +67,6 @@ struct nft_flow_rule {
struct flow_rule *rule; struct flow_rule *rule;
}; };
#define NFT_OFFLOAD_F_ACTION (1 << 0)
void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow, void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
enum flow_dissector_key_id addr_type); enum flow_dissector_key_id addr_type);
......
...@@ -6551,12 +6551,15 @@ static int nf_tables_updobj(const struct nft_ctx *ctx, ...@@ -6551,12 +6551,15 @@ static int nf_tables_updobj(const struct nft_ctx *ctx,
{ {
struct nft_object *newobj; struct nft_object *newobj;
struct nft_trans *trans; struct nft_trans *trans;
int err; int err = -ENOMEM;
if (!try_module_get(type->owner))
return -ENOENT;
trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ, trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ,
sizeof(struct nft_trans_obj)); sizeof(struct nft_trans_obj));
if (!trans) if (!trans)
return -ENOMEM; goto err_trans;
newobj = nft_obj_init(ctx, type, attr); newobj = nft_obj_init(ctx, type, attr);
if (IS_ERR(newobj)) { if (IS_ERR(newobj)) {
...@@ -6573,6 +6576,8 @@ static int nf_tables_updobj(const struct nft_ctx *ctx, ...@@ -6573,6 +6576,8 @@ static int nf_tables_updobj(const struct nft_ctx *ctx,
err_free_trans: err_free_trans:
kfree(trans); kfree(trans);
err_trans:
module_put(type->owner);
return err; return err;
} }
...@@ -8185,7 +8190,7 @@ static void nft_obj_commit_update(struct nft_trans *trans) ...@@ -8185,7 +8190,7 @@ static void nft_obj_commit_update(struct nft_trans *trans)
if (obj->ops->update) if (obj->ops->update)
obj->ops->update(obj, newobj); obj->ops->update(obj, newobj);
kfree(newobj); nft_obj_destroy(&trans->ctx, newobj);
} }
static void nft_commit_release(struct nft_trans *trans) static void nft_commit_release(struct nft_trans *trans)
...@@ -8976,7 +8981,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) ...@@ -8976,7 +8981,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
break; break;
case NFT_MSG_NEWOBJ: case NFT_MSG_NEWOBJ:
if (nft_trans_obj_update(trans)) { if (nft_trans_obj_update(trans)) {
kfree(nft_trans_obj_newobj(trans)); nft_obj_destroy(&trans->ctx, nft_trans_obj_newobj(trans));
nft_trans_destroy(trans); nft_trans_destroy(trans);
} else { } else {
trans->ctx.table->use--; trans->ctx.table->use--;
...@@ -9636,10 +9641,13 @@ EXPORT_SYMBOL_GPL(__nft_release_basechain); ...@@ -9636,10 +9641,13 @@ EXPORT_SYMBOL_GPL(__nft_release_basechain);
static void __nft_release_hook(struct net *net, struct nft_table *table) static void __nft_release_hook(struct net *net, struct nft_table *table)
{ {
struct nft_flowtable *flowtable;
struct nft_chain *chain; struct nft_chain *chain;
list_for_each_entry(chain, &table->chains, list) list_for_each_entry(chain, &table->chains, list)
nf_tables_unregister_hook(net, table, chain); nf_tables_unregister_hook(net, table, chain);
list_for_each_entry(flowtable, &table->flowtables, list)
nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list);
} }
static void __nft_release_hooks(struct net *net) static void __nft_release_hooks(struct net *net)
......
...@@ -94,7 +94,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net, ...@@ -94,7 +94,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,
expr = nft_expr_first(rule); expr = nft_expr_first(rule);
while (nft_expr_more(rule, expr)) { while (nft_expr_more(rule, expr)) {
if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION) if (expr->ops->offload_action &&
expr->ops->offload_action(expr))
num_actions++; num_actions++;
expr = nft_expr_next(expr); expr = nft_expr_next(expr);
......
...@@ -67,6 +67,11 @@ static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx, ...@@ -67,6 +67,11 @@ static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx,
return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_MIRRED, oif); return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_MIRRED, oif);
} }
static bool nft_dup_netdev_offload_action(const struct nft_expr *expr)
{
return true;
}
static struct nft_expr_type nft_dup_netdev_type; static struct nft_expr_type nft_dup_netdev_type;
static const struct nft_expr_ops nft_dup_netdev_ops = { static const struct nft_expr_ops nft_dup_netdev_ops = {
.type = &nft_dup_netdev_type, .type = &nft_dup_netdev_type,
...@@ -75,6 +80,7 @@ static const struct nft_expr_ops nft_dup_netdev_ops = { ...@@ -75,6 +80,7 @@ static const struct nft_expr_ops nft_dup_netdev_ops = {
.init = nft_dup_netdev_init, .init = nft_dup_netdev_init,
.dump = nft_dup_netdev_dump, .dump = nft_dup_netdev_dump,
.offload = nft_dup_netdev_offload, .offload = nft_dup_netdev_offload,
.offload_action = nft_dup_netdev_offload_action,
}; };
static struct nft_expr_type nft_dup_netdev_type __read_mostly = { static struct nft_expr_type nft_dup_netdev_type __read_mostly = {
......
...@@ -79,6 +79,11 @@ static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx, ...@@ -79,6 +79,11 @@ static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx,
return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_REDIRECT, oif); return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_REDIRECT, oif);
} }
static bool nft_fwd_netdev_offload_action(const struct nft_expr *expr)
{
return true;
}
struct nft_fwd_neigh { struct nft_fwd_neigh {
u8 sreg_dev; u8 sreg_dev;
u8 sreg_addr; u8 sreg_addr;
...@@ -222,6 +227,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = { ...@@ -222,6 +227,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = {
.dump = nft_fwd_netdev_dump, .dump = nft_fwd_netdev_dump,
.validate = nft_fwd_validate, .validate = nft_fwd_validate,
.offload = nft_fwd_netdev_offload, .offload = nft_fwd_netdev_offload,
.offload_action = nft_fwd_netdev_offload_action,
}; };
static const struct nft_expr_ops * static const struct nft_expr_ops *
......
...@@ -213,6 +213,16 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx, ...@@ -213,6 +213,16 @@ static int nft_immediate_offload(struct nft_offload_ctx *ctx,
return 0; return 0;
} }
static bool nft_immediate_offload_action(const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
if (priv->dreg == NFT_REG_VERDICT)
return true;
return false;
}
static const struct nft_expr_ops nft_imm_ops = { static const struct nft_expr_ops nft_imm_ops = {
.type = &nft_imm_type, .type = &nft_imm_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
...@@ -224,7 +234,7 @@ static const struct nft_expr_ops nft_imm_ops = { ...@@ -224,7 +234,7 @@ static const struct nft_expr_ops nft_imm_ops = {
.dump = nft_immediate_dump, .dump = nft_immediate_dump,
.validate = nft_immediate_validate, .validate = nft_immediate_validate,
.offload = nft_immediate_offload, .offload = nft_immediate_offload,
.offload_flags = NFT_OFFLOAD_F_ACTION, .offload_action = nft_immediate_offload_action,
}; };
struct nft_expr_type nft_imm_type __read_mostly = { struct nft_expr_type nft_imm_type __read_mostly = {
......
...@@ -340,11 +340,20 @@ static int nft_limit_obj_pkts_dump(struct sk_buff *skb, ...@@ -340,11 +340,20 @@ static int nft_limit_obj_pkts_dump(struct sk_buff *skb,
return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS); return nft_limit_dump(skb, &priv->limit, NFT_LIMIT_PKTS);
} }
static void nft_limit_obj_pkts_destroy(const struct nft_ctx *ctx,
struct nft_object *obj)
{
struct nft_limit_priv_pkts *priv = nft_obj_data(obj);
nft_limit_destroy(ctx, &priv->limit);
}
static struct nft_object_type nft_limit_obj_type; static struct nft_object_type nft_limit_obj_type;
static const struct nft_object_ops nft_limit_obj_pkts_ops = { static const struct nft_object_ops nft_limit_obj_pkts_ops = {
.type = &nft_limit_obj_type, .type = &nft_limit_obj_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)), .size = NFT_EXPR_SIZE(sizeof(struct nft_limit_priv_pkts)),
.init = nft_limit_obj_pkts_init, .init = nft_limit_obj_pkts_init,
.destroy = nft_limit_obj_pkts_destroy,
.eval = nft_limit_obj_pkts_eval, .eval = nft_limit_obj_pkts_eval,
.dump = nft_limit_obj_pkts_dump, .dump = nft_limit_obj_pkts_dump,
}; };
...@@ -378,11 +387,20 @@ static int nft_limit_obj_bytes_dump(struct sk_buff *skb, ...@@ -378,11 +387,20 @@ static int nft_limit_obj_bytes_dump(struct sk_buff *skb,
return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES); return nft_limit_dump(skb, priv, NFT_LIMIT_PKT_BYTES);
} }
static void nft_limit_obj_bytes_destroy(const struct nft_ctx *ctx,
struct nft_object *obj)
{
struct nft_limit_priv *priv = nft_obj_data(obj);
nft_limit_destroy(ctx, priv);
}
static struct nft_object_type nft_limit_obj_type; static struct nft_object_type nft_limit_obj_type;
static const struct nft_object_ops nft_limit_obj_bytes_ops = { static const struct nft_object_ops nft_limit_obj_bytes_ops = {
.type = &nft_limit_obj_type, .type = &nft_limit_obj_type,
.size = sizeof(struct nft_limit_priv), .size = sizeof(struct nft_limit_priv),
.init = nft_limit_obj_bytes_init, .init = nft_limit_obj_bytes_init,
.destroy = nft_limit_obj_bytes_destroy,
.eval = nft_limit_obj_bytes_eval, .eval = nft_limit_obj_bytes_eval,
.dump = nft_limit_obj_bytes_dump, .dump = nft_limit_obj_bytes_dump,
}; };
......
...@@ -220,8 +220,10 @@ static void socket_mt_destroy(const struct xt_mtdtor_param *par) ...@@ -220,8 +220,10 @@ static void socket_mt_destroy(const struct xt_mtdtor_param *par)
{ {
if (par->family == NFPROTO_IPV4) if (par->family == NFPROTO_IPV4)
nf_defrag_ipv4_disable(par->net); nf_defrag_ipv4_disable(par->net);
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
else if (par->family == NFPROTO_IPV6) else if (par->family == NFPROTO_IPV6)
nf_defrag_ipv6_disable(par->net); nf_defrag_ipv6_disable(par->net);
#endif
} }
static struct xt_match socket_mt_reg[] __read_mostly = { static struct xt_match socket_mt_reg[] __read_mostly = {
......
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