xref: /openbmc/linux/net/netfilter/xt_SECMARK.c (revision a2df1648)
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