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