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_SECMARK.c (4348B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Module for modifying the secmark field of the skb, for use by
      4 * security subsystems.
      5 *
      6 * Based on the nfmark match by:
      7 * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
      8 *
      9 * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
     10 */
     11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     12#include <linux/module.h>
     13#include <linux/security.h>
     14#include <linux/skbuff.h>
     15#include <linux/netfilter/x_tables.h>
     16#include <linux/netfilter/xt_SECMARK.h>
     17
     18MODULE_LICENSE("GPL");
     19MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
     20MODULE_DESCRIPTION("Xtables: packet security mark modification");
     21MODULE_ALIAS("ipt_SECMARK");
     22MODULE_ALIAS("ip6t_SECMARK");
     23
     24static u8 mode;
     25
     26static unsigned int
     27secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info)
     28{
     29	u32 secmark = 0;
     30
     31	switch (mode) {
     32	case SECMARK_MODE_SEL:
     33		secmark = info->secid;
     34		break;
     35	default:
     36		BUG();
     37	}
     38
     39	skb->secmark = secmark;
     40	return XT_CONTINUE;
     41}
     42
     43static int checkentry_lsm(struct xt_secmark_target_info_v1 *info)
     44{
     45	int err;
     46
     47	info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
     48	info->secid = 0;
     49
     50	err = security_secctx_to_secid(info->secctx, strlen(info->secctx),
     51				       &info->secid);
     52	if (err) {
     53		if (err == -EINVAL)
     54			pr_info_ratelimited("invalid security context \'%s\'\n",
     55					    info->secctx);
     56		return err;
     57	}
     58
     59	if (!info->secid) {
     60		pr_info_ratelimited("unable to map security context \'%s\'\n",
     61				    info->secctx);
     62		return -ENOENT;
     63	}
     64
     65	err = security_secmark_relabel_packet(info->secid);
     66	if (err) {
     67		pr_info_ratelimited("unable to obtain relabeling permission\n");
     68		return err;
     69	}
     70
     71	security_secmark_refcount_inc();
     72	return 0;
     73}
     74
     75static int
     76secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info)
     77{
     78	int err;
     79
     80	if (strcmp(table, "mangle") != 0 &&
     81	    strcmp(table, "security") != 0) {
     82		pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
     83				    table);
     84		return -EINVAL;
     85	}
     86
     87	if (mode && mode != info->mode) {
     88		pr_info_ratelimited("mode already set to %hu cannot mix with rules for mode %hu\n",
     89				    mode, info->mode);
     90		return -EINVAL;
     91	}
     92
     93	switch (info->mode) {
     94	case SECMARK_MODE_SEL:
     95		break;
     96	default:
     97		pr_info_ratelimited("invalid mode: %hu\n", info->mode);
     98		return -EINVAL;
     99	}
    100
    101	err = checkentry_lsm(info);
    102	if (err)
    103		return err;
    104
    105	if (!mode)
    106		mode = info->mode;
    107	return 0;
    108}
    109
    110static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
    111{
    112	switch (mode) {
    113	case SECMARK_MODE_SEL:
    114		security_secmark_refcount_dec();
    115	}
    116}
    117
    118static int secmark_tg_check_v0(const struct xt_tgchk_param *par)
    119{
    120	struct xt_secmark_target_info *info = par->targinfo;
    121	struct xt_secmark_target_info_v1 newinfo = {
    122		.mode	= info->mode,
    123	};
    124	int ret;
    125
    126	memcpy(newinfo.secctx, info->secctx, SECMARK_SECCTX_MAX);
    127
    128	ret = secmark_tg_check(par->table, &newinfo);
    129	info->secid = newinfo.secid;
    130
    131	return ret;
    132}
    133
    134static unsigned int
    135secmark_tg_v0(struct sk_buff *skb, const struct xt_action_param *par)
    136{
    137	const struct xt_secmark_target_info *info = par->targinfo;
    138	struct xt_secmark_target_info_v1 newinfo = {
    139		.secid	= info->secid,
    140	};
    141
    142	return secmark_tg(skb, &newinfo);
    143}
    144
    145static int secmark_tg_check_v1(const struct xt_tgchk_param *par)
    146{
    147	return secmark_tg_check(par->table, par->targinfo);
    148}
    149
    150static unsigned int
    151secmark_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
    152{
    153	return secmark_tg(skb, par->targinfo);
    154}
    155
    156static struct xt_target secmark_tg_reg[] __read_mostly = {
    157	{
    158		.name		= "SECMARK",
    159		.revision	= 0,
    160		.family		= NFPROTO_UNSPEC,
    161		.checkentry	= secmark_tg_check_v0,
    162		.destroy	= secmark_tg_destroy,
    163		.target		= secmark_tg_v0,
    164		.targetsize	= sizeof(struct xt_secmark_target_info),
    165		.me		= THIS_MODULE,
    166	},
    167	{
    168		.name		= "SECMARK",
    169		.revision	= 1,
    170		.family		= NFPROTO_UNSPEC,
    171		.checkentry	= secmark_tg_check_v1,
    172		.destroy	= secmark_tg_destroy,
    173		.target		= secmark_tg_v1,
    174		.targetsize	= sizeof(struct xt_secmark_target_info_v1),
    175		.usersize	= offsetof(struct xt_secmark_target_info_v1, secid),
    176		.me		= THIS_MODULE,
    177	},
    178};
    179
    180static int __init secmark_tg_init(void)
    181{
    182	return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
    183}
    184
    185static void __exit secmark_tg_exit(void)
    186{
    187	xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
    188}
    189
    190module_init(secmark_tg_init);
    191module_exit(secmark_tg_exit);