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

xt_statistic.c (2499B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
      4 *
      5 * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>.
      6 */
      7
      8#include <linux/init.h>
      9#include <linux/spinlock.h>
     10#include <linux/skbuff.h>
     11#include <linux/net.h>
     12#include <linux/slab.h>
     13
     14#include <linux/netfilter/xt_statistic.h>
     15#include <linux/netfilter/x_tables.h>
     16#include <linux/module.h>
     17
     18struct xt_statistic_priv {
     19	atomic_t count;
     20} ____cacheline_aligned_in_smp;
     21
     22MODULE_LICENSE("GPL");
     23MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
     24MODULE_DESCRIPTION("Xtables: statistics-based matching (\"Nth\", random)");
     25MODULE_ALIAS("ipt_statistic");
     26MODULE_ALIAS("ip6t_statistic");
     27
     28static bool
     29statistic_mt(const struct sk_buff *skb, struct xt_action_param *par)
     30{
     31	const struct xt_statistic_info *info = par->matchinfo;
     32	bool ret = info->flags & XT_STATISTIC_INVERT;
     33	int nval, oval;
     34
     35	switch (info->mode) {
     36	case XT_STATISTIC_MODE_RANDOM:
     37		if ((prandom_u32() & 0x7FFFFFFF) < info->u.random.probability)
     38			ret = !ret;
     39		break;
     40	case XT_STATISTIC_MODE_NTH:
     41		do {
     42			oval = atomic_read(&info->master->count);
     43			nval = (oval == info->u.nth.every) ? 0 : oval + 1;
     44		} while (atomic_cmpxchg(&info->master->count, oval, nval) != oval);
     45		if (nval == 0)
     46			ret = !ret;
     47		break;
     48	}
     49
     50	return ret;
     51}
     52
     53static int statistic_mt_check(const struct xt_mtchk_param *par)
     54{
     55	struct xt_statistic_info *info = par->matchinfo;
     56
     57	if (info->mode > XT_STATISTIC_MODE_MAX ||
     58	    info->flags & ~XT_STATISTIC_MASK)
     59		return -EINVAL;
     60
     61	info->master = kzalloc(sizeof(*info->master), GFP_KERNEL);
     62	if (info->master == NULL)
     63		return -ENOMEM;
     64	atomic_set(&info->master->count, info->u.nth.count);
     65
     66	return 0;
     67}
     68
     69static void statistic_mt_destroy(const struct xt_mtdtor_param *par)
     70{
     71	const struct xt_statistic_info *info = par->matchinfo;
     72
     73	kfree(info->master);
     74}
     75
     76static struct xt_match xt_statistic_mt_reg __read_mostly = {
     77	.name       = "statistic",
     78	.revision   = 0,
     79	.family     = NFPROTO_UNSPEC,
     80	.match      = statistic_mt,
     81	.checkentry = statistic_mt_check,
     82	.destroy    = statistic_mt_destroy,
     83	.matchsize  = sizeof(struct xt_statistic_info),
     84	.usersize   = offsetof(struct xt_statistic_info, master),
     85	.me         = THIS_MODULE,
     86};
     87
     88static int __init statistic_mt_init(void)
     89{
     90	return xt_register_match(&xt_statistic_mt_reg);
     91}
     92
     93static void __exit statistic_mt_exit(void)
     94{
     95	xt_unregister_match(&xt_statistic_mt_reg);
     96}
     97
     98module_init(statistic_mt_init);
     99module_exit(statistic_mt_exit);