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_u32.c (2796B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *	xt_u32 - kernel module to match u32 packet content
      4 *
      5 *	Original author: Don Cohen <don@isis.cs3-inc.com>
      6 *	(C) CC Computer Consultants GmbH, 2007
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/moduleparam.h>
     11#include <linux/spinlock.h>
     12#include <linux/skbuff.h>
     13#include <linux/types.h>
     14#include <linux/netfilter/x_tables.h>
     15#include <linux/netfilter/xt_u32.h>
     16
     17static bool u32_match_it(const struct xt_u32 *data,
     18			 const struct sk_buff *skb)
     19{
     20	const struct xt_u32_test *ct;
     21	unsigned int testind;
     22	unsigned int nnums;
     23	unsigned int nvals;
     24	unsigned int i;
     25	__be32 n;
     26	u_int32_t pos;
     27	u_int32_t val;
     28	u_int32_t at;
     29
     30	/*
     31	 * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
     32	 * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
     33	 */
     34	for (testind = 0; testind < data->ntests; ++testind) {
     35		ct  = &data->tests[testind];
     36		at  = 0;
     37		pos = ct->location[0].number;
     38
     39		if (skb->len < 4 || pos > skb->len - 4)
     40			return false;
     41
     42		if (skb_copy_bits(skb, pos, &n, sizeof(n)) < 0)
     43			BUG();
     44		val   = ntohl(n);
     45		nnums = ct->nnums;
     46
     47		/* Inner loop runs over "&", "<<", ">>" and "@" operands */
     48		for (i = 1; i < nnums; ++i) {
     49			u_int32_t number = ct->location[i].number;
     50			switch (ct->location[i].nextop) {
     51			case XT_U32_AND:
     52				val &= number;
     53				break;
     54			case XT_U32_LEFTSH:
     55				val <<= number;
     56				break;
     57			case XT_U32_RIGHTSH:
     58				val >>= number;
     59				break;
     60			case XT_U32_AT:
     61				if (at + val < at)
     62					return false;
     63				at += val;
     64				pos = number;
     65				if (at + 4 < at || skb->len < at + 4 ||
     66				    pos > skb->len - at - 4)
     67					return false;
     68
     69				if (skb_copy_bits(skb, at + pos, &n,
     70						    sizeof(n)) < 0)
     71					BUG();
     72				val = ntohl(n);
     73				break;
     74			}
     75		}
     76
     77		/* Run over the "," and ":" operands */
     78		nvals = ct->nvalues;
     79		for (i = 0; i < nvals; ++i)
     80			if (ct->value[i].min <= val && val <= ct->value[i].max)
     81				break;
     82
     83		if (i >= ct->nvalues)
     84			return false;
     85	}
     86
     87	return true;
     88}
     89
     90static bool u32_mt(const struct sk_buff *skb, struct xt_action_param *par)
     91{
     92	const struct xt_u32 *data = par->matchinfo;
     93	bool ret;
     94
     95	ret = u32_match_it(data, skb);
     96	return ret ^ data->invert;
     97}
     98
     99static struct xt_match xt_u32_mt_reg __read_mostly = {
    100	.name       = "u32",
    101	.revision   = 0,
    102	.family     = NFPROTO_UNSPEC,
    103	.match      = u32_mt,
    104	.matchsize  = sizeof(struct xt_u32),
    105	.me         = THIS_MODULE,
    106};
    107
    108static int __init u32_mt_init(void)
    109{
    110	return xt_register_match(&xt_u32_mt_reg);
    111}
    112
    113static void __exit u32_mt_exit(void)
    114{
    115	xt_unregister_match(&xt_u32_mt_reg);
    116}
    117
    118module_init(u32_mt_init);
    119module_exit(u32_mt_exit);
    120MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
    121MODULE_DESCRIPTION("Xtables: arbitrary byte matching");
    122MODULE_LICENSE("GPL");
    123MODULE_ALIAS("ipt_u32");
    124MODULE_ALIAS("ip6t_u32");