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 * 8560ee653SJames Morris * (C) 2006,2008 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>"); 232ae15b64SJan Engelhardt MODULE_DESCRIPTION("Xtables: packet security mark modification"); 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 31d3c5ee6dSJan Engelhardt static unsigned int 327eb35586SJan Engelhardt secmark_tg(struct sk_buff *skb, const struct xt_target_param *par) 335e6874cdSJames Morris { 345e6874cdSJames Morris u32 secmark = 0; 357eb35586SJan Engelhardt const struct xt_secmark_target_info *info = par->targinfo; 365e6874cdSJames Morris 375e6874cdSJames Morris BUG_ON(info->mode != mode); 385e6874cdSJames Morris 395e6874cdSJames Morris switch (mode) { 405e6874cdSJames Morris case SECMARK_MODE_SEL: 415e6874cdSJames Morris secmark = info->u.sel.selsid; 425e6874cdSJames Morris break; 435e6874cdSJames Morris 445e6874cdSJames Morris default: 455e6874cdSJames Morris BUG(); 465e6874cdSJames Morris } 475e6874cdSJames Morris 483db05feaSHerbert Xu skb->secmark = secmark; 495e6874cdSJames Morris return XT_CONTINUE; 505e6874cdSJames Morris } 515e6874cdSJames Morris 52e1931b78SJan Engelhardt static bool checkentry_selinux(struct xt_secmark_target_info *info) 535e6874cdSJames Morris { 545e6874cdSJames Morris int err; 555e6874cdSJames Morris struct xt_secmark_target_selinux_info *sel = &info->u.sel; 56a280b899SJames Morris 57a280b899SJames Morris sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0'; 585e6874cdSJames Morris 595e6874cdSJames Morris err = selinux_string_to_sid(sel->selctx, &sel->selsid); 605e6874cdSJames Morris if (err) { 615e6874cdSJames Morris if (err == -EINVAL) 625e6874cdSJames Morris printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", 635e6874cdSJames Morris sel->selctx); 64e1931b78SJan Engelhardt return false; 655e6874cdSJames Morris } 665e6874cdSJames Morris 675e6874cdSJames Morris if (!sel->selsid) { 685e6874cdSJames Morris printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", 695e6874cdSJames Morris sel->selctx); 70e1931b78SJan Engelhardt return false; 715e6874cdSJames Morris } 725e6874cdSJames Morris 73d621d35eSPaul Moore err = selinux_secmark_relabel_packet_permission(sel->selsid); 745e6874cdSJames Morris if (err) { 755e6874cdSJames Morris printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); 76e1931b78SJan Engelhardt return false; 775e6874cdSJames Morris } 785e6874cdSJames Morris 79d621d35eSPaul Moore selinux_secmark_refcount_inc(); 80e1931b78SJan Engelhardt return true; 815e6874cdSJames Morris } 825e6874cdSJames Morris 83af5d6dc2SJan Engelhardt static bool secmark_tg_check(const struct xt_tgchk_param *par) 845e6874cdSJames Morris { 85af5d6dc2SJan Engelhardt struct xt_secmark_target_info *info = par->targinfo; 865e6874cdSJames Morris 87af5d6dc2SJan Engelhardt if (strcmp(par->table, "mangle") != 0 && 88af5d6dc2SJan Engelhardt strcmp(par->table, "security") != 0) { 89560ee653SJames Morris printk(KERN_INFO PFX "target only valid in the \'mangle\' " 90af5d6dc2SJan Engelhardt "or \'security\' tables, not \'%s\'.\n", par->table); 91560ee653SJames Morris return false; 92560ee653SJames Morris } 93560ee653SJames Morris 945e6874cdSJames Morris if (mode && mode != info->mode) { 955e6874cdSJames Morris printk(KERN_INFO PFX "mode already set to %hu cannot mix with " 965e6874cdSJames Morris "rules for mode %hu\n", mode, info->mode); 97e1931b78SJan Engelhardt return false; 985e6874cdSJames Morris } 995e6874cdSJames Morris 1005e6874cdSJames Morris switch (info->mode) { 1015e6874cdSJames Morris case SECMARK_MODE_SEL: 1025e6874cdSJames Morris if (!checkentry_selinux(info)) 103e1931b78SJan Engelhardt return false; 1045e6874cdSJames Morris break; 1055e6874cdSJames Morris 1065e6874cdSJames Morris default: 1075e6874cdSJames Morris printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); 108e1931b78SJan Engelhardt return false; 1095e6874cdSJames Morris } 1105e6874cdSJames Morris 1115e6874cdSJames Morris if (!mode) 1125e6874cdSJames Morris mode = info->mode; 113e1931b78SJan Engelhardt return true; 1145e6874cdSJames Morris } 1155e6874cdSJames Morris 116a2df1648SJan Engelhardt static void secmark_tg_destroy(const struct xt_tgdtor_param *par) 117d621d35eSPaul Moore { 118d621d35eSPaul Moore switch (mode) { 119d621d35eSPaul Moore case SECMARK_MODE_SEL: 120d621d35eSPaul Moore selinux_secmark_refcount_dec(); 121d621d35eSPaul Moore } 122d621d35eSPaul Moore } 123d621d35eSPaul Moore 12455b69e91SJan Engelhardt static struct xt_target secmark_tg_reg __read_mostly = { 1255e6874cdSJames Morris .name = "SECMARK", 12655b69e91SJan Engelhardt .revision = 0, 12755b69e91SJan Engelhardt .family = NFPROTO_UNSPEC, 128d3c5ee6dSJan Engelhardt .checkentry = secmark_tg_check, 129d621d35eSPaul Moore .destroy = secmark_tg_destroy, 130d3c5ee6dSJan Engelhardt .target = secmark_tg, 1315e6874cdSJames Morris .targetsize = sizeof(struct xt_secmark_target_info), 1325e6874cdSJames Morris .me = THIS_MODULE, 1335e6874cdSJames Morris }; 1345e6874cdSJames Morris 135d3c5ee6dSJan Engelhardt static int __init secmark_tg_init(void) 1365e6874cdSJames Morris { 13755b69e91SJan Engelhardt return xt_register_target(&secmark_tg_reg); 1385e6874cdSJames Morris } 1395e6874cdSJames Morris 140d3c5ee6dSJan Engelhardt static void __exit secmark_tg_exit(void) 1415e6874cdSJames Morris { 14255b69e91SJan Engelhardt xt_unregister_target(&secmark_tg_reg); 1435e6874cdSJames Morris } 1445e6874cdSJames Morris 145d3c5ee6dSJan Engelhardt module_init(secmark_tg_init); 146d3c5ee6dSJan Engelhardt module_exit(secmark_tg_exit); 147