Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This module is used to copy security markings from packets
0004  * to connections, and restore security markings from connections
0005  * back to packets.  This would normally be performed in conjunction
0006  * with the SECMARK target and state match.
0007  *
0008  * Based somewhat on CONNMARK:
0009  *   Copyright (C) 2002,2004 MARA Systems AB <https://www.marasystems.com>
0010  *    by Henrik Nordstrom <hno@marasystems.com>
0011  *
0012  * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
0013  */
0014 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0015 #include <linux/module.h>
0016 #include <linux/skbuff.h>
0017 #include <linux/netfilter/x_tables.h>
0018 #include <linux/netfilter/xt_CONNSECMARK.h>
0019 #include <net/netfilter/nf_conntrack.h>
0020 #include <net/netfilter/nf_conntrack_ecache.h>
0021 
0022 MODULE_LICENSE("GPL");
0023 MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
0024 MODULE_DESCRIPTION("Xtables: target for copying between connection and security mark");
0025 MODULE_ALIAS("ipt_CONNSECMARK");
0026 MODULE_ALIAS("ip6t_CONNSECMARK");
0027 
0028 /*
0029  * If the packet has a security mark and the connection does not, copy
0030  * the security mark from the packet to the connection.
0031  */
0032 static void secmark_save(const struct sk_buff *skb)
0033 {
0034     if (skb->secmark) {
0035         struct nf_conn *ct;
0036         enum ip_conntrack_info ctinfo;
0037 
0038         ct = nf_ct_get(skb, &ctinfo);
0039         if (ct && !ct->secmark) {
0040             ct->secmark = skb->secmark;
0041             nf_conntrack_event_cache(IPCT_SECMARK, ct);
0042         }
0043     }
0044 }
0045 
0046 /*
0047  * If packet has no security mark, and the connection does, restore the
0048  * security mark from the connection to the packet.
0049  */
0050 static void secmark_restore(struct sk_buff *skb)
0051 {
0052     if (!skb->secmark) {
0053         const struct nf_conn *ct;
0054         enum ip_conntrack_info ctinfo;
0055 
0056         ct = nf_ct_get(skb, &ctinfo);
0057         if (ct && ct->secmark)
0058             skb->secmark = ct->secmark;
0059     }
0060 }
0061 
0062 static unsigned int
0063 connsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
0064 {
0065     const struct xt_connsecmark_target_info *info = par->targinfo;
0066 
0067     switch (info->mode) {
0068     case CONNSECMARK_SAVE:
0069         secmark_save(skb);
0070         break;
0071 
0072     case CONNSECMARK_RESTORE:
0073         secmark_restore(skb);
0074         break;
0075 
0076     default:
0077         BUG();
0078     }
0079 
0080     return XT_CONTINUE;
0081 }
0082 
0083 static int connsecmark_tg_check(const struct xt_tgchk_param *par)
0084 {
0085     const struct xt_connsecmark_target_info *info = par->targinfo;
0086     int ret;
0087 
0088     if (strcmp(par->table, "mangle") != 0 &&
0089         strcmp(par->table, "security") != 0) {
0090         pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
0091                     par->table);
0092         return -EINVAL;
0093     }
0094 
0095     switch (info->mode) {
0096     case CONNSECMARK_SAVE:
0097     case CONNSECMARK_RESTORE:
0098         break;
0099 
0100     default:
0101         pr_info_ratelimited("invalid mode: %hu\n", info->mode);
0102         return -EINVAL;
0103     }
0104 
0105     ret = nf_ct_netns_get(par->net, par->family);
0106     if (ret < 0)
0107         pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
0108                     par->family);
0109     return ret;
0110 }
0111 
0112 static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
0113 {
0114     nf_ct_netns_put(par->net, par->family);
0115 }
0116 
0117 static struct xt_target connsecmark_tg_reg __read_mostly = {
0118     .name       = "CONNSECMARK",
0119     .revision   = 0,
0120     .family     = NFPROTO_UNSPEC,
0121     .checkentry = connsecmark_tg_check,
0122     .destroy    = connsecmark_tg_destroy,
0123     .target     = connsecmark_tg,
0124     .targetsize = sizeof(struct xt_connsecmark_target_info),
0125     .me         = THIS_MODULE,
0126 };
0127 
0128 static int __init connsecmark_tg_init(void)
0129 {
0130     return xt_register_target(&connsecmark_tg_reg);
0131 }
0132 
0133 static void __exit connsecmark_tg_exit(void)
0134 {
0135     xt_unregister_target(&connsecmark_tg_reg);
0136 }
0137 
0138 module_init(connsecmark_tg_init);
0139 module_exit(connsecmark_tg_exit);