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_connmark.c (5251B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *	xt_connmark - Netfilter module to operate on connection marks
      4 *
      5 *	Copyright (C) 2002,2004 MARA Systems AB <https://www.marasystems.com>
      6 *	by Henrik Nordstrom <hno@marasystems.com>
      7 *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
      8 *	Jan Engelhardt <jengelh@medozas.de>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/skbuff.h>
     13#include <net/netfilter/nf_conntrack.h>
     14#include <net/netfilter/nf_conntrack_ecache.h>
     15#include <linux/netfilter/x_tables.h>
     16#include <linux/netfilter/xt_connmark.h>
     17
     18MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
     19MODULE_DESCRIPTION("Xtables: connection mark operations");
     20MODULE_LICENSE("GPL");
     21MODULE_ALIAS("ipt_CONNMARK");
     22MODULE_ALIAS("ip6t_CONNMARK");
     23MODULE_ALIAS("ipt_connmark");
     24MODULE_ALIAS("ip6t_connmark");
     25
     26static unsigned int
     27connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)
     28{
     29	enum ip_conntrack_info ctinfo;
     30	u_int32_t new_targetmark;
     31	struct nf_conn *ct;
     32	u_int32_t newmark;
     33
     34	ct = nf_ct_get(skb, &ctinfo);
     35	if (ct == NULL)
     36		return XT_CONTINUE;
     37
     38	switch (info->mode) {
     39	case XT_CONNMARK_SET:
     40		newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
     41		if (info->shift_dir == D_SHIFT_RIGHT)
     42			newmark >>= info->shift_bits;
     43		else
     44			newmark <<= info->shift_bits;
     45
     46		if (ct->mark != newmark) {
     47			ct->mark = newmark;
     48			nf_conntrack_event_cache(IPCT_MARK, ct);
     49		}
     50		break;
     51	case XT_CONNMARK_SAVE:
     52		new_targetmark = (skb->mark & info->nfmask);
     53		if (info->shift_dir == D_SHIFT_RIGHT)
     54			new_targetmark >>= info->shift_bits;
     55		else
     56			new_targetmark <<= info->shift_bits;
     57
     58		newmark = (ct->mark & ~info->ctmask) ^
     59			  new_targetmark;
     60		if (ct->mark != newmark) {
     61			ct->mark = newmark;
     62			nf_conntrack_event_cache(IPCT_MARK, ct);
     63		}
     64		break;
     65	case XT_CONNMARK_RESTORE:
     66		new_targetmark = (ct->mark & info->ctmask);
     67		if (info->shift_dir == D_SHIFT_RIGHT)
     68			new_targetmark >>= info->shift_bits;
     69		else
     70			new_targetmark <<= info->shift_bits;
     71
     72		newmark = (skb->mark & ~info->nfmask) ^
     73			  new_targetmark;
     74		skb->mark = newmark;
     75		break;
     76	}
     77	return XT_CONTINUE;
     78}
     79
     80static unsigned int
     81connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
     82{
     83	const struct xt_connmark_tginfo1 *info = par->targinfo;
     84	const struct xt_connmark_tginfo2 info2 = {
     85		.ctmark	= info->ctmark,
     86		.ctmask	= info->ctmask,
     87		.nfmask	= info->nfmask,
     88		.mode	= info->mode,
     89	};
     90
     91	return connmark_tg_shift(skb, &info2);
     92}
     93
     94static unsigned int
     95connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
     96{
     97	const struct xt_connmark_tginfo2 *info = par->targinfo;
     98
     99	return connmark_tg_shift(skb, info);
    100}
    101
    102static int connmark_tg_check(const struct xt_tgchk_param *par)
    103{
    104	int ret;
    105
    106	ret = nf_ct_netns_get(par->net, par->family);
    107	if (ret < 0)
    108		pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
    109				    par->family);
    110	return ret;
    111}
    112
    113static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
    114{
    115	nf_ct_netns_put(par->net, par->family);
    116}
    117
    118static bool
    119connmark_mt(const struct sk_buff *skb, struct xt_action_param *par)
    120{
    121	const struct xt_connmark_mtinfo1 *info = par->matchinfo;
    122	enum ip_conntrack_info ctinfo;
    123	const struct nf_conn *ct;
    124
    125	ct = nf_ct_get(skb, &ctinfo);
    126	if (ct == NULL)
    127		return false;
    128
    129	return ((ct->mark & info->mask) == info->mark) ^ info->invert;
    130}
    131
    132static int connmark_mt_check(const struct xt_mtchk_param *par)
    133{
    134	int ret;
    135
    136	ret = nf_ct_netns_get(par->net, par->family);
    137	if (ret < 0)
    138		pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
    139				    par->family);
    140	return ret;
    141}
    142
    143static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
    144{
    145	nf_ct_netns_put(par->net, par->family);
    146}
    147
    148static struct xt_target connmark_tg_reg[] __read_mostly = {
    149	{
    150		.name           = "CONNMARK",
    151		.revision       = 1,
    152		.family         = NFPROTO_UNSPEC,
    153		.checkentry     = connmark_tg_check,
    154		.target         = connmark_tg,
    155		.targetsize     = sizeof(struct xt_connmark_tginfo1),
    156		.destroy        = connmark_tg_destroy,
    157		.me             = THIS_MODULE,
    158	},
    159	{
    160		.name           = "CONNMARK",
    161		.revision       = 2,
    162		.family         = NFPROTO_UNSPEC,
    163		.checkentry     = connmark_tg_check,
    164		.target         = connmark_tg_v2,
    165		.targetsize     = sizeof(struct xt_connmark_tginfo2),
    166		.destroy        = connmark_tg_destroy,
    167		.me             = THIS_MODULE,
    168	}
    169};
    170
    171static struct xt_match connmark_mt_reg __read_mostly = {
    172	.name           = "connmark",
    173	.revision       = 1,
    174	.family         = NFPROTO_UNSPEC,
    175	.checkentry     = connmark_mt_check,
    176	.match          = connmark_mt,
    177	.matchsize      = sizeof(struct xt_connmark_mtinfo1),
    178	.destroy        = connmark_mt_destroy,
    179	.me             = THIS_MODULE,
    180};
    181
    182static int __init connmark_mt_init(void)
    183{
    184	int ret;
    185
    186	ret = xt_register_targets(connmark_tg_reg,
    187				  ARRAY_SIZE(connmark_tg_reg));
    188	if (ret < 0)
    189		return ret;
    190	ret = xt_register_match(&connmark_mt_reg);
    191	if (ret < 0) {
    192		xt_unregister_targets(connmark_tg_reg,
    193				      ARRAY_SIZE(connmark_tg_reg));
    194		return ret;
    195	}
    196	return 0;
    197}
    198
    199static void __exit connmark_mt_exit(void)
    200{
    201	xt_unregister_match(&connmark_mt_reg);
    202	xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
    203}
    204
    205module_init(connmark_mt_init);
    206module_exit(connmark_mt_exit);