Skip to content

FIPS-8 Legacy: CVE-2024-27397 #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,16 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex
return nft_set_ext(ext, NFT_SET_EXT_EXPRESSIONS);
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
u64 tstamp)
{
return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext));
time_after_eq64(tstamp, *nft_set_ext_expiration(ext));
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
{
return __nft_set_elem_expired(ext, get_jiffies_64());
}

static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
Expand Down Expand Up @@ -1534,6 +1540,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
#endif

struct nftables_pernet {
u64 tstamp;
unsigned int gc_seq;
};

Expand All @@ -1544,4 +1551,9 @@ static inline struct nftables_pernet *nft_pernet(const struct net *net)
return net_generic(net, nf_tables_net_id);
}

static inline u64 nft_net_tstamp(const struct net *net)
{
return nft_pernet(net)->tstamp;
}

#endif /* _NET_NF_TABLES_H */
2 changes: 2 additions & 0 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -8643,9 +8643,11 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb,

static bool nf_tables_valid_genid(struct net *net, u32 genid)
{
struct nftables_pernet *nft_net = nft_pernet(net);
bool genid_ok;

mutex_lock(&net->nft_commit_mutex);
nft_net->tstamp = get_jiffies_64();

genid_ok = genid == 0 || net->nft.base_seq == genid;
if (!genid_ok)
Expand Down
8 changes: 7 additions & 1 deletion net/netfilter/nft_set_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct nft_rhash_cmp_arg {
const struct nft_set *set;
const u32 *key;
u8 genmask;
u64 tstamp;
};

static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed)
Expand All @@ -64,7 +65,7 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
return 1;
if (nft_set_elem_is_dead(&he->ext))
return 1;
if (nft_set_elem_expired(&he->ext))
if (__nft_set_elem_expired(&he->ext, x->tstamp))
return 1;
if (!nft_set_elem_active(&he->ext, x->genmask))
return 1;
Expand All @@ -88,6 +89,7 @@ static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
.genmask = nft_genmask_cur(net),
.set = set,
.key = key,
.tstamp = get_jiffies_64(),
};

he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
Expand All @@ -106,6 +108,7 @@ static void *nft_rhash_get(const struct net *net, const struct nft_set *set,
.genmask = nft_genmask_cur(net),
.set = set,
.key = elem->key.val.data,
.tstamp = get_jiffies_64(),
};

he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
Expand All @@ -129,6 +132,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
.genmask = NFT_GENMASK_ANY,
.set = set,
.key = key,
.tstamp = get_jiffies_64(),
};

he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
Expand Down Expand Up @@ -172,6 +176,7 @@ static int nft_rhash_insert(const struct net *net, const struct nft_set *set,
.genmask = nft_genmask_next(net),
.set = set,
.key = elem->key.val.data,
.tstamp = nft_net_tstamp(net),
};
struct nft_rhash_elem *prev;

Expand Down Expand Up @@ -212,6 +217,7 @@ static void *nft_rhash_deactivate(const struct net *net,
.genmask = nft_genmask_next(net),
.set = set,
.key = elem->key.val.data,
.tstamp = nft_net_tstamp(net),
};

rcu_read_lock();
Expand Down
18 changes: 11 additions & 7 deletions net/netfilter/nft_set_pipapo.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ static bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
* @set: nftables API set representation
* @data: Key data to be matched against existing elements
* @genmask: If set, check that element is active in given genmask
* @tstamp: timestamp to check for expired elements
*
* This is essentially the same as the lookup function, except that it matches
* key data against the uncommitted copy and doesn't use preallocated maps for
Expand All @@ -644,7 +645,8 @@ static bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
*/
static struct nft_pipapo_elem *pipapo_get(const struct net *net,
const struct nft_set *set,
const u8 *data, u8 genmask)
const u8 *data, u8 genmask,
u64 tstamp)
{
struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
struct nft_pipapo *priv = nft_set_priv(set);
Expand Down Expand Up @@ -704,7 +706,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net,
goto out;

if (last) {
if (nft_set_elem_expired(&f->mt[b].e->ext))
if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp))
goto next_match;
if ((genmask &&
!nft_set_elem_active(&f->mt[b].e->ext, genmask)))
Expand Down Expand Up @@ -741,7 +743,7 @@ void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
const struct nft_set_elem *elem, unsigned int flags)
{
return pipapo_get(net, set, (const u8 *)elem->key.val.data,
nft_genmask_cur(net));
nft_genmask_cur(net), get_jiffies_64());
}

/**
Expand Down Expand Up @@ -1100,14 +1102,15 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
struct nft_pipapo *priv = nft_set_priv(set);
struct nft_pipapo_match *m = priv->clone;
u8 genmask = nft_genmask_next(net);
u64 tstamp = nft_net_tstamp(net);
struct nft_pipapo_field *f;
int i, bsize_max, err = 0;

dup = pipapo_get(net, set, start, genmask);
dup = pipapo_get(net, set, start, genmask, tstamp);
if (PTR_ERR(dup) == -ENOENT) {
if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END)) {
end = (const u8 *)nft_set_ext_key_end(ext)->data;
dup = pipapo_get(net, set, end, nft_genmask_next(net));
dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp);
} else {
end = start;
}
Expand Down Expand Up @@ -1457,6 +1460,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
struct nft_set *set = (struct nft_set *) _set;
struct nft_pipapo *priv = nft_set_priv(set);
struct net *net = read_pnet(&set->net);
u64 tstamp = nft_net_tstamp(net);
int rules_f0, first_rule = 0;
struct nft_pipapo_elem *e;
struct nft_trans_gc *gc;
Expand Down Expand Up @@ -1491,7 +1495,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
/* synchronous gc never fails, there is no need to set on
* NFT_SET_ELEM_DEAD_BIT.
*/
if (nft_set_elem_expired(&e->ext)) {
if (__nft_set_elem_expired(&e->ext, tstamp)) {
priv->dirty = true;

gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
Expand Down Expand Up @@ -1662,7 +1666,7 @@ static void *pipapo_deactivate(const struct net *net, const struct nft_set *set,
{
struct nft_pipapo_elem *e;

e = pipapo_get(net, set, data, nft_genmask_next(net));
e = pipapo_get(net, set, data, nft_genmask_next(net), nft_net_tstamp(net));
if (IS_ERR(e))
return NULL;

Expand Down
21 changes: 13 additions & 8 deletions net/netfilter/nft_set_rbtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
{
struct nft_rbtree *priv = nft_set_priv(set);
u8 genmask = nft_genmask_next(net);
u64 tstamp = nft_net_tstamp(net);
struct nft_rbtree_elem *rbe;
struct rb_node *parent, **p;
bool overlap = false;
Expand Down Expand Up @@ -287,13 +288,13 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
if (nft_rbtree_interval_start(new)) {
if (nft_rbtree_interval_end(rbe) &&
nft_set_elem_active(&rbe->ext, genmask) &&
!nft_set_elem_expired(&rbe->ext) && !*p)
!__nft_set_elem_expired(&rbe->ext, tstamp) && !*p)
overlap = false;
} else {
overlap = nft_rbtree_interval_end(rbe) &&
nft_set_elem_active(&rbe->ext,
genmask) &&
!nft_set_elem_expired(&rbe->ext);
!__nft_set_elem_expired(&rbe->ext, tstamp);
}
} else if (d > 0) {
p = &parent->rb_right;
Expand All @@ -302,9 +303,9 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
overlap = nft_rbtree_interval_end(rbe) &&
nft_set_elem_active(&rbe->ext,
genmask) &&
!nft_set_elem_expired(&rbe->ext);
!__nft_set_elem_expired(&rbe->ext, tstamp);
} else if (nft_set_elem_active(&rbe->ext, genmask) &&
!nft_set_elem_expired(&rbe->ext)) {
!__nft_set_elem_expired(&rbe->ext, tstamp)) {
overlap = nft_rbtree_interval_end(rbe);
}
} else {
Expand All @@ -313,17 +314,17 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
p = &parent->rb_left;

if (nft_set_elem_active(&rbe->ext, genmask) &&
!nft_set_elem_expired(&rbe->ext))
!__nft_set_elem_expired(&rbe->ext, tstamp))
overlap = false;
} else if (nft_rbtree_interval_start(rbe) &&
nft_rbtree_interval_end(new)) {
p = &parent->rb_right;

if (nft_set_elem_active(&rbe->ext, genmask) &&
!nft_set_elem_expired(&rbe->ext))
!__nft_set_elem_expired(&rbe->ext, tstamp))
overlap = false;
} else if (nft_set_elem_active(&rbe->ext, genmask) &&
!nft_set_elem_expired(&rbe->ext)) {
!__nft_set_elem_expired(&rbe->ext, tstamp)) {
*ext = &rbe->ext;
return -EEXIST;
} else {
Expand Down Expand Up @@ -400,6 +401,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
const struct rb_node *parent = priv->root.rb_node;
struct nft_rbtree_elem *rbe, *this = elem->priv;
u8 genmask = nft_genmask_next(net);
u64 tstamp = nft_net_tstamp(net);
int d;

while (parent != NULL) {
Expand All @@ -420,6 +422,8 @@ static void *nft_rbtree_deactivate(const struct net *net,
nft_rbtree_interval_end(this)) {
parent = parent->rb_right;
continue;
} else if (__nft_set_elem_expired(&rbe->ext, tstamp)) {
break;
} else if (!nft_set_elem_active(&rbe->ext, genmask)) {
parent = parent->rb_left;
continue;
Expand Down Expand Up @@ -472,6 +476,7 @@ static void nft_rbtree_gc(struct work_struct *work)
struct nft_set *set;
unsigned int gc_seq;
struct net *net;
u64 tstamp;

priv = container_of(work, struct nft_rbtree, gc_work.work);
set = nft_set_container_of(priv);
Expand Down Expand Up @@ -510,7 +515,7 @@ static void nft_rbtree_gc(struct work_struct *work)
rbe_end = rbe;
continue;
}
if (!nft_set_elem_expired(&rbe->ext))
if (!__nft_set_elem_expired(&rbe->ext, tstamp))
continue;

nft_set_elem_dead(&rbe->ext);
Expand Down
Loading