mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf after rc5
Cross-merge BPF and other fixes after downstream PR. No conflicts. Adjacent: Auto-merging MAINTAINERS Auto-merging Makefile Auto-merging kernel/bpf/verifier.c Auto-merging kernel/sched/ext.c Auto-merging mm/memcontrol.c Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
@@ -408,6 +408,9 @@ err_put:
|
||||
return -1;
|
||||
|
||||
err_unreach:
|
||||
if (!skb->dev)
|
||||
skb->dev = skb_dst(skb)->dev;
|
||||
|
||||
dst_link_failure(skb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net,
|
||||
struct nf_conn *found_ct;
|
||||
unsigned int collect = 0;
|
||||
bool refcounted = false;
|
||||
int err = 0;
|
||||
|
||||
if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
|
||||
return -ENOENT;
|
||||
|
||||
if (ct && nf_ct_is_confirmed(ct)) {
|
||||
if (refcounted)
|
||||
nf_ct_put(ct);
|
||||
return -EEXIST;
|
||||
err = -EEXIST;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if ((u32)jiffies == list->last_gc)
|
||||
@@ -229,14 +229,19 @@ static int __nf_conncount_add(struct net *net,
|
||||
|
||||
nf_ct_put(found_ct);
|
||||
}
|
||||
list->last_gc = (u32)jiffies;
|
||||
|
||||
add_new_node:
|
||||
if (WARN_ON_ONCE(list->count > INT_MAX))
|
||||
return -EOVERFLOW;
|
||||
if (WARN_ON_ONCE(list->count > INT_MAX)) {
|
||||
err = -EOVERFLOW;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
|
||||
if (conn == NULL)
|
||||
return -ENOMEM;
|
||||
if (conn == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
conn->tuple = tuple;
|
||||
conn->zone = *zone;
|
||||
@@ -244,12 +249,11 @@ add_new_node:
|
||||
conn->jiffies32 = (u32)jiffies;
|
||||
list_add_tail(&conn->node, &list->head);
|
||||
list->count++;
|
||||
list->last_gc = (u32)jiffies;
|
||||
|
||||
out_put:
|
||||
if (refcounted)
|
||||
nf_ct_put(ct);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
int nf_conncount_add_skb(struct net *net,
|
||||
@@ -456,11 +460,10 @@ restart:
|
||||
|
||||
rb_link_node_rcu(&rbconn->node, parent, rbnode);
|
||||
rb_insert_color(&rbconn->node, root);
|
||||
|
||||
if (refcounted)
|
||||
nf_ct_put(ct);
|
||||
}
|
||||
out_unlock:
|
||||
if (refcounted)
|
||||
nf_ct_put(ct);
|
||||
spin_unlock_bh(&nf_conncount_locks[hash]);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -2487,6 +2487,7 @@ void nf_conntrack_cleanup_net(struct net *net)
|
||||
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
|
||||
{
|
||||
struct nf_ct_iter_data iter_data = {};
|
||||
unsigned long start = jiffies;
|
||||
struct net *net;
|
||||
int busy;
|
||||
|
||||
@@ -2507,6 +2508,8 @@ i_see_dead_people:
|
||||
busy = 1;
|
||||
}
|
||||
if (busy) {
|
||||
DEBUG_NET_WARN_ONCE(time_after(jiffies, start + 60 * HZ),
|
||||
"conntrack cleanup blocked for 60s");
|
||||
schedule();
|
||||
goto i_see_dead_people;
|
||||
}
|
||||
|
||||
@@ -250,6 +250,9 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
|
||||
if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0)
|
||||
nft_dev_path_info(&stack, &info, ha, &ft->data);
|
||||
|
||||
if (info.outdev)
|
||||
route->tuple[dir].out.ifindex = info.outdev->ifindex;
|
||||
|
||||
if (!info.indev || !nft_flowtable_find_dev(info.indev, ft))
|
||||
return;
|
||||
|
||||
@@ -269,7 +272,6 @@ static void nft_dev_forward_path(const struct nft_pktinfo *pkt,
|
||||
|
||||
route->tuple[!dir].in.num_encaps = info.num_encaps;
|
||||
route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
|
||||
route->tuple[dir].out.ifindex = info.outdev->ifindex;
|
||||
|
||||
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
|
||||
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
|
||||
|
||||
@@ -89,7 +89,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
|
||||
if (pf == NFPROTO_UNSPEC) {
|
||||
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
|
||||
if (rcu_access_pointer(loggers[i][logger->type])) {
|
||||
ret = -EEXIST;
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
|
||||
rcu_assign_pointer(loggers[i][logger->type], logger);
|
||||
} else {
|
||||
if (rcu_access_pointer(loggers[pf][logger->type])) {
|
||||
ret = -EEXIST;
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
rcu_assign_pointer(loggers[pf][logger->type], logger);
|
||||
|
||||
@@ -294,25 +294,13 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
|
||||
|
||||
ct = nf_ct_tuplehash_to_ctrack(thash);
|
||||
|
||||
/* NB: IP_CT_DIR_ORIGINAL should be impossible because
|
||||
* nf_nat_used_tuple() handles origin collisions.
|
||||
*
|
||||
* Handle remote chance other CPU confirmed its ct right after.
|
||||
*/
|
||||
if (thash->tuple.dst.dir != IP_CT_DIR_REPLY)
|
||||
goto out;
|
||||
|
||||
/* clashing connection subject to NAT? Retry with new tuple. */
|
||||
if (READ_ONCE(ct->status) & uses_nat)
|
||||
goto out;
|
||||
|
||||
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
|
||||
&ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple) &&
|
||||
nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
|
||||
&ignored_ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) {
|
||||
&ignored_ct->tuplehash[IP_CT_DIR_REPLY].tuple))
|
||||
taken = false;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
nf_ct_put(ct);
|
||||
return taken;
|
||||
|
||||
@@ -123,6 +123,29 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s
|
||||
|
||||
table->validate_state = new_validate_state;
|
||||
}
|
||||
|
||||
static bool nft_chain_vstate_valid(const struct nft_ctx *ctx,
|
||||
const struct nft_chain *chain)
|
||||
{
|
||||
const struct nft_base_chain *base_chain;
|
||||
enum nft_chain_types type;
|
||||
u8 hooknum;
|
||||
|
||||
if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain)))
|
||||
return false;
|
||||
|
||||
base_chain = nft_base_chain(ctx->chain);
|
||||
hooknum = base_chain->ops.hooknum;
|
||||
type = base_chain->type->type;
|
||||
|
||||
/* chain is already validated for this call depth */
|
||||
if (chain->vstate.depth >= ctx->level &&
|
||||
chain->vstate.hook_mask[type] & BIT(hooknum))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void nf_tables_trans_destroy_work(struct work_struct *w);
|
||||
|
||||
static void nft_trans_gc_work(struct work_struct *work);
|
||||
@@ -4079,6 +4102,29 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
|
||||
nf_tables_rule_destroy(ctx, rule);
|
||||
}
|
||||
|
||||
static void nft_chain_vstate_update(const struct nft_ctx *ctx, struct nft_chain *chain)
|
||||
{
|
||||
const struct nft_base_chain *base_chain;
|
||||
enum nft_chain_types type;
|
||||
u8 hooknum;
|
||||
|
||||
/* ctx->chain must hold the calling base chain. */
|
||||
if (WARN_ON_ONCE(!nft_is_base_chain(ctx->chain))) {
|
||||
memset(&chain->vstate, 0, sizeof(chain->vstate));
|
||||
return;
|
||||
}
|
||||
|
||||
base_chain = nft_base_chain(ctx->chain);
|
||||
hooknum = base_chain->ops.hooknum;
|
||||
type = base_chain->type->type;
|
||||
|
||||
BUILD_BUG_ON(BIT(NF_INET_NUMHOOKS) > U8_MAX);
|
||||
|
||||
chain->vstate.hook_mask[type] |= BIT(hooknum);
|
||||
if (chain->vstate.depth < ctx->level)
|
||||
chain->vstate.depth = ctx->level;
|
||||
}
|
||||
|
||||
/** nft_chain_validate - loop detection and hook validation
|
||||
*
|
||||
* @ctx: context containing call depth and base chain
|
||||
@@ -4088,15 +4134,25 @@ static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *r
|
||||
* and set lookups until either the jump limit is hit or all reachable
|
||||
* chains have been validated.
|
||||
*/
|
||||
int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
|
||||
int nft_chain_validate(const struct nft_ctx *ctx, struct nft_chain *chain)
|
||||
{
|
||||
struct nft_expr *expr, *last;
|
||||
struct nft_rule *rule;
|
||||
int err;
|
||||
|
||||
BUILD_BUG_ON(NFT_JUMP_STACK_SIZE > 255);
|
||||
if (ctx->level == NFT_JUMP_STACK_SIZE)
|
||||
return -EMLINK;
|
||||
|
||||
if (ctx->level > 0) {
|
||||
/* jumps to base chains are not allowed. */
|
||||
if (nft_is_base_chain(chain))
|
||||
return -ELOOP;
|
||||
|
||||
if (nft_chain_vstate_valid(ctx, chain))
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry(rule, &chain->rules, list) {
|
||||
if (fatal_signal_pending(current))
|
||||
return -EINTR;
|
||||
@@ -4115,8 +4171,11 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
nft_chain_vstate_update(ctx, chain);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_chain_validate);
|
||||
@@ -4128,7 +4187,7 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
|
||||
.net = net,
|
||||
.family = table->family,
|
||||
};
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(chain, &table->chains, list) {
|
||||
if (!nft_is_base_chain(chain))
|
||||
@@ -4137,12 +4196,14 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
|
||||
ctx.chain = chain;
|
||||
err = nft_chain_validate(&ctx, chain);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cond_resched();
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
list_for_each_entry(chain, &table->chains, list)
|
||||
memset(&chain->vstate, 0, sizeof(chain->vstate));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
@@ -4378,7 +4439,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
|
||||
if (!nft_use_inc(&chain->use)) {
|
||||
err = -EMFILE;
|
||||
goto err_release_rule;
|
||||
goto err_destroy_flow;
|
||||
}
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
|
||||
@@ -4428,6 +4489,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
|
||||
|
||||
err_destroy_flow_rule:
|
||||
nft_use_dec_restore(&chain->use);
|
||||
err_destroy_flow:
|
||||
if (flow)
|
||||
nft_flow_rule_destroy(flow);
|
||||
err_release_rule:
|
||||
@@ -11676,21 +11738,10 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
|
||||
enum nft_data_types type,
|
||||
unsigned int len)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (reg) {
|
||||
case NFT_REG_VERDICT:
|
||||
if (type != NFT_DATA_VERDICT)
|
||||
return -EINVAL;
|
||||
|
||||
if (data != NULL &&
|
||||
(data->verdict.code == NFT_GOTO ||
|
||||
data->verdict.code == NFT_JUMP)) {
|
||||
err = nft_chain_validate(ctx, data->verdict.chain);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if (type != NFT_DATA_VALUE)
|
||||
|
||||
@@ -1317,8 +1317,8 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
|
||||
else
|
||||
dup_end = dup_key;
|
||||
|
||||
if (!memcmp(start, dup_key->data, sizeof(*dup_key->data)) &&
|
||||
!memcmp(end, dup_end->data, sizeof(*dup_end->data))) {
|
||||
if (!memcmp(start, dup_key->data, set->klen) &&
|
||||
!memcmp(end, dup_end->data, set->klen)) {
|
||||
*elem_priv = &dup->priv;
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ static void nft_synproxy_eval_v4(const struct nft_synproxy *priv,
|
||||
struct tcphdr *_tcph,
|
||||
struct synproxy_options *opts)
|
||||
{
|
||||
struct nf_synproxy_info info = priv->info;
|
||||
struct nf_synproxy_info info = READ_ONCE(priv->info);
|
||||
struct net *net = nft_net(pkt);
|
||||
struct synproxy_net *snet = synproxy_pernet(net);
|
||||
struct sk_buff *skb = pkt->skb;
|
||||
@@ -79,7 +79,7 @@ static void nft_synproxy_eval_v6(const struct nft_synproxy *priv,
|
||||
struct tcphdr *_tcph,
|
||||
struct synproxy_options *opts)
|
||||
{
|
||||
struct nf_synproxy_info info = priv->info;
|
||||
struct nf_synproxy_info info = READ_ONCE(priv->info);
|
||||
struct net *net = nft_net(pkt);
|
||||
struct synproxy_net *snet = synproxy_pernet(net);
|
||||
struct sk_buff *skb = pkt->skb;
|
||||
@@ -340,7 +340,7 @@ static void nft_synproxy_obj_update(struct nft_object *obj,
|
||||
struct nft_synproxy *newpriv = nft_obj_data(newobj);
|
||||
struct nft_synproxy *priv = nft_obj_data(obj);
|
||||
|
||||
priv->info = newpriv->info;
|
||||
WRITE_ONCE(priv->info, newpriv->info);
|
||||
}
|
||||
|
||||
static struct nft_object_type nft_synproxy_obj_type;
|
||||
|
||||
@@ -1764,7 +1764,7 @@ EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
|
||||
int xt_register_template(const struct xt_table *table,
|
||||
int (*table_init)(struct net *net))
|
||||
{
|
||||
int ret = -EEXIST, af = table->af;
|
||||
int ret = -EBUSY, af = table->af;
|
||||
struct xt_template *t;
|
||||
|
||||
mutex_lock(&xt[af].mutex);
|
||||
|
||||
Reference in New Issue
Block a user