15e6874cdSJames Morris /* 25e6874cdSJames Morris * Module for modifying the secmark field of the skb, for use by 35e6874cdSJames Morris * security subsystems. 45e6874cdSJames Morris * 55e6874cdSJames Morris * Based on the nfmark match by: 65e6874cdSJames Morris * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> 75e6874cdSJames Morris * 85e6874cdSJames Morris * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> 95e6874cdSJames Morris * 105e6874cdSJames Morris * This program is free software; you can redistribute it and/or modify 115e6874cdSJames Morris * it under the terms of the GNU General Public License version 2 as 125e6874cdSJames Morris * published by the Free Software Foundation. 135e6874cdSJames Morris * 145e6874cdSJames Morris */ 155e6874cdSJames Morris #include <linux/module.h> 165e6874cdSJames Morris #include <linux/skbuff.h> 175e6874cdSJames Morris #include <linux/selinux.h> 185e6874cdSJames Morris #include <linux/netfilter/x_tables.h> 195e6874cdSJames Morris #include <linux/netfilter/xt_SECMARK.h> 205e6874cdSJames Morris 215e6874cdSJames Morris MODULE_LICENSE("GPL"); 225e6874cdSJames Morris MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); 235e6874cdSJames Morris MODULE_DESCRIPTION("ip[6]tables SECMARK modification module"); 245e6874cdSJames Morris MODULE_ALIAS("ipt_SECMARK"); 255e6874cdSJames Morris MODULE_ALIAS("ip6t_SECMARK"); 265e6874cdSJames Morris 275e6874cdSJames Morris #define PFX "SECMARK: " 285e6874cdSJames Morris 295e6874cdSJames Morris static u8 mode; 305e6874cdSJames Morris 315e6874cdSJames Morris static unsigned int target(struct sk_buff **pskb, const struct net_device *in, 325e6874cdSJames Morris const struct net_device *out, unsigned int hooknum, 335e6874cdSJames Morris const struct xt_target *target, 34fe1cb108SPatrick McHardy const void *targinfo) 355e6874cdSJames Morris { 365e6874cdSJames Morris u32 secmark = 0; 375e6874cdSJames Morris const struct xt_secmark_target_info *info = targinfo; 385e6874cdSJames Morris 395e6874cdSJames Morris BUG_ON(info->mode != mode); 405e6874cdSJames Morris 415e6874cdSJames Morris switch (mode) { 425e6874cdSJames Morris case SECMARK_MODE_SEL: 435e6874cdSJames Morris secmark = info->u.sel.selsid; 445e6874cdSJames Morris break; 455e6874cdSJames Morris 465e6874cdSJames Morris default: 475e6874cdSJames Morris BUG(); 485e6874cdSJames Morris } 495e6874cdSJames Morris 505e6874cdSJames Morris (*pskb)->secmark = secmark; 515e6874cdSJames Morris return XT_CONTINUE; 525e6874cdSJames Morris } 535e6874cdSJames Morris 54e1931b78SJan Engelhardt static bool checkentry_selinux(struct xt_secmark_target_info *info) 555e6874cdSJames Morris { 565e6874cdSJames Morris int err; 575e6874cdSJames Morris struct xt_secmark_target_selinux_info *sel = &info->u.sel; 58a280b899SJames Morris 59a280b899SJames Morris sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0'; 605e6874cdSJames Morris 615e6874cdSJames Morris err = selinux_string_to_sid(sel->selctx, &sel->selsid); 625e6874cdSJames Morris if (err) { 635e6874cdSJames Morris if (err == -EINVAL) 645e6874cdSJames Morris printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", 655e6874cdSJames Morris sel->selctx); 66e1931b78SJan Engelhardt return false; 675e6874cdSJames Morris } 685e6874cdSJames Morris 695e6874cdSJames Morris if (!sel->selsid) { 705e6874cdSJames Morris printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", 715e6874cdSJames Morris sel->selctx); 72e1931b78SJan Engelhardt return false; 735e6874cdSJames Morris } 745e6874cdSJames Morris 755e6874cdSJames Morris err = selinux_relabel_packet_permission(sel->selsid); 765e6874cdSJames Morris if (err) { 775e6874cdSJames Morris printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); 78e1931b78SJan Engelhardt return false; 795e6874cdSJames Morris } 805e6874cdSJames Morris 81e1931b78SJan Engelhardt return true; 825e6874cdSJames Morris } 835e6874cdSJames Morris 84e1931b78SJan Engelhardt static bool checkentry(const char *tablename, const void *entry, 855e6874cdSJames Morris const struct xt_target *target, void *targinfo, 86efa74165SPatrick McHardy unsigned int hook_mask) 875e6874cdSJames Morris { 885e6874cdSJames Morris struct xt_secmark_target_info *info = targinfo; 895e6874cdSJames Morris 905e6874cdSJames Morris if (mode && mode != info->mode) { 915e6874cdSJames Morris printk(KERN_INFO PFX "mode already set to %hu cannot mix with " 925e6874cdSJames Morris "rules for mode %hu\n", mode, info->mode); 93e1931b78SJan Engelhardt return false; 945e6874cdSJames Morris } 955e6874cdSJames Morris 965e6874cdSJames Morris switch (info->mode) { 975e6874cdSJames Morris case SECMARK_MODE_SEL: 985e6874cdSJames Morris if (!checkentry_selinux(info)) 99e1931b78SJan Engelhardt return false; 1005e6874cdSJames Morris break; 1015e6874cdSJames Morris 1025e6874cdSJames Morris default: 1035e6874cdSJames Morris printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); 104e1931b78SJan Engelhardt return false; 1055e6874cdSJames Morris } 1065e6874cdSJames Morris 1075e6874cdSJames Morris if (!mode) 1085e6874cdSJames Morris mode = info->mode; 109e1931b78SJan Engelhardt return true; 1105e6874cdSJames Morris } 1115e6874cdSJames Morris 11228094864SThomas Graf static struct xt_target xt_secmark_target[] = { 1134470bbc7SPatrick McHardy { 1145e6874cdSJames Morris .name = "SECMARK", 1155e6874cdSJames Morris .family = AF_INET, 1164470bbc7SPatrick McHardy .checkentry = checkentry, 1175e6874cdSJames Morris .target = target, 1185e6874cdSJames Morris .targetsize = sizeof(struct xt_secmark_target_info), 1195e6874cdSJames Morris .table = "mangle", 1205e6874cdSJames Morris .me = THIS_MODULE, 1214470bbc7SPatrick McHardy }, 1224470bbc7SPatrick McHardy { 1234470bbc7SPatrick McHardy .name = "SECMARK", 1245e6874cdSJames Morris .family = AF_INET6, 1254470bbc7SPatrick McHardy .checkentry = checkentry, 1264470bbc7SPatrick McHardy .target = target, 1274470bbc7SPatrick McHardy .targetsize = sizeof(struct xt_secmark_target_info), 1284470bbc7SPatrick McHardy .table = "mangle", 1294470bbc7SPatrick McHardy .me = THIS_MODULE, 1304470bbc7SPatrick McHardy }, 1315e6874cdSJames Morris }; 1325e6874cdSJames Morris 1335e6874cdSJames Morris static int __init xt_secmark_init(void) 1345e6874cdSJames Morris { 1354470bbc7SPatrick McHardy return xt_register_targets(xt_secmark_target, 1364470bbc7SPatrick McHardy ARRAY_SIZE(xt_secmark_target)); 1375e6874cdSJames Morris } 1385e6874cdSJames Morris 1395e6874cdSJames Morris static void __exit xt_secmark_fini(void) 1405e6874cdSJames Morris { 1414470bbc7SPatrick McHardy xt_unregister_targets(xt_secmark_target, ARRAY_SIZE(xt_secmark_target)); 1425e6874cdSJames Morris } 1435e6874cdSJames Morris 1445e6874cdSJames Morris module_init(xt_secmark_init); 1455e6874cdSJames Morris module_exit(xt_secmark_fini); 146