Commit 4f6b15c3 authored by David S. Miller's avatar David S. Miller

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

Pablo Neira Ayuso says:

====================
Netfilter/IPVS fixes for net

The following patchset contains Netfilter/IPVS fixes for your net tree,
they are:

1) Fix handling of simultaneous open TCP connection in conntrack,
   from Jozsef Kadlecsik.

2) Insufficient sanitify check of xtables extension names, from
   Florian Westphal.

3) Skip unnecessary synchronize_rcu() call when transaction log
   is already empty, from Florian Westphal.

4) Incorrect destination mac validation in ebt_stp, from Stephen
   Hemminger.

5) xtables module reference counter leak in nft_compat, from
   Florian Westphal.

6) Incorrect connection reference counting logic in IPVS
   one-packet scheduler, from Julian Anastasov.

7) Wrong stats for 32-bits CPU in IPVS, also from Julian.

8) Calm down sparse error in netfilter core, also from Florian.

9) Use nla_strlcpy to fix compilation warning in nfnetlink_acct
   and nfnetlink_cthelper, again from Florian.

10) Missing module alias in icmp and icmp6 xtables extensions,
    from Florian Westphal.

11) Base chain statistics in nf_tables may be unset/null, from Florian.

12) Fix handling of large matchinfo size in nft_compat, this includes
    one preparation for before this fix. From Florian.

13) Fix bogus EBUSY error when deleting chains due to incorrect reference
    counting from the preparation phase of the two-phase commit protocol.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 91dfd02b f0dfd7a2
...@@ -170,6 +170,7 @@ struct nft_data_desc { ...@@ -170,6 +170,7 @@ struct nft_data_desc {
int nft_data_init(const struct nft_ctx *ctx, int nft_data_init(const struct nft_ctx *ctx,
struct nft_data *data, unsigned int size, struct nft_data *data, unsigned int size,
struct nft_data_desc *desc, const struct nlattr *nla); struct nft_data_desc *desc, const struct nlattr *nla);
void nft_data_hold(const struct nft_data *data, enum nft_data_types type);
void nft_data_release(const struct nft_data *data, enum nft_data_types type); void nft_data_release(const struct nft_data *data, enum nft_data_types type);
int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
enum nft_data_types type, unsigned int len); enum nft_data_types type, unsigned int len);
...@@ -736,6 +737,10 @@ struct nft_expr_ops { ...@@ -736,6 +737,10 @@ struct nft_expr_ops {
int (*init)(const struct nft_ctx *ctx, int (*init)(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nlattr * const tb[]); const struct nlattr * const tb[]);
void (*activate)(const struct nft_ctx *ctx,
const struct nft_expr *expr);
void (*deactivate)(const struct nft_ctx *ctx,
const struct nft_expr *expr);
void (*destroy)(const struct nft_ctx *ctx, void (*destroy)(const struct nft_ctx *ctx,
const struct nft_expr *expr); const struct nft_expr *expr);
int (*dump)(struct sk_buff *skb, int (*dump)(struct sk_buff *skb,
......
...@@ -46,6 +46,9 @@ enum tcp_conntrack { ...@@ -46,6 +46,9 @@ enum tcp_conntrack {
/* Marks possibility for expected RFC5961 challenge ACK */ /* Marks possibility for expected RFC5961 challenge ACK */
#define IP_CT_EXP_CHALLENGE_ACK 0x40 #define IP_CT_EXP_CHALLENGE_ACK 0x40
/* Simultaneous open initialized */
#define IP_CT_TCP_SIMULTANEOUS_OPEN 0x80
struct nf_ct_tcp_flags { struct nf_ct_tcp_flags {
__u8 flags; __u8 flags;
__u8 mask; __u8 mask;
......
...@@ -161,8 +161,8 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par) ...@@ -161,8 +161,8 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par)
/* Make sure the match only receives stp frames */ /* Make sure the match only receives stp frames */
if (!par->nft_compat && if (!par->nft_compat &&
(!ether_addr_equal(e->destmac, eth_stp_addr) || (!ether_addr_equal(e->destmac, eth_stp_addr) ||
!is_broadcast_ether_addr(e->destmsk) || !(e->bitmask & EBT_DESTMAC) ||
!(e->bitmask & EBT_DESTMAC))) !is_broadcast_ether_addr(e->destmsk)))
return -EINVAL; return -EINVAL;
return 0; return 0;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("IPv4 packet filter"); MODULE_DESCRIPTION("IPv4 packet filter");
MODULE_ALIAS("ipt_icmp");
void *ipt_alloc_initial_table(const struct xt_table *info) void *ipt_alloc_initial_table(const struct xt_table *info)
{ {
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("IPv6 packet filter"); MODULE_DESCRIPTION("IPv6 packet filter");
MODULE_ALIAS("ip6t_icmp6");
void *ip6t_alloc_initial_table(const struct xt_table *info) void *ip6t_alloc_initial_table(const struct xt_table *info)
{ {
......
...@@ -585,7 +585,8 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); ...@@ -585,7 +585,8 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
EXPORT_SYMBOL(nf_nat_decode_session_hook); EXPORT_SYMBOL(nf_nat_decode_session_hook);
#endif #endif
static void __net_init __netfilter_net_init(struct nf_hook_entries **e, int max) static void __net_init
__netfilter_net_init(struct nf_hook_entries __rcu **e, int max)
{ {
int h; int h;
......
...@@ -232,7 +232,10 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp) ...@@ -232,7 +232,10 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp) static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
{ {
unsigned int hash; unsigned int hash;
bool ret; bool ret = false;
if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
return refcount_dec_if_one(&cp->refcnt);
hash = ip_vs_conn_hashkey_conn(cp); hash = ip_vs_conn_hashkey_conn(cp);
...@@ -240,15 +243,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp) ...@@ -240,15 +243,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
spin_lock(&cp->lock); spin_lock(&cp->lock);
if (cp->flags & IP_VS_CONN_F_HASHED) { if (cp->flags & IP_VS_CONN_F_HASHED) {
ret = false;
/* Decrease refcnt and unlink conn only if we are last user */ /* Decrease refcnt and unlink conn only if we are last user */
if (refcount_dec_if_one(&cp->refcnt)) { if (refcount_dec_if_one(&cp->refcnt)) {
hlist_del_rcu(&cp->c_list); hlist_del_rcu(&cp->c_list);
cp->flags &= ~IP_VS_CONN_F_HASHED; cp->flags &= ~IP_VS_CONN_F_HASHED;
ret = true; ret = true;
} }
} else }
ret = refcount_read(&cp->refcnt) ? false : true;
spin_unlock(&cp->lock); spin_unlock(&cp->lock);
ct_write_unlock_bh(hash); ct_write_unlock_bh(hash);
...@@ -454,12 +455,6 @@ ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af, ...@@ -454,12 +455,6 @@ ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
} }
EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto); EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp)
{
__ip_vs_conn_put(cp);
ip_vs_conn_expire(&cp->timer);
}
/* /*
* Put back the conn and restart its timer with its timeout * Put back the conn and restart its timer with its timeout
*/ */
...@@ -478,7 +473,7 @@ void ip_vs_conn_put(struct ip_vs_conn *cp) ...@@ -478,7 +473,7 @@ void ip_vs_conn_put(struct ip_vs_conn *cp)
(refcount_read(&cp->refcnt) == 1) && (refcount_read(&cp->refcnt) == 1) &&
!timer_pending(&cp->timer)) !timer_pending(&cp->timer))
/* expire connection immediately */ /* expire connection immediately */
__ip_vs_conn_put_notimer(cp); ip_vs_conn_expire(&cp->timer);
else else
__ip_vs_conn_put_timer(cp); __ip_vs_conn_put_timer(cp);
} }
......
...@@ -119,6 +119,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb) ...@@ -119,6 +119,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
struct ip_vs_cpu_stats *s; struct ip_vs_cpu_stats *s;
struct ip_vs_service *svc; struct ip_vs_service *svc;
local_bh_disable();
s = this_cpu_ptr(dest->stats.cpustats); s = this_cpu_ptr(dest->stats.cpustats);
u64_stats_update_begin(&s->syncp); u64_stats_update_begin(&s->syncp);
s->cnt.inpkts++; s->cnt.inpkts++;
...@@ -137,6 +139,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb) ...@@ -137,6 +139,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
s->cnt.inpkts++; s->cnt.inpkts++;
s->cnt.inbytes += skb->len; s->cnt.inbytes += skb->len;
u64_stats_update_end(&s->syncp); u64_stats_update_end(&s->syncp);
local_bh_enable();
} }
} }
...@@ -151,6 +155,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) ...@@ -151,6 +155,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
struct ip_vs_cpu_stats *s; struct ip_vs_cpu_stats *s;
struct ip_vs_service *svc; struct ip_vs_service *svc;
local_bh_disable();
s = this_cpu_ptr(dest->stats.cpustats); s = this_cpu_ptr(dest->stats.cpustats);
u64_stats_update_begin(&s->syncp); u64_stats_update_begin(&s->syncp);
s->cnt.outpkts++; s->cnt.outpkts++;
...@@ -169,6 +175,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb) ...@@ -169,6 +175,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
s->cnt.outpkts++; s->cnt.outpkts++;
s->cnt.outbytes += skb->len; s->cnt.outbytes += skb->len;
u64_stats_update_end(&s->syncp); u64_stats_update_end(&s->syncp);
local_bh_enable();
} }
} }
...@@ -179,6 +187,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) ...@@ -179,6 +187,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
struct netns_ipvs *ipvs = svc->ipvs; struct netns_ipvs *ipvs = svc->ipvs;
struct ip_vs_cpu_stats *s; struct ip_vs_cpu_stats *s;
local_bh_disable();
s = this_cpu_ptr(cp->dest->stats.cpustats); s = this_cpu_ptr(cp->dest->stats.cpustats);
u64_stats_update_begin(&s->syncp); u64_stats_update_begin(&s->syncp);
s->cnt.conns++; s->cnt.conns++;
...@@ -193,6 +203,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc) ...@@ -193,6 +203,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
u64_stats_update_begin(&s->syncp); u64_stats_update_begin(&s->syncp);
s->cnt.conns++; s->cnt.conns++;
u64_stats_update_end(&s->syncp); u64_stats_update_end(&s->syncp);
local_bh_enable();
} }
......
...@@ -981,6 +981,17 @@ static int tcp_packet(struct nf_conn *ct, ...@@ -981,6 +981,17 @@ static int tcp_packet(struct nf_conn *ct,
return NF_ACCEPT; /* Don't change state */ return NF_ACCEPT; /* Don't change state */
} }
break; break;
case TCP_CONNTRACK_SYN_SENT2:
/* tcp_conntracks table is not smart enough to handle
* simultaneous open.
*/
ct->proto.tcp.last_flags |= IP_CT_TCP_SIMULTANEOUS_OPEN;
break;
case TCP_CONNTRACK_SYN_RECV:
if (dir == IP_CT_DIR_REPLY && index == TCP_ACK_SET &&
ct->proto.tcp.last_flags & IP_CT_TCP_SIMULTANEOUS_OPEN)
new_state = TCP_CONNTRACK_ESTABLISHED;
break;
case TCP_CONNTRACK_CLOSE: case TCP_CONNTRACK_CLOSE:
if (index == TCP_RST_SET if (index == TCP_RST_SET
&& (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
......
...@@ -214,6 +214,34 @@ static int nft_delchain(struct nft_ctx *ctx) ...@@ -214,6 +214,34 @@ static int nft_delchain(struct nft_ctx *ctx)
return err; return err;
} }
static void nft_rule_expr_activate(const struct nft_ctx *ctx,
struct nft_rule *rule)
{
struct nft_expr *expr;
expr = nft_expr_first(rule);
while (expr != nft_expr_last(rule) && expr->ops) {
if (expr->ops->activate)
expr->ops->activate(ctx, expr);
expr = nft_expr_next(expr);
}
}
static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
struct nft_rule *rule)
{
struct nft_expr *expr;
expr = nft_expr_first(rule);
while (expr != nft_expr_last(rule) && expr->ops) {
if (expr->ops->deactivate)
expr->ops->deactivate(ctx, expr);
expr = nft_expr_next(expr);
}
}
static int static int
nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
{ {
...@@ -259,6 +287,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule) ...@@ -259,6 +287,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
nft_trans_destroy(trans); nft_trans_destroy(trans);
return err; return err;
} }
nft_rule_expr_deactivate(ctx, rule);
return 0; return 0;
} }
...@@ -2238,6 +2267,13 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx, ...@@ -2238,6 +2267,13 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
kfree(rule); kfree(rule);
} }
static void nf_tables_rule_release(const struct nft_ctx *ctx,
struct nft_rule *rule)
{
nft_rule_expr_deactivate(ctx, rule);
nf_tables_rule_destroy(ctx, rule);
}
#define NFT_RULE_MAXEXPRS 128 #define NFT_RULE_MAXEXPRS 128
static struct nft_expr_info *info; static struct nft_expr_info *info;
...@@ -2402,7 +2438,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk, ...@@ -2402,7 +2438,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
return 0; return 0;
err2: err2:
nf_tables_rule_destroy(&ctx, rule); nf_tables_rule_release(&ctx, rule);
err1: err1:
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (info[i].ops != NULL) if (info[i].ops != NULL)
...@@ -4044,8 +4080,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, ...@@ -4044,8 +4080,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^ if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^
nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) || nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) ||
nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^ nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^
nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) {
return -EBUSY; err = -EBUSY;
goto err5;
}
if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
memcmp(nft_set_ext_data(ext), memcmp(nft_set_ext_data(ext),
...@@ -4130,7 +4168,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk, ...@@ -4130,7 +4168,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
* NFT_GOTO verdicts. This function must be called on active data objects * NFT_GOTO verdicts. This function must be called on active data objects
* from the second phase of the commit protocol. * from the second phase of the commit protocol.
*/ */
static void nft_data_hold(const struct nft_data *data, enum nft_data_types type) void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
{ {
if (type == NFT_DATA_VERDICT) { if (type == NFT_DATA_VERDICT) {
switch (data->verdict.code) { switch (data->verdict.code) {
...@@ -5761,7 +5799,7 @@ static void nft_chain_commit_update(struct nft_trans *trans) ...@@ -5761,7 +5799,7 @@ static void nft_chain_commit_update(struct nft_trans *trans)
} }
} }
static void nf_tables_commit_release(struct nft_trans *trans) static void nft_commit_release(struct nft_trans *trans)
{ {
switch (trans->msg_type) { switch (trans->msg_type) {
case NFT_MSG_DELTABLE: case NFT_MSG_DELTABLE:
...@@ -5790,6 +5828,21 @@ static void nf_tables_commit_release(struct nft_trans *trans) ...@@ -5790,6 +5828,21 @@ static void nf_tables_commit_release(struct nft_trans *trans)
kfree(trans); kfree(trans);
} }
static void nf_tables_commit_release(struct net *net)
{
struct nft_trans *trans, *next;
if (list_empty(&net->nft.commit_list))
return;
synchronize_rcu();
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
list_del(&trans->list);
nft_commit_release(trans);
}
}
static int nf_tables_commit(struct net *net, struct sk_buff *skb) static int nf_tables_commit(struct net *net, struct sk_buff *skb)
{ {
struct nft_trans *trans, *next; struct nft_trans *trans, *next;
...@@ -5920,13 +5973,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) ...@@ -5920,13 +5973,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
} }
} }
synchronize_rcu(); nf_tables_commit_release(net);
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
list_del(&trans->list);
nf_tables_commit_release(trans);
}
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
return 0; return 0;
...@@ -6006,10 +6053,12 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb) ...@@ -6006,10 +6053,12 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
case NFT_MSG_NEWRULE: case NFT_MSG_NEWRULE:
trans->ctx.chain->use--; trans->ctx.chain->use--;
list_del_rcu(&nft_trans_rule(trans)->list); list_del_rcu(&nft_trans_rule(trans)->list);
nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
break; break;
case NFT_MSG_DELRULE: case NFT_MSG_DELRULE:
trans->ctx.chain->use++; trans->ctx.chain->use++;
nft_clear(trans->ctx.net, nft_trans_rule(trans)); nft_clear(trans->ctx.net, nft_trans_rule(trans));
nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
nft_trans_destroy(trans); nft_trans_destroy(trans);
break; break;
case NFT_MSG_NEWSET: case NFT_MSG_NEWSET:
...@@ -6585,7 +6634,7 @@ int __nft_release_basechain(struct nft_ctx *ctx) ...@@ -6585,7 +6634,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
list_del(&rule->list); list_del(&rule->list);
ctx->chain->use--; ctx->chain->use--;
nf_tables_rule_destroy(ctx, rule); nf_tables_rule_release(ctx, rule);
} }
list_del(&ctx->chain->list); list_del(&ctx->chain->list);
ctx->table->use--; ctx->table->use--;
...@@ -6623,7 +6672,7 @@ static void __nft_release_tables(struct net *net) ...@@ -6623,7 +6672,7 @@ static void __nft_release_tables(struct net *net)
list_for_each_entry_safe(rule, nr, &chain->rules, list) { list_for_each_entry_safe(rule, nr, &chain->rules, list) {
list_del(&rule->list); list_del(&rule->list);
chain->use--; chain->use--;
nf_tables_rule_destroy(&ctx, rule); nf_tables_rule_release(&ctx, rule);
} }
} }
list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
......
...@@ -119,15 +119,22 @@ DEFINE_STATIC_KEY_FALSE(nft_counters_enabled); ...@@ -119,15 +119,22 @@ DEFINE_STATIC_KEY_FALSE(nft_counters_enabled);
static noinline void nft_update_chain_stats(const struct nft_chain *chain, static noinline void nft_update_chain_stats(const struct nft_chain *chain,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
struct nft_base_chain *base_chain;
struct nft_stats *stats; struct nft_stats *stats;
local_bh_disable(); base_chain = nft_base_chain(chain);
stats = this_cpu_ptr(rcu_dereference(nft_base_chain(chain)->stats)); if (!base_chain->stats)
u64_stats_update_begin(&stats->syncp); return;
stats->pkts++;
stats->bytes += pkt->skb->len; stats = this_cpu_ptr(rcu_dereference(base_chain->stats));
u64_stats_update_end(&stats->syncp); if (stats) {
local_bh_enable(); local_bh_disable();
u64_stats_update_begin(&stats->syncp);
stats->pkts++;
stats->bytes += pkt->skb->len;
u64_stats_update_end(&stats->syncp);
local_bh_enable();
}
} }
struct nft_jumpstack { struct nft_jumpstack {
......
...@@ -115,7 +115,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl, ...@@ -115,7 +115,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
nfacct->flags = flags; nfacct->flags = flags;
} }
strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX); nla_strlcpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);
if (tb[NFACCT_BYTES]) { if (tb[NFACCT_BYTES]) {
atomic64_set(&nfacct->bytes, atomic64_set(&nfacct->bytes,
......
...@@ -149,8 +149,8 @@ nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy, ...@@ -149,8 +149,8 @@ nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy,
!tb[NFCTH_POLICY_EXPECT_TIMEOUT]) !tb[NFCTH_POLICY_EXPECT_TIMEOUT])
return -EINVAL; return -EINVAL;
strncpy(expect_policy->name, nla_strlcpy(expect_policy->name,
nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN); nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN);
expect_policy->max_expected = expect_policy->max_expected =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX])); ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT) if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
...@@ -234,7 +234,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[], ...@@ -234,7 +234,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
if (ret < 0) if (ret < 0)
goto err1; goto err1;
strncpy(helper->name, nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN); nla_strlcpy(helper->name,
nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN);
size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
if (size > FIELD_SIZEOF(struct nf_conn_help, data)) { if (size > FIELD_SIZEOF(struct nf_conn_help, data)) {
ret = -ENOMEM; ret = -ENOMEM;
......
This diff is collapsed.
...@@ -69,8 +69,16 @@ static int nft_immediate_init(const struct nft_ctx *ctx, ...@@ -69,8 +69,16 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
return err; return err;
} }
static void nft_immediate_destroy(const struct nft_ctx *ctx, static void nft_immediate_activate(const struct nft_ctx *ctx,
const struct nft_expr *expr) const struct nft_expr *expr)
{
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
}
static void nft_immediate_deactivate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{ {
const struct nft_immediate_expr *priv = nft_expr_priv(expr); const struct nft_immediate_expr *priv = nft_expr_priv(expr);
...@@ -108,7 +116,8 @@ static const struct nft_expr_ops nft_imm_ops = { ...@@ -108,7 +116,8 @@ static const struct nft_expr_ops nft_imm_ops = {
.size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
.eval = nft_immediate_eval, .eval = nft_immediate_eval,
.init = nft_immediate_init, .init = nft_immediate_init,
.destroy = nft_immediate_destroy, .activate = nft_immediate_activate,
.deactivate = nft_immediate_deactivate,
.dump = nft_immediate_dump, .dump = nft_immediate_dump,
.validate = nft_immediate_validate, .validate = nft_immediate_validate,
}; };
......
...@@ -183,6 +183,9 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision) ...@@ -183,6 +183,9 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
struct xt_match *m; struct xt_match *m;
int err = -ENOENT; int err = -ENOENT;
if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
return ERR_PTR(-EINVAL);
mutex_lock(&xt[af].mutex); mutex_lock(&xt[af].mutex);
list_for_each_entry(m, &xt[af].match, list) { list_for_each_entry(m, &xt[af].match, list) {
if (strcmp(m->name, name) == 0) { if (strcmp(m->name, name) == 0) {
...@@ -229,6 +232,9 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision) ...@@ -229,6 +232,9 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
struct xt_target *t; struct xt_target *t;
int err = -ENOENT; int err = -ENOENT;
if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
return ERR_PTR(-EINVAL);
mutex_lock(&xt[af].mutex); mutex_lock(&xt[af].mutex);
list_for_each_entry(t, &xt[af].target, list) { list_for_each_entry(t, &xt[af].target, list) {
if (strcmp(t->name, name) == 0) { if (strcmp(t->name, name) == 0) {
......
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