1100468e9c05c10fb6872751c1af523b996d6afa9James Morris/* 2100468e9c05c10fb6872751c1af523b996d6afa9James Morris * This module is used to copy security markings from packets 3100468e9c05c10fb6872751c1af523b996d6afa9James Morris * to connections, and restore security markings from connections 4100468e9c05c10fb6872751c1af523b996d6afa9James Morris * back to packets. This would normally be performed in conjunction 5100468e9c05c10fb6872751c1af523b996d6afa9James Morris * with the SECMARK target and state match. 6100468e9c05c10fb6872751c1af523b996d6afa9James Morris * 7100468e9c05c10fb6872751c1af523b996d6afa9James Morris * Based somewhat on CONNMARK: 8100468e9c05c10fb6872751c1af523b996d6afa9James Morris * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 9100468e9c05c10fb6872751c1af523b996d6afa9James Morris * by Henrik Nordstrom <hno@marasystems.com> 10100468e9c05c10fb6872751c1af523b996d6afa9James Morris * 11560ee653b67074b805f1b661988a72a0e58811a5James Morris * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com> 12100468e9c05c10fb6872751c1af523b996d6afa9James Morris * 13100468e9c05c10fb6872751c1af523b996d6afa9James Morris * This program is free software; you can redistribute it and/or modify 14100468e9c05c10fb6872751c1af523b996d6afa9James Morris * it under the terms of the GNU General Public License version 2 as 15100468e9c05c10fb6872751c1af523b996d6afa9James Morris * published by the Free Software Foundation. 16100468e9c05c10fb6872751c1af523b996d6afa9James Morris * 17100468e9c05c10fb6872751c1af523b996d6afa9James Morris */ 188bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19100468e9c05c10fb6872751c1af523b996d6afa9James Morris#include <linux/module.h> 20100468e9c05c10fb6872751c1af523b996d6afa9James Morris#include <linux/skbuff.h> 21100468e9c05c10fb6872751c1af523b996d6afa9James Morris#include <linux/netfilter/x_tables.h> 22100468e9c05c10fb6872751c1af523b996d6afa9James Morris#include <linux/netfilter/xt_CONNSECMARK.h> 23587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy#include <net/netfilter/nf_conntrack.h> 2437fccd8577d38e249dde71512fb38d2f6a4d9d3cPablo Neira Ayuso#include <net/netfilter/nf_conntrack_ecache.h> 25100468e9c05c10fb6872751c1af523b996d6afa9James Morris 26100468e9c05c10fb6872751c1af523b996d6afa9James MorrisMODULE_LICENSE("GPL"); 27100468e9c05c10fb6872751c1af523b996d6afa9James MorrisMODULE_AUTHOR("James Morris <jmorris@redhat.com>"); 282ae15b64e6a1608c840c60df38e8e5eef7b2b8c3Jan EngelhardtMODULE_DESCRIPTION("Xtables: target for copying between connection and security mark"); 29100468e9c05c10fb6872751c1af523b996d6afa9James MorrisMODULE_ALIAS("ipt_CONNSECMARK"); 30100468e9c05c10fb6872751c1af523b996d6afa9James MorrisMODULE_ALIAS("ip6t_CONNSECMARK"); 31100468e9c05c10fb6872751c1af523b996d6afa9James Morris 32100468e9c05c10fb6872751c1af523b996d6afa9James Morris/* 33100468e9c05c10fb6872751c1af523b996d6afa9James Morris * If the packet has a security mark and the connection does not, copy 34100468e9c05c10fb6872751c1af523b996d6afa9James Morris * the security mark from the packet to the connection. 35100468e9c05c10fb6872751c1af523b996d6afa9James Morris */ 36a47362a226456d8db8207e618324a2278d05d3a7Jan Engelhardtstatic void secmark_save(const struct sk_buff *skb) 37100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 38100468e9c05c10fb6872751c1af523b996d6afa9James Morris if (skb->secmark) { 39587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy struct nf_conn *ct; 40100468e9c05c10fb6872751c1af523b996d6afa9James Morris enum ip_conntrack_info ctinfo; 41100468e9c05c10fb6872751c1af523b996d6afa9James Morris 42587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 4337fccd8577d38e249dde71512fb38d2f6a4d9d3cPablo Neira Ayuso if (ct && !ct->secmark) { 44587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy ct->secmark = skb->secmark; 45a71996fccce4b2086a26036aa3c915365ca36926Alexey Dobriyan nf_conntrack_event_cache(IPCT_SECMARK, ct); 4637fccd8577d38e249dde71512fb38d2f6a4d9d3cPablo Neira Ayuso } 47100468e9c05c10fb6872751c1af523b996d6afa9James Morris } 48100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 49100468e9c05c10fb6872751c1af523b996d6afa9James Morris 50100468e9c05c10fb6872751c1af523b996d6afa9James Morris/* 51100468e9c05c10fb6872751c1af523b996d6afa9James Morris * If packet has no security mark, and the connection does, restore the 52100468e9c05c10fb6872751c1af523b996d6afa9James Morris * security mark from the connection to the packet. 53100468e9c05c10fb6872751c1af523b996d6afa9James Morris */ 54100468e9c05c10fb6872751c1af523b996d6afa9James Morrisstatic void secmark_restore(struct sk_buff *skb) 55100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 56100468e9c05c10fb6872751c1af523b996d6afa9James Morris if (!skb->secmark) { 573cf93c96af7adf78542d45f8a27f0e5f8704409dJan Engelhardt const struct nf_conn *ct; 58100468e9c05c10fb6872751c1af523b996d6afa9James Morris enum ip_conntrack_info ctinfo; 59100468e9c05c10fb6872751c1af523b996d6afa9James Morris 60587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy ct = nf_ct_get(skb, &ctinfo); 61587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy if (ct && ct->secmark) 62587aa64163bb14f70098f450abab9410787fce9dPatrick McHardy skb->secmark = ct->secmark; 63100468e9c05c10fb6872751c1af523b996d6afa9James Morris } 64100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 65100468e9c05c10fb6872751c1af523b996d6afa9James Morris 66d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic unsigned int 674b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardtconnsecmark_tg(struct sk_buff *skb, const struct xt_action_param *par) 68100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 697eb3558655aaa87a3e71a0c065dfaddda521fa6dJan Engelhardt const struct xt_connsecmark_target_info *info = par->targinfo; 70100468e9c05c10fb6872751c1af523b996d6afa9James Morris 71100468e9c05c10fb6872751c1af523b996d6afa9James Morris switch (info->mode) { 72100468e9c05c10fb6872751c1af523b996d6afa9James Morris case CONNSECMARK_SAVE: 73100468e9c05c10fb6872751c1af523b996d6afa9James Morris secmark_save(skb); 74100468e9c05c10fb6872751c1af523b996d6afa9James Morris break; 75100468e9c05c10fb6872751c1af523b996d6afa9James Morris 76100468e9c05c10fb6872751c1af523b996d6afa9James Morris case CONNSECMARK_RESTORE: 77100468e9c05c10fb6872751c1af523b996d6afa9James Morris secmark_restore(skb); 78100468e9c05c10fb6872751c1af523b996d6afa9James Morris break; 79100468e9c05c10fb6872751c1af523b996d6afa9James Morris 80100468e9c05c10fb6872751c1af523b996d6afa9James Morris default: 81100468e9c05c10fb6872751c1af523b996d6afa9James Morris BUG(); 82100468e9c05c10fb6872751c1af523b996d6afa9James Morris } 83100468e9c05c10fb6872751c1af523b996d6afa9James Morris 84100468e9c05c10fb6872751c1af523b996d6afa9James Morris return XT_CONTINUE; 85100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 86100468e9c05c10fb6872751c1af523b996d6afa9James Morris 87135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int connsecmark_tg_check(const struct xt_tgchk_param *par) 88100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 89af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt const struct xt_connsecmark_target_info *info = par->targinfo; 904a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt int ret; 91100468e9c05c10fb6872751c1af523b996d6afa9James Morris 92af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt if (strcmp(par->table, "mangle") != 0 && 93af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt strcmp(par->table, "security") != 0) { 948bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("target only valid in the \'mangle\' " 958bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt "or \'security\' tables, not \'%s\'.\n", par->table); 96d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt return -EINVAL; 97560ee653b67074b805f1b661988a72a0e58811a5James Morris } 98560ee653b67074b805f1b661988a72a0e58811a5James Morris 99100468e9c05c10fb6872751c1af523b996d6afa9James Morris switch (info->mode) { 100100468e9c05c10fb6872751c1af523b996d6afa9James Morris case CONNSECMARK_SAVE: 101100468e9c05c10fb6872751c1af523b996d6afa9James Morris case CONNSECMARK_RESTORE: 102100468e9c05c10fb6872751c1af523b996d6afa9James Morris break; 103100468e9c05c10fb6872751c1af523b996d6afa9James Morris 104100468e9c05c10fb6872751c1af523b996d6afa9James Morris default: 1058bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("invalid mode: %hu\n", info->mode); 1064a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt return -EINVAL; 107100468e9c05c10fb6872751c1af523b996d6afa9James Morris } 108100468e9c05c10fb6872751c1af523b996d6afa9James Morris 1094a5a5c73b7cfee46a0b1411903cfa0dea532deecJan Engelhardt ret = nf_ct_l3proto_try_module_get(par->family); 110f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt if (ret < 0) 1118bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt pr_info("cannot load conntrack support for proto=%u\n", 1128bee4bad03c5b601bd6cea123c31025680587cccJan Engelhardt par->family); 113f95c74e33eff5e3fe9798e2dc0a7749150ea3f80Jan Engelhardt return ret; 114100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 115100468e9c05c10fb6872751c1af523b996d6afa9James Morris 116a2df1648ba615dd5908e9a1fa7b2f133fa302487Jan Engelhardtstatic void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) 11711078c371e2ecfce011d1dffb67888c6fed1b664Yasuyuki Kozakai{ 11892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt nf_ct_l3proto_module_put(par->family); 11911078c371e2ecfce011d1dffb67888c6fed1b664Yasuyuki Kozakai} 12011078c371e2ecfce011d1dffb67888c6fed1b664Yasuyuki Kozakai 12192f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardtstatic struct xt_target connsecmark_tg_reg __read_mostly = { 12292f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .name = "CONNSECMARK", 12392f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .revision = 0, 12492f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .family = NFPROTO_UNSPEC, 12592f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .checkentry = connsecmark_tg_check, 12692f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .destroy = connsecmark_tg_destroy, 12792f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .target = connsecmark_tg, 12892f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .targetsize = sizeof(struct xt_connsecmark_target_info), 12992f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt .me = THIS_MODULE, 130100468e9c05c10fb6872751c1af523b996d6afa9James Morris}; 131100468e9c05c10fb6872751c1af523b996d6afa9James Morris 132d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic int __init connsecmark_tg_init(void) 133100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 13492f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt return xt_register_target(&connsecmark_tg_reg); 135100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 136100468e9c05c10fb6872751c1af523b996d6afa9James Morris 137d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtstatic void __exit connsecmark_tg_exit(void) 138100468e9c05c10fb6872751c1af523b996d6afa9James Morris{ 13992f3b2b1bc968caaabee8cd78bee75ab7c4af74eJan Engelhardt xt_unregister_target(&connsecmark_tg_reg); 140100468e9c05c10fb6872751c1af523b996d6afa9James Morris} 141100468e9c05c10fb6872751c1af523b996d6afa9James Morris 142d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_init(connsecmark_tg_init); 143d3c5ee6d545b5372fd525ebe16988a5b6efeceb0Jan Engelhardtmodule_exit(connsecmark_tg_exit); 144