xt_CONNSECMARK.c (3543B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * This module is used to copy security markings from packets 4 * to connections, and restore security markings from connections 5 * back to packets. This would normally be performed in conjunction 6 * with the SECMARK target and state match. 7 * 8 * Based somewhat on CONNMARK: 9 * Copyright (C) 2002,2004 MARA Systems AB <https://www.marasystems.com> 10 * by Henrik Nordstrom <hno@marasystems.com> 11 * 12 * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com> 13 */ 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15#include <linux/module.h> 16#include <linux/skbuff.h> 17#include <linux/netfilter/x_tables.h> 18#include <linux/netfilter/xt_CONNSECMARK.h> 19#include <net/netfilter/nf_conntrack.h> 20#include <net/netfilter/nf_conntrack_ecache.h> 21 22MODULE_LICENSE("GPL"); 23MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); 24MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark"); 25MODULE_ALIAS("ipt_CONNSECMARK"); 26MODULE_ALIAS("ip6t_CONNSECMARK"); 27 28/* 29 * If the packet has a security mark and the connection does not, copy 30 * the security mark from the packet to the connection. 31 */ 32static void secmark_save(const struct sk_buff *skb) 33{ 34 if (skb->secmark) { 35 struct nf_conn *ct; 36 enum ip_conntrack_info ctinfo; 37 38 ct = nf_ct_get(skb, &ctinfo); 39 if (ct && !ct->secmark) { 40 ct->secmark = skb->secmark; 41 nf_conntrack_event_cache(IPCT_SECMARK, ct); 42 } 43 } 44} 45 46/* 47 * If packet has no security mark, and the connection does, restore the 48 * security mark from the connection to the packet. 49 */ 50static void secmark_restore(struct sk_buff *skb) 51{ 52 if (!skb->secmark) { 53 const struct nf_conn *ct; 54 enum ip_conntrack_info ctinfo; 55 56 ct = nf_ct_get(skb, &ctinfo); 57 if (ct && ct->secmark) 58 skb->secmark = ct->secmark; 59 } 60} 61 62static unsigned int 63connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par) 64{ 65 const struct xt_connsecmark_target_info *info = par->targinfo; 66 67 switch (info->mode) { 68 case CONNSECMARK_SAVE: 69 secmark_save(skb); 70 break; 71 72 case CONNSECMARK_RESTORE: 73 secmark_restore(skb); 74 break; 75 76 default: 77 BUG(); 78 } 79 80 return XT_CONTINUE; 81} 82 83static int connsecmark_tg_check(const struct xt_tgchk_param *par) 84{ 85 const struct xt_connsecmark_target_info *info = par->targinfo; 86 int ret; 87 88 if (strcmp(par->table, "mangle") != 0 && 89 strcmp(par->table, "security") != 0) { 90 pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n", 91 par->table); 92 return -EINVAL; 93 } 94 95 switch (info->mode) { 96 case CONNSECMARK_SAVE: 97 case CONNSECMARK_RESTORE: 98 break; 99 100 default: 101 pr_info_ratelimited("invalid mode: %hu\n", info->mode); 102 return -EINVAL; 103 } 104 105 ret = nf_ct_netns_get(par->net, par->family); 106 if (ret < 0) 107 pr_info_ratelimited("cannot load conntrack support for proto=%u\n", 108 par->family); 109 return ret; 110} 111 112static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) 113{ 114 nf_ct_netns_put(par->net, par->family); 115} 116 117static struct xt_target connsecmark_tg_reg __read_mostly = { 118 .name = "CONNSECMARK", 119 .revision = 0, 120 .family = NFPROTO_UNSPEC, 121 .checkentry = connsecmark_tg_check, 122 .destroy = connsecmark_tg_destroy, 123 .target = connsecmark_tg, 124 .targetsize = sizeof(struct xt_connsecmark_target_info), 125 .me = THIS_MODULE, 126}; 127 128static int __init connsecmark_tg_init(void) 129{ 130 return xt_register_target(&connsecmark_tg_reg); 131} 132 133static void __exit connsecmark_tg_exit(void) 134{ 135 xt_unregister_target(&connsecmark_tg_reg); 136} 137 138module_init(connsecmark_tg_init); 139module_exit(connsecmark_tg_exit);