cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nft_last.c (3143B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#include <linux/kernel.h>
      3#include <linux/init.h>
      4#include <linux/module.h>
      5#include <linux/netlink.h>
      6#include <linux/netfilter.h>
      7#include <linux/netfilter/nf_tables.h>
      8#include <net/netfilter/nf_tables_core.h>
      9#include <net/netfilter/nf_tables.h>
     10
     11struct nft_last {
     12	unsigned long	jiffies;
     13	unsigned int	set;
     14};
     15
     16struct nft_last_priv {
     17	struct nft_last	*last;
     18};
     19
     20static const struct nla_policy nft_last_policy[NFTA_LAST_MAX + 1] = {
     21	[NFTA_LAST_SET] = { .type = NLA_U32 },
     22	[NFTA_LAST_MSECS] = { .type = NLA_U64 },
     23};
     24
     25static int nft_last_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
     26			 const struct nlattr * const tb[])
     27{
     28	struct nft_last_priv *priv = nft_expr_priv(expr);
     29	struct nft_last *last;
     30	u64 last_jiffies;
     31	int err;
     32
     33	last = kzalloc(sizeof(*last), GFP_KERNEL_ACCOUNT);
     34	if (!last)
     35		return -ENOMEM;
     36
     37	if (tb[NFTA_LAST_SET])
     38		last->set = ntohl(nla_get_be32(tb[NFTA_LAST_SET]));
     39
     40	if (last->set && tb[NFTA_LAST_MSECS]) {
     41		err = nf_msecs_to_jiffies64(tb[NFTA_LAST_MSECS], &last_jiffies);
     42		if (err < 0)
     43			goto err;
     44
     45		last->jiffies = jiffies - (unsigned long)last_jiffies;
     46	}
     47	priv->last = last;
     48
     49	return 0;
     50err:
     51	kfree(last);
     52
     53	return err;
     54}
     55
     56static void nft_last_eval(const struct nft_expr *expr,
     57			  struct nft_regs *regs, const struct nft_pktinfo *pkt)
     58{
     59	struct nft_last_priv *priv = nft_expr_priv(expr);
     60	struct nft_last *last = priv->last;
     61
     62	if (READ_ONCE(last->jiffies) != jiffies)
     63		WRITE_ONCE(last->jiffies, jiffies);
     64	if (READ_ONCE(last->set) == 0)
     65		WRITE_ONCE(last->set, 1);
     66}
     67
     68static int nft_last_dump(struct sk_buff *skb, const struct nft_expr *expr)
     69{
     70	struct nft_last_priv *priv = nft_expr_priv(expr);
     71	struct nft_last *last = priv->last;
     72	unsigned long last_jiffies = READ_ONCE(last->jiffies);
     73	u32 last_set = READ_ONCE(last->set);
     74	__be64 msecs;
     75
     76	if (time_before(jiffies, last_jiffies)) {
     77		WRITE_ONCE(last->set, 0);
     78		last_set = 0;
     79	}
     80
     81	if (last_set)
     82		msecs = nf_jiffies64_to_msecs(jiffies - last_jiffies);
     83	else
     84		msecs = 0;
     85
     86	if (nla_put_be32(skb, NFTA_LAST_SET, htonl(last_set)) ||
     87	    nla_put_be64(skb, NFTA_LAST_MSECS, msecs, NFTA_LAST_PAD))
     88		goto nla_put_failure;
     89
     90	return 0;
     91
     92nla_put_failure:
     93	return -1;
     94}
     95
     96static void nft_last_destroy(const struct nft_ctx *ctx,
     97			     const struct nft_expr *expr)
     98{
     99	struct nft_last_priv *priv = nft_expr_priv(expr);
    100
    101	kfree(priv->last);
    102}
    103
    104static int nft_last_clone(struct nft_expr *dst, const struct nft_expr *src)
    105{
    106	struct nft_last_priv *priv_dst = nft_expr_priv(dst);
    107
    108	priv_dst->last = kzalloc(sizeof(*priv_dst->last), GFP_ATOMIC);
    109	if (!priv_dst->last)
    110		return -ENOMEM;
    111
    112	return 0;
    113}
    114
    115static const struct nft_expr_ops nft_last_ops = {
    116	.type		= &nft_last_type,
    117	.size		= NFT_EXPR_SIZE(sizeof(struct nft_last_priv)),
    118	.eval		= nft_last_eval,
    119	.init		= nft_last_init,
    120	.destroy	= nft_last_destroy,
    121	.clone		= nft_last_clone,
    122	.dump		= nft_last_dump,
    123	.reduce		= NFT_REDUCE_READONLY,
    124};
    125
    126struct nft_expr_type nft_last_type __read_mostly = {
    127	.name		= "last",
    128	.ops		= &nft_last_ops,
    129	.policy		= nft_last_policy,
    130	.maxattr	= NFTA_LAST_MAX,
    131	.flags		= NFT_EXPR_STATEFUL,
    132	.owner		= THIS_MODULE,
    133};