mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'nf-26-03-13' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Florian Westphal says:
====================
netfilter: updates for net
This is a much earlier pull request than usual, due to the large
backlog. We are aware of several unfixed issues, in particular
in ctnetlink, patches are being worked on.
The following patchset contains Netfilter fixes for *net*:
1) fix a use-after-free in ctnetlink, from Hyunwoo Kim, broken
since v3.10.
2) add missing netlink range checks in ctnetlink, broken since v2.6
days.
3) fix content length truncation in sip conntrack helper,
from Lukas Johannes Möller. Broken since 2.6.34.
4) Revert a recent patch to add stronger checks for overlapping ranges
in nf_tables rbtree set type.
Patch is correct, but several nftables version have a bug (now fixed)
that trigger the checks incorrectly.
5) Reset mac header before the vlan push to avoid warning splat (and
make things functional). From Eric Woudstra.
6) Add missing bounds check in H323 conntrack helper, broken since this
helper was added 20 years ago, from Jenny Guanni Qu.
7) Fix a memory leak in the dynamic set infrastructure, from Pablo Neira
Ayuso. Broken since v5.11.
8+9) a few spots failed to purge skbs queued to userspace via nfqueue,
this causes RCU escape / use-after-free. Also from Pablo. broken
since v3.4 added the CT target to xtables.
10) Fix undefined behaviour in xt_time, use u32 for a shift-by-31
operation, not s32, from Jenny Guanni Qu.
11) H323 conntrack helper lacks a check for length variable becoming
negative after decrement, causes major out-of-bounds read due to
cast to unsigned size later, also from Jenny.
Both issues exist since 2.6 days.
* tag 'nf-26-03-13' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
netfilter: nf_conntrack_h323: check for zero length in DecodeQ931()
netfilter: xt_time: use unsigned int for monthday bit shift
netfilter: xt_CT: drop pending enqueued packets on template removal
netfilter: nft_ct: drop pending enqueued packets on removal
nf_tables: nft_dynset: fix possible stateful expression memleak in error path
netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case
netfilter: nf_flow_table_ip: reset mac header before vlan push
netfilter: revert nft_set_rbtree: validate open interval overlap
netfilter: nf_conntrack_sip: fix Content-Length u32 truncation in sip_help_tcp()
netfilter: conntrack: add missing netlink policy validations
netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct()
====================
Link: https://patch.msgid.link/20260313150614.21177-1-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -277,8 +277,6 @@ struct nft_userdata {
|
||||
unsigned char data[];
|
||||
};
|
||||
|
||||
#define NFT_SET_ELEM_INTERNAL_LAST 0x1
|
||||
|
||||
/* placeholder structure for opaque set element backend representation. */
|
||||
struct nft_elem_priv { };
|
||||
|
||||
@@ -288,7 +286,6 @@ struct nft_elem_priv { };
|
||||
* @key: element key
|
||||
* @key_end: closing element key
|
||||
* @data: element data
|
||||
* @flags: flags
|
||||
* @priv: element private data and extensions
|
||||
*/
|
||||
struct nft_set_elem {
|
||||
@@ -304,7 +301,6 @@ struct nft_set_elem {
|
||||
u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
|
||||
struct nft_data val;
|
||||
} data;
|
||||
u32 flags;
|
||||
struct nft_elem_priv *priv;
|
||||
};
|
||||
|
||||
@@ -878,6 +874,8 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
|
||||
u64 timeout, u64 expiration, gfp_t gfp);
|
||||
int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
|
||||
struct nft_expr *expr_array[]);
|
||||
void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_set_elem_expr *elem_expr);
|
||||
void nft_set_elem_destroy(const struct nft_set *set,
|
||||
const struct nft_elem_priv *elem_priv,
|
||||
bool destroy_expr);
|
||||
|
||||
@@ -331,6 +331,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
|
||||
if (nf_h323_error_boundary(bs, 0, 2))
|
||||
return H323_ERROR_BOUND;
|
||||
len = get_bits(bs, 2) + 1;
|
||||
if (nf_h323_error_boundary(bs, len, 0))
|
||||
return H323_ERROR_BOUND;
|
||||
BYTE_ALIGN(bs);
|
||||
if (base && (f->attr & DECODE)) { /* timeToLive */
|
||||
unsigned int v = get_uint(bs, len) + f->lb;
|
||||
@@ -922,6 +924,8 @@ int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931)
|
||||
break;
|
||||
p++;
|
||||
len--;
|
||||
if (len <= 0)
|
||||
break;
|
||||
return DecodeH323_UserInformation(buf, p, len,
|
||||
&q931->UUIE);
|
||||
}
|
||||
|
||||
@@ -3212,7 +3212,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
|
||||
struct nf_conn *ct = cb->data;
|
||||
struct nf_conn_help *help = nfct_help(ct);
|
||||
struct nf_conn_help *help;
|
||||
u_int8_t l3proto = nfmsg->nfgen_family;
|
||||
unsigned long last_id = cb->args[1];
|
||||
struct nf_conntrack_expect *exp;
|
||||
@@ -3220,6 +3220,10 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
if (cb->args[0])
|
||||
return 0;
|
||||
|
||||
help = nfct_help(ct);
|
||||
if (!help)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
restart:
|
||||
@@ -3249,6 +3253,24 @@ out:
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static int ctnetlink_dump_exp_ct_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nf_conn *ct = cb->data;
|
||||
|
||||
if (!refcount_inc_not_zero(&ct->ct_general.use))
|
||||
return -ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctnetlink_dump_exp_ct_done(struct netlink_callback *cb)
|
||||
{
|
||||
struct nf_conn *ct = cb->data;
|
||||
|
||||
if (ct)
|
||||
nf_ct_put(ct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
|
||||
struct sk_buff *skb,
|
||||
const struct nlmsghdr *nlh,
|
||||
@@ -3264,6 +3286,8 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
|
||||
struct nf_conntrack_zone zone;
|
||||
struct netlink_dump_control c = {
|
||||
.dump = ctnetlink_exp_ct_dump_table,
|
||||
.start = ctnetlink_dump_exp_ct_start,
|
||||
.done = ctnetlink_dump_exp_ct_done,
|
||||
};
|
||||
|
||||
err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
|
||||
@@ -3465,7 +3489,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x,
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_NAT)
|
||||
static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
|
||||
[CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 },
|
||||
[CTA_EXPECT_NAT_DIR] = NLA_POLICY_MAX(NLA_BE32, IP_CT_DIR_REPLY),
|
||||
[CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED },
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -582,7 +582,8 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = {
|
||||
[CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 },
|
||||
[CTA_PROTOINFO_SCTP_STATE] = NLA_POLICY_MAX(NLA_U8,
|
||||
SCTP_CONNTRACK_HEARTBEAT_SENT),
|
||||
[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 },
|
||||
[CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
@@ -1534,11 +1534,12 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
|
||||
{
|
||||
struct tcphdr *th, _tcph;
|
||||
unsigned int dataoff, datalen;
|
||||
unsigned int matchoff, matchlen, clen;
|
||||
unsigned int matchoff, matchlen;
|
||||
unsigned int msglen, origlen;
|
||||
const char *dptr, *end;
|
||||
s16 diff, tdiff = 0;
|
||||
int ret = NF_ACCEPT;
|
||||
unsigned long clen;
|
||||
bool term;
|
||||
|
||||
if (ctinfo != IP_CT_ESTABLISHED &&
|
||||
@@ -1573,6 +1574,9 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
|
||||
if (dptr + matchoff == end)
|
||||
break;
|
||||
|
||||
if (clen > datalen)
|
||||
break;
|
||||
|
||||
term = false;
|
||||
for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) {
|
||||
if (end[0] == '\r' && end[1] == '\n' &&
|
||||
|
||||
@@ -738,6 +738,7 @@ static int nf_flow_encap_push(struct sk_buff *skb,
|
||||
switch (tuple->encap[i].proto) {
|
||||
case htons(ETH_P_8021Q):
|
||||
case htons(ETH_P_8021AD):
|
||||
skb_reset_mac_header(skb);
|
||||
if (skb_vlan_push(skb, tuple->encap[i].proto,
|
||||
tuple->encap[i].id) < 0)
|
||||
return -1;
|
||||
|
||||
@@ -6744,8 +6744,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_set_elem_expr *elem_expr)
|
||||
void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_set_elem_expr *elem_expr)
|
||||
{
|
||||
struct nft_expr *expr;
|
||||
u32 size;
|
||||
@@ -7156,8 +7156,7 @@ static u32 nft_set_maxsize(const struct nft_set *set)
|
||||
}
|
||||
|
||||
static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
const struct nlattr *attr, u32 nlmsg_flags,
|
||||
bool last)
|
||||
const struct nlattr *attr, u32 nlmsg_flags)
|
||||
{
|
||||
struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {};
|
||||
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
|
||||
@@ -7444,11 +7443,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
if (flags)
|
||||
*nft_set_ext_flags(ext) = flags;
|
||||
|
||||
if (last)
|
||||
elem.flags = NFT_SET_ELEM_INTERNAL_LAST;
|
||||
else
|
||||
elem.flags = 0;
|
||||
|
||||
if (obj)
|
||||
*nft_set_ext_obj(ext) = obj;
|
||||
|
||||
@@ -7613,8 +7607,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
|
||||
nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
|
||||
|
||||
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
|
||||
err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags,
|
||||
nla_is_last(attr, rem));
|
||||
err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags);
|
||||
if (err < 0) {
|
||||
NL_SET_BAD_ATTR(extack, attr);
|
||||
return err;
|
||||
@@ -7738,7 +7731,7 @@ static void nft_trans_elems_destroy_abort(const struct nft_ctx *ctx,
|
||||
}
|
||||
|
||||
static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
const struct nlattr *attr, bool last)
|
||||
const struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
|
||||
struct nft_set_ext_tmpl tmpl;
|
||||
@@ -7806,11 +7799,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
if (flags)
|
||||
*nft_set_ext_flags(ext) = flags;
|
||||
|
||||
if (last)
|
||||
elem.flags = NFT_SET_ELEM_INTERNAL_LAST;
|
||||
else
|
||||
elem.flags = 0;
|
||||
|
||||
trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
|
||||
if (trans == NULL)
|
||||
goto fail_trans;
|
||||
@@ -7961,8 +7949,7 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
|
||||
return nft_set_flush(&ctx, set, genmask);
|
||||
|
||||
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
|
||||
err = nft_del_setelem(&ctx, set, attr,
|
||||
nla_is_last(attr, rem));
|
||||
err = nft_del_setelem(&ctx, set, attr);
|
||||
if (err == -ENOENT &&
|
||||
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM)
|
||||
continue;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <net/netfilter/nf_conntrack_l4proto.h>
|
||||
#include <net/netfilter/nf_conntrack_expect.h>
|
||||
#include <net/netfilter/nf_conntrack_seqadj.h>
|
||||
#include "nf_internals.h"
|
||||
|
||||
struct nft_ct_helper_obj {
|
||||
struct nf_conntrack_helper *helper4;
|
||||
@@ -543,6 +544,7 @@ static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
|
||||
#endif
|
||||
#ifdef CONFIG_NF_CONNTRACK_ZONES
|
||||
case NFT_CT_ZONE:
|
||||
nf_queue_nf_hook_drop(ctx->net);
|
||||
mutex_lock(&nft_ct_pcpu_mutex);
|
||||
if (--nft_ct_pcpu_template_refcnt == 0)
|
||||
nft_ct_tmpl_put_pcpu();
|
||||
@@ -1015,6 +1017,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
|
||||
struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
|
||||
struct nf_ct_timeout *timeout = priv->timeout;
|
||||
|
||||
nf_queue_nf_hook_drop(ctx->net);
|
||||
nf_ct_untimeout(ctx->net, timeout);
|
||||
nf_ct_netns_put(ctx->net, ctx->family);
|
||||
kfree(priv->timeout);
|
||||
@@ -1147,6 +1150,7 @@ static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx,
|
||||
{
|
||||
struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
|
||||
nf_queue_nf_hook_drop(ctx->net);
|
||||
if (priv->helper4)
|
||||
nf_conntrack_helper_put(priv->helper4);
|
||||
if (priv->helper6)
|
||||
|
||||
@@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv,
|
||||
const struct nft_set_ext *ext)
|
||||
{
|
||||
struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext);
|
||||
struct nft_ctx ctx = {
|
||||
.net = read_pnet(&priv->set->net),
|
||||
.family = priv->set->table->family,
|
||||
};
|
||||
struct nft_expr *expr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_exprs; i++) {
|
||||
expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
|
||||
if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0)
|
||||
return -1;
|
||||
goto err_out;
|
||||
|
||||
elem_expr->size += priv->expr_array[i]->ops->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_out:
|
||||
nft_set_elem_expr_destroy(&ctx, elem_expr);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct nft_elem_priv *nft_dynset_new(struct nft_set *set,
|
||||
|
||||
@@ -304,19 +304,10 @@ static void nft_rbtree_set_start_cookie(struct nft_rbtree *priv,
|
||||
priv->start_rbe_cookie = (unsigned long)rbe;
|
||||
}
|
||||
|
||||
static void nft_rbtree_set_start_cookie_open(struct nft_rbtree *priv,
|
||||
const struct nft_rbtree_elem *rbe,
|
||||
unsigned long open_interval)
|
||||
{
|
||||
priv->start_rbe_cookie = (unsigned long)rbe | open_interval;
|
||||
}
|
||||
|
||||
#define NFT_RBTREE_OPEN_INTERVAL 1UL
|
||||
|
||||
static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv,
|
||||
const struct nft_rbtree_elem *rbe)
|
||||
{
|
||||
return (priv->start_rbe_cookie & ~NFT_RBTREE_OPEN_INTERVAL) == (unsigned long)rbe;
|
||||
return priv->start_rbe_cookie == (unsigned long)rbe;
|
||||
}
|
||||
|
||||
static bool nft_rbtree_insert_same_interval(const struct net *net,
|
||||
@@ -346,14 +337,13 @@ static bool nft_rbtree_insert_same_interval(const struct net *net,
|
||||
|
||||
static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
struct nft_rbtree_elem *new,
|
||||
struct nft_elem_priv **elem_priv, u64 tstamp, bool last)
|
||||
struct nft_elem_priv **elem_priv, u64 tstamp)
|
||||
{
|
||||
struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev;
|
||||
struct rb_node *node, *next, *parent, **p, *first = NULL;
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
u8 cur_genmask = nft_genmask_cur(net);
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
unsigned long open_interval = 0;
|
||||
int d;
|
||||
|
||||
/* Descend the tree to search for an existing element greater than the
|
||||
@@ -459,18 +449,10 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
}
|
||||
}
|
||||
|
||||
if (nft_rbtree_interval_null(set, new)) {
|
||||
if (nft_rbtree_interval_null(set, new))
|
||||
priv->start_rbe_cookie = 0;
|
||||
else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie)
|
||||
priv->start_rbe_cookie = 0;
|
||||
} else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie) {
|
||||
if (nft_set_is_anonymous(set)) {
|
||||
priv->start_rbe_cookie = 0;
|
||||
} else if (priv->start_rbe_cookie & NFT_RBTREE_OPEN_INTERVAL) {
|
||||
/* Previous element is an open interval that partially
|
||||
* overlaps with an existing non-open interval.
|
||||
*/
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* - new start element matching existing start element: full overlap
|
||||
* reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given.
|
||||
@@ -478,27 +460,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) &&
|
||||
nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) {
|
||||
*elem_priv = &rbe_ge->priv;
|
||||
|
||||
/* - Corner case: new start element of open interval (which
|
||||
* comes as last element in the batch) overlaps the start of
|
||||
* an existing interval with an end element: partial overlap.
|
||||
*/
|
||||
node = rb_first(&priv->root);
|
||||
rbe = __nft_rbtree_next_active(node, genmask);
|
||||
if (rbe && nft_rbtree_interval_end(rbe)) {
|
||||
rbe = nft_rbtree_next_active(rbe, genmask);
|
||||
if (rbe &&
|
||||
nft_rbtree_interval_start(rbe) &&
|
||||
!nft_rbtree_cmp(set, new, rbe)) {
|
||||
if (last)
|
||||
return -ENOTEMPTY;
|
||||
|
||||
/* Maybe open interval? */
|
||||
open_interval = NFT_RBTREE_OPEN_INTERVAL;
|
||||
}
|
||||
}
|
||||
nft_rbtree_set_start_cookie_open(priv, rbe_ge, open_interval);
|
||||
|
||||
nft_rbtree_set_start_cookie(priv, rbe_ge);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
@@ -553,12 +515,6 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new))
|
||||
return -ENOTEMPTY;
|
||||
|
||||
/* - start element overlaps an open interval but end element is new:
|
||||
* partial overlap, reported as -ENOEMPTY.
|
||||
*/
|
||||
if (!rbe_ge && priv->start_rbe_cookie && nft_rbtree_interval_end(new))
|
||||
return -ENOTEMPTY;
|
||||
|
||||
/* Accepted element: pick insertion point depending on key value */
|
||||
parent = NULL;
|
||||
p = &priv->root.rb_node;
|
||||
@@ -668,7 +624,6 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
struct nft_elem_priv **elem_priv)
|
||||
{
|
||||
struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv);
|
||||
bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST);
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
u64 tstamp = nft_net_tstamp(net);
|
||||
int err;
|
||||
@@ -685,12 +640,8 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
cond_resched();
|
||||
|
||||
write_lock_bh(&priv->lock);
|
||||
err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp, last);
|
||||
err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp);
|
||||
write_unlock_bh(&priv->lock);
|
||||
|
||||
if (nft_rbtree_interval_end(rbe))
|
||||
priv->start_rbe_cookie = 0;
|
||||
|
||||
} while (err == -EAGAIN);
|
||||
|
||||
return err;
|
||||
@@ -778,7 +729,6 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set,
|
||||
const struct nft_set_elem *elem)
|
||||
{
|
||||
struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv);
|
||||
bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST);
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
const struct rb_node *parent = priv->root.rb_node;
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
@@ -819,10 +769,9 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nft_rbtree_interval_start(rbe)) {
|
||||
if (!last)
|
||||
nft_rbtree_set_start_cookie(priv, rbe);
|
||||
} else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe))
|
||||
if (nft_rbtree_interval_start(rbe))
|
||||
nft_rbtree_set_start_cookie(priv, rbe);
|
||||
else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe))
|
||||
return NULL;
|
||||
|
||||
nft_rbtree_flush(net, set, &rbe->priv);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <net/netfilter/nf_conntrack_ecache.h>
|
||||
#include <net/netfilter/nf_conntrack_timeout.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include "nf_internals.h"
|
||||
|
||||
static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
|
||||
{
|
||||
@@ -283,6 +284,9 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
|
||||
struct nf_conn_help *help;
|
||||
|
||||
if (ct) {
|
||||
if (info->helper[0] || info->timeout[0])
|
||||
nf_queue_nf_hook_drop(par->net);
|
||||
|
||||
help = nfct_help(ct);
|
||||
xt_ct_put_helper(help);
|
||||
|
||||
|
||||
@@ -223,13 +223,13 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
|
||||
localtime_2(¤t_time, stamp);
|
||||
|
||||
if (!(info->weekdays_match & (1 << current_time.weekday)))
|
||||
if (!(info->weekdays_match & (1U << current_time.weekday)))
|
||||
return false;
|
||||
|
||||
/* Do not spend time computing monthday if all days match anyway */
|
||||
if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) {
|
||||
localtime_3(¤t_time, stamp);
|
||||
if (!(info->monthdays_match & (1 << current_time.monthday)))
|
||||
if (!(info->monthdays_match & (1U << current_time.monthday)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user