aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2008-06-09 18:57:24 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-09 18:57:24 -0400
commit560ee653b67074b805f1b661988a72a0e58811a5 (patch)
treee480158d626854dde7421d87e76b1fa6443c457f
parenta258860e01b80e8f554a4ab1a6c95e6042eb8b73 (diff)
netfilter: ip_tables: add iptables security table for mandatory access control rules
The following patch implements a new "security" table for iptables, so that MAC (SELinux etc.) networking rules can be managed separately to standard DAC rules. This is to help with distro integration of the new secmark-based network controls, per various previous discussions. The need for a separate table arises from the fact that existing tools and usage of iptables will likely clash with centralized MAC policy management. The SECMARK and CONNSECMARK targets will still be valid in the mangle table to prevent breakage of existing users. Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter_ipv4.h1
-rw-r--r--include/net/netns/ipv4.h1
-rw-r--r--net/ipv4/netfilter/Kconfig12
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/iptable_security.c180
-rw-r--r--net/netfilter/xt_CONNSECMARK.c10
-rw-r--r--net/netfilter/xt_SECMARK.c10
7 files changed, 209 insertions, 6 deletions
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 650318b0c405..29c7727ff0e8 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -60,6 +60,7 @@ enum nf_ip_hook_priorities {
60 NF_IP_PRI_MANGLE = -150, 60 NF_IP_PRI_MANGLE = -150,
61 NF_IP_PRI_NAT_DST = -100, 61 NF_IP_PRI_NAT_DST = -100,
62 NF_IP_PRI_FILTER = 0, 62 NF_IP_PRI_FILTER = 0,
63 NF_IP_PRI_SECURITY = 50,
63 NF_IP_PRI_NAT_SRC = 100, 64 NF_IP_PRI_NAT_SRC = 100,
64 NF_IP_PRI_SELINUX_LAST = 225, 65 NF_IP_PRI_SELINUX_LAST = 225,
65 NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX, 66 NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 34ee348a2cf2..6ef90b5fafb3 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -36,6 +36,7 @@ struct netns_ipv4 {
36 struct xt_table *iptable_mangle; 36 struct xt_table *iptable_mangle;
37 struct xt_table *iptable_raw; 37 struct xt_table *iptable_raw;
38 struct xt_table *arptable_filter; 38 struct xt_table *arptable_filter;
39 struct xt_table *iptable_security;
39#endif 40#endif
40 41
41 int sysctl_icmp_echo_ignore_all; 42 int sysctl_icmp_echo_ignore_all;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 2767841a8cef..6e251402506e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -365,6 +365,18 @@ config IP_NF_RAW
365 If you want to compile it as a module, say M here and read 365 If you want to compile it as a module, say M here and read
366 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 366 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
367 367
368# security table for MAC policy
369config IP_NF_SECURITY
370 tristate "Security table"
371 depends on IP_NF_IPTABLES
372 depends on SECURITY
373 default m if NETFILTER_ADVANCED=n
374 help
375 This option adds a `security' table to iptables, for use
376 with Mandatory Access Control (MAC) policy.
377
378 If unsure, say N.
379
368# ARP tables 380# ARP tables
369config IP_NF_ARPTABLES 381config IP_NF_ARPTABLES
370 tristate "ARP tables support" 382 tristate "ARP tables support"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index d9b92fbf5579..3f31291f37ce 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
42obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o 42obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
43obj-$(CONFIG_NF_NAT) += iptable_nat.o 43obj-$(CONFIG_NF_NAT) += iptable_nat.o
44obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o 44obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
45obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
45 46
46# matches 47# matches
47obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 48obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
new file mode 100644
index 000000000000..2b472ac2263a
--- /dev/null
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -0,0 +1,180 @@
1/*
2 * "security" table
3 *
4 * This is for use by Mandatory Access Control (MAC) security models,
5 * which need to be able to manage security policy in separate context
6 * to DAC.
7 *
8 * Based on iptable_mangle.c
9 *
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 * Copyright (C) 2000-2004 Netfilter Core Team <coreteam <at> netfilter.org>
12 * Copyright (C) 2008 Red Hat, Inc., James Morris <jmorris <at> redhat.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#include <linux/module.h>
19#include <linux/netfilter_ipv4/ip_tables.h>
20#include <net/ip.h>
21
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("James Morris <jmorris <at> redhat.com>");
24MODULE_DESCRIPTION("iptables security table, for MAC rules");
25
26#define SECURITY_VALID_HOOKS (1 << NF_INET_LOCAL_IN) | \
27 (1 << NF_INET_FORWARD) | \
28 (1 << NF_INET_LOCAL_OUT)
29
30static struct
31{
32 struct ipt_replace repl;
33 struct ipt_standard entries[3];
34 struct ipt_error term;
35} initial_table __initdata = {
36 .repl = {
37 .name = "security",
38 .valid_hooks = SECURITY_VALID_HOOKS,
39 .num_entries = 4,
40 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
41 .hook_entry = {
42 [NF_INET_LOCAL_IN] = 0,
43 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
44 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
45 },
46 .underflow = {
47 [NF_INET_LOCAL_IN] = 0,
48 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
49 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
50 },
51 },
52 .entries = {
53 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
54 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
55 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
56 },
57 .term = IPT_ERROR_INIT, /* ERROR */
58};
59
60static struct xt_table security_table = {
61 .name = "security",
62 .valid_hooks = SECURITY_VALID_HOOKS,
63 .lock = __RW_LOCK_UNLOCKED(security_table.lock),
64 .me = THIS_MODULE,
65 .af = AF_INET,
66};
67
68static unsigned int
69ipt_local_in_hook(unsigned int hook,
70 struct sk_buff *skb,
71 const struct net_device *in,
72 const struct net_device *out,
73 int (*okfn)(struct sk_buff *))
74{
75 return ipt_do_table(skb, hook, in, out,
76 nf_local_in_net(in, out)->ipv4.iptable_security);
77}
78
79static unsigned int
80ipt_forward_hook(unsigned int hook,
81 struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out,
84 int (*okfn)(struct sk_buff *))
85{
86 return ipt_do_table(skb, hook, in, out,
87 nf_forward_net(in, out)->ipv4.iptable_security);
88}
89
90static unsigned int
91ipt_local_out_hook(unsigned int hook,
92 struct sk_buff *skb,
93 const struct net_device *in,
94 const struct net_device *out,
95 int (*okfn)(struct sk_buff *))
96{
97 /* Somebody is playing with raw sockets. */
98 if (skb->len < sizeof(struct iphdr)
99 || ip_hdrlen(skb) < sizeof(struct iphdr)) {
100 if (net_ratelimit())
101 printk(KERN_INFO "iptable_security: ignoring short "
102 "SOCK_RAW packet.\n");
103 return NF_ACCEPT;
104 }
105 return ipt_do_table(skb, hook, in, out,
106 nf_local_out_net(in, out)->ipv4.iptable_security);
107}
108
109static struct nf_hook_ops ipt_ops[] __read_mostly = {
110 {
111 .hook = ipt_local_in_hook,
112 .owner = THIS_MODULE,
113 .pf = PF_INET,
114 .hooknum = NF_INET_LOCAL_IN,
115 .priority = NF_IP_PRI_SECURITY,
116 },
117 {
118 .hook = ipt_forward_hook,
119 .owner = THIS_MODULE,
120 .pf = PF_INET,
121 .hooknum = NF_INET_FORWARD,
122 .priority = NF_IP_PRI_SECURITY,
123 },
124 {
125 .hook = ipt_local_out_hook,
126 .owner = THIS_MODULE,
127 .pf = PF_INET,
128 .hooknum = NF_INET_LOCAL_OUT,
129 .priority = NF_IP_PRI_SECURITY,
130 },
131};
132
133static int __net_init iptable_security_net_init(struct net *net)
134{
135 net->ipv4.iptable_security =
136 ipt_register_table(net, &security_table, &initial_table.repl);
137
138 if (IS_ERR(net->ipv4.iptable_security))
139 return PTR_ERR(net->ipv4.iptable_security);
140
141 return 0;
142}
143
144static void __net_exit iptable_security_net_exit(struct net *net)
145{
146 ipt_unregister_table(net->ipv4.iptable_security);
147}
148
149static struct pernet_operations iptable_security_net_ops = {
150 .init = iptable_security_net_init,
151 .exit = iptable_security_net_exit,
152};
153
154static int __init iptable_security_init(void)
155{
156 int ret;
157
158 ret = register_pernet_subsys(&iptable_security_net_ops);
159 if (ret < 0)
160 return ret;
161
162 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
163 if (ret < 0)
164 goto cleanup_table;
165
166 return ret;
167
168cleanup_table:
169 unregister_pernet_subsys(&iptable_security_net_ops);
170 return ret;
171}
172
173static void __exit iptable_security_fini(void)
174{
175 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops));
176 unregister_pernet_subsys(&iptable_security_net_ops);
177}
178
179module_init(iptable_security_init);
180module_exit(iptable_security_fini);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 211189eb2b67..76ca1f2421eb 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -8,7 +8,7 @@
8 * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> 8 * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9 * by Henrik Nordstrom <hno@marasystems.com> 9 * by Henrik Nordstrom <hno@marasystems.com>
10 * 10 *
11 * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> 11 * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
12 * 12 *
13 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as 14 * it under the terms of the GNU General Public License version 2 as
@@ -94,6 +94,12 @@ connsecmark_tg_check(const char *tablename, const void *entry,
94{ 94{
95 const struct xt_connsecmark_target_info *info = targinfo; 95 const struct xt_connsecmark_target_info *info = targinfo;
96 96
97 if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) {
98 printk(KERN_INFO PFX "target only valid in the \'mangle\' "
99 "or \'security\' tables, not \'%s\'.\n", tablename);
100 return false;
101 }
102
97 switch (info->mode) { 103 switch (info->mode) {
98 case CONNSECMARK_SAVE: 104 case CONNSECMARK_SAVE:
99 case CONNSECMARK_RESTORE: 105 case CONNSECMARK_RESTORE:
@@ -126,7 +132,6 @@ static struct xt_target connsecmark_tg_reg[] __read_mostly = {
126 .destroy = connsecmark_tg_destroy, 132 .destroy = connsecmark_tg_destroy,
127 .target = connsecmark_tg, 133 .target = connsecmark_tg,
128 .targetsize = sizeof(struct xt_connsecmark_target_info), 134 .targetsize = sizeof(struct xt_connsecmark_target_info),
129 .table = "mangle",
130 .me = THIS_MODULE, 135 .me = THIS_MODULE,
131 }, 136 },
132 { 137 {
@@ -136,7 +141,6 @@ static struct xt_target connsecmark_tg_reg[] __read_mostly = {
136 .destroy = connsecmark_tg_destroy, 141 .destroy = connsecmark_tg_destroy,
137 .target = connsecmark_tg, 142 .target = connsecmark_tg,
138 .targetsize = sizeof(struct xt_connsecmark_target_info), 143 .targetsize = sizeof(struct xt_connsecmark_target_info),
139 .table = "mangle",
140 .me = THIS_MODULE, 144 .me = THIS_MODULE,
141 }, 145 },
142}; 146};
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index c0284856ccd4..94f87ee7552b 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -5,7 +5,7 @@
5 * Based on the nfmark match by: 5 * Based on the nfmark match by:
6 * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> 6 * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
7 * 7 *
8 * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> 8 * (C) 2006,2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -89,6 +89,12 @@ secmark_tg_check(const char *tablename, const void *entry,
89{ 89{
90 struct xt_secmark_target_info *info = targinfo; 90 struct xt_secmark_target_info *info = targinfo;
91 91
92 if (strcmp(tablename, "mangle") && strcmp(tablename, "security")) {
93 printk(KERN_INFO PFX "target only valid in the \'mangle\' "
94 "or \'security\' tables, not \'%s\'.\n", tablename);
95 return false;
96 }
97
92 if (mode && mode != info->mode) { 98 if (mode && mode != info->mode) {
93 printk(KERN_INFO PFX "mode already set to %hu cannot mix with " 99 printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
94 "rules for mode %hu\n", mode, info->mode); 100 "rules for mode %hu\n", mode, info->mode);
@@ -127,7 +133,6 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
127 .destroy = secmark_tg_destroy, 133 .destroy = secmark_tg_destroy,
128 .target = secmark_tg, 134 .target = secmark_tg,
129 .targetsize = sizeof(struct xt_secmark_target_info), 135 .targetsize = sizeof(struct xt_secmark_target_info),
130 .table = "mangle",
131 .me = THIS_MODULE, 136 .me = THIS_MODULE,
132 }, 137 },
133 { 138 {
@@ -137,7 +142,6 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
137 .destroy = secmark_tg_destroy, 142 .destroy = secmark_tg_destroy,
138 .target = secmark_tg, 143 .target = secmark_tg,
139 .targetsize = sizeof(struct xt_secmark_target_info), 144 .targetsize = sizeof(struct xt_secmark_target_info),
140 .table = "mangle",
141 .me = THIS_MODULE, 145 .me = THIS_MODULE,
142 }, 146 },
143}; 147};