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_objref.c (6632B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.org>
      4 */
      5
      6#include <linux/init.h>
      7#include <linux/module.h>
      8#include <linux/skbuff.h>
      9#include <linux/netlink.h>
     10#include <linux/netfilter.h>
     11#include <linux/netfilter/nf_tables.h>
     12#include <net/netfilter/nf_tables_core.h>
     13
     14#define nft_objref_priv(expr)	*((struct nft_object **)nft_expr_priv(expr))
     15
     16static void nft_objref_eval(const struct nft_expr *expr,
     17			    struct nft_regs *regs,
     18			    const struct nft_pktinfo *pkt)
     19{
     20	struct nft_object *obj = nft_objref_priv(expr);
     21
     22	obj->ops->eval(obj, regs, pkt);
     23}
     24
     25static int nft_objref_init(const struct nft_ctx *ctx,
     26			   const struct nft_expr *expr,
     27			   const struct nlattr * const tb[])
     28{
     29	struct nft_object *obj = nft_objref_priv(expr);
     30	u8 genmask = nft_genmask_next(ctx->net);
     31	u32 objtype;
     32
     33	if (!tb[NFTA_OBJREF_IMM_NAME] ||
     34	    !tb[NFTA_OBJREF_IMM_TYPE])
     35		return -EINVAL;
     36
     37	objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE]));
     38	obj = nft_obj_lookup(ctx->net, ctx->table,
     39			     tb[NFTA_OBJREF_IMM_NAME], objtype,
     40			     genmask);
     41	if (IS_ERR(obj))
     42		return -ENOENT;
     43
     44	nft_objref_priv(expr) = obj;
     45	obj->use++;
     46
     47	return 0;
     48}
     49
     50static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
     51{
     52	const struct nft_object *obj = nft_objref_priv(expr);
     53
     54	if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->key.name) ||
     55	    nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE,
     56			 htonl(obj->ops->type->type)))
     57		goto nla_put_failure;
     58
     59	return 0;
     60
     61nla_put_failure:
     62	return -1;
     63}
     64
     65static void nft_objref_deactivate(const struct nft_ctx *ctx,
     66				  const struct nft_expr *expr,
     67				  enum nft_trans_phase phase)
     68{
     69	struct nft_object *obj = nft_objref_priv(expr);
     70
     71	if (phase == NFT_TRANS_COMMIT)
     72		return;
     73
     74	obj->use--;
     75}
     76
     77static void nft_objref_activate(const struct nft_ctx *ctx,
     78				const struct nft_expr *expr)
     79{
     80	struct nft_object *obj = nft_objref_priv(expr);
     81
     82	obj->use++;
     83}
     84
     85static struct nft_expr_type nft_objref_type;
     86static const struct nft_expr_ops nft_objref_ops = {
     87	.type		= &nft_objref_type,
     88	.size		= NFT_EXPR_SIZE(sizeof(struct nft_object *)),
     89	.eval		= nft_objref_eval,
     90	.init		= nft_objref_init,
     91	.activate	= nft_objref_activate,
     92	.deactivate	= nft_objref_deactivate,
     93	.dump		= nft_objref_dump,
     94	.reduce		= NFT_REDUCE_READONLY,
     95};
     96
     97struct nft_objref_map {
     98	struct nft_set		*set;
     99	u8			sreg;
    100	struct nft_set_binding	binding;
    101};
    102
    103static void nft_objref_map_eval(const struct nft_expr *expr,
    104				struct nft_regs *regs,
    105				const struct nft_pktinfo *pkt)
    106{
    107	struct nft_objref_map *priv = nft_expr_priv(expr);
    108	const struct nft_set *set = priv->set;
    109	struct net *net = nft_net(pkt);
    110	const struct nft_set_ext *ext;
    111	struct nft_object *obj;
    112	bool found;
    113
    114	found = nft_set_do_lookup(net, set, &regs->data[priv->sreg], &ext);
    115	if (!found) {
    116		ext = nft_set_catchall_lookup(net, set);
    117		if (!ext) {
    118			regs->verdict.code = NFT_BREAK;
    119			return;
    120		}
    121	}
    122	obj = *nft_set_ext_obj(ext);
    123	obj->ops->eval(obj, regs, pkt);
    124}
    125
    126static int nft_objref_map_init(const struct nft_ctx *ctx,
    127			       const struct nft_expr *expr,
    128			       const struct nlattr * const tb[])
    129{
    130	struct nft_objref_map *priv = nft_expr_priv(expr);
    131	u8 genmask = nft_genmask_next(ctx->net);
    132	struct nft_set *set;
    133	int err;
    134
    135	set = nft_set_lookup_global(ctx->net, ctx->table,
    136				    tb[NFTA_OBJREF_SET_NAME],
    137				    tb[NFTA_OBJREF_SET_ID], genmask);
    138	if (IS_ERR(set))
    139		return PTR_ERR(set);
    140
    141	if (!(set->flags & NFT_SET_OBJECT))
    142		return -EINVAL;
    143
    144	err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg,
    145				      set->klen);
    146	if (err < 0)
    147		return err;
    148
    149	priv->binding.flags = set->flags & NFT_SET_OBJECT;
    150
    151	err = nf_tables_bind_set(ctx, set, &priv->binding);
    152	if (err < 0)
    153		return err;
    154
    155	priv->set = set;
    156	return 0;
    157}
    158
    159static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)
    160{
    161	const struct nft_objref_map *priv = nft_expr_priv(expr);
    162
    163	if (nft_dump_register(skb, NFTA_OBJREF_SET_SREG, priv->sreg) ||
    164	    nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name))
    165		goto nla_put_failure;
    166
    167	return 0;
    168
    169nla_put_failure:
    170	return -1;
    171}
    172
    173static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
    174				      const struct nft_expr *expr,
    175				      enum nft_trans_phase phase)
    176{
    177	struct nft_objref_map *priv = nft_expr_priv(expr);
    178
    179	nf_tables_deactivate_set(ctx, priv->set, &priv->binding, phase);
    180}
    181
    182static void nft_objref_map_activate(const struct nft_ctx *ctx,
    183				    const struct nft_expr *expr)
    184{
    185	struct nft_objref_map *priv = nft_expr_priv(expr);
    186
    187	priv->set->use++;
    188}
    189
    190static void nft_objref_map_destroy(const struct nft_ctx *ctx,
    191				   const struct nft_expr *expr)
    192{
    193	struct nft_objref_map *priv = nft_expr_priv(expr);
    194
    195	nf_tables_destroy_set(ctx, priv->set);
    196}
    197
    198static struct nft_expr_type nft_objref_type;
    199static const struct nft_expr_ops nft_objref_map_ops = {
    200	.type		= &nft_objref_type,
    201	.size		= NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
    202	.eval		= nft_objref_map_eval,
    203	.init		= nft_objref_map_init,
    204	.activate	= nft_objref_map_activate,
    205	.deactivate	= nft_objref_map_deactivate,
    206	.destroy	= nft_objref_map_destroy,
    207	.dump		= nft_objref_map_dump,
    208	.reduce		= NFT_REDUCE_READONLY,
    209};
    210
    211static const struct nft_expr_ops *
    212nft_objref_select_ops(const struct nft_ctx *ctx,
    213                      const struct nlattr * const tb[])
    214{
    215	if (tb[NFTA_OBJREF_SET_SREG] &&
    216	    (tb[NFTA_OBJREF_SET_NAME] ||
    217	     tb[NFTA_OBJREF_SET_ID]))
    218		return &nft_objref_map_ops;
    219	else if (tb[NFTA_OBJREF_IMM_NAME] &&
    220		 tb[NFTA_OBJREF_IMM_TYPE])
    221		return &nft_objref_ops;
    222
    223	return ERR_PTR(-EOPNOTSUPP);
    224}
    225
    226static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = {
    227	[NFTA_OBJREF_IMM_NAME]	= { .type = NLA_STRING,
    228				    .len = NFT_OBJ_MAXNAMELEN - 1 },
    229	[NFTA_OBJREF_IMM_TYPE]	= { .type = NLA_U32 },
    230	[NFTA_OBJREF_SET_SREG]	= { .type = NLA_U32 },
    231	[NFTA_OBJREF_SET_NAME]	= { .type = NLA_STRING,
    232				    .len = NFT_SET_MAXNAMELEN - 1 },
    233	[NFTA_OBJREF_SET_ID]	= { .type = NLA_U32 },
    234};
    235
    236static struct nft_expr_type nft_objref_type __read_mostly = {
    237	.name		= "objref",
    238	.select_ops	= nft_objref_select_ops,
    239	.policy		= nft_objref_policy,
    240	.maxattr	= NFTA_OBJREF_MAX,
    241	.owner		= THIS_MODULE,
    242};
    243
    244static int __init nft_objref_module_init(void)
    245{
    246	return nft_register_expr(&nft_objref_type);
    247}
    248
    249static void __exit nft_objref_module_exit(void)
    250{
    251	nft_unregister_expr(&nft_objref_type);
    252}
    253
    254module_init(nft_objref_module_init);
    255module_exit(nft_objref_module_exit);
    256
    257MODULE_LICENSE("GPL");
    258MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
    259MODULE_ALIAS_NFT_EXPR("objref");
    260MODULE_DESCRIPTION("nftables stateful object reference module");