netfilter pull request nf-26-03-13
-----BEGIN PGP SIGNATURE----- iQJdBAABCABHFiEEgKkgxbID4Gn1hq6fcJGo2a1f9gAFAmm0H74bFIAAAAAABAAO bWFudTIsMi41KzEuMTEsMiwyDRxmd0BzdHJsZW4uZGUACgkQcJGo2a1f9gAB5BAA hkqYt78OBz3ATN4FIA2G9jg/3EN6Qz59Db+Io4b6PJhqhVkmJfkf6s9TZLMFFUdN Q888fn/gMfvfsxBX9EM8m/w4qWdnKu/qPBYpmCOi2rByyN6lYUEa1M1elKlISdVe 2LG4FhVIRn4gXfp0xEovsb70JkLPh1tzuQB7Kaq3/MrjObXxYodUexvJWkjt3zkF ziRg1hx+PO+FjA7M0MmZmPjr/KyRoP9IGesInCIZZ0BJimkwgvry9KFqSTLazn6w AiN32MJc6tNesKNq6ulF4oLCAcu5x5NPbQZS7wx0vV+oO49W2v25mvmyza6XpRLi s0hQ5OLfPIDddIcdwhiFsSUtD1nTRRrtzjkMZdupCR9YNfpFjK2zsqM3LY3+mn7B vtPJV0j1PeFXzbRSK8teog3cjB8eTwIZiriqEXZslK9XD5bsICWq+72v5xJmKpIE Pk+p5g2yLyUkbl/F3D8zh8INTn38QZOTZtYeHZLse7xKWsGRGWjvc5ncaUQQyD+J pNrGdRf9ESbMVfrxoPi0oMtrnPcFllqH2MejNXb7FeHApF8Iq/c3i0lmya1N3aFa CAMv4T4e8ik5M+Yxn/OeN4KtdzJq2eGPIe12aZAq6T8ZWrqvUW+vgNbWuRHeR2WM apUiHEcfZg4Pt4TJox7UvBNUOj+aJz1a17esfv1pwwU= =wla9 -----END PGP SIGNATURE----- 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:
commit
eeeff8dda6
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue