aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2008-01-29 08:49:27 -0500
committerJames Morris <jmorris@namei.org>2008-01-29 16:17:30 -0500
commiteffad8df44261031a882e1a895415f7186a5098e (patch)
tree42c04b3247ede13077546e13f82fe3da83ce7b90 /security/selinux
parent13541b3adad2dc2f56761c5193c2b88db3597f0e (diff)
SELinux: Add network ingress and egress control permission checks
This patch implements packet ingress/egress controls for SELinux which allow SELinux security policy to control the flow of all IPv4 and IPv6 packets into and out of the system. Currently SELinux does not have proper control over forwarded packets and this patch corrects this problem. Special thanks to Venkat Yekkirala <vyekkirala@trustedcs.com> whose earlier work on this topic eventually led to this patch. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c402
1 files changed, 280 insertions, 122 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c90e865a8603..b3c064744d32 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,8 +12,8 @@
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 15 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com> 16 * Paul Moore <paul.moore@hp.com>
17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. 17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
18 * Yuichi Nakamura <ynakam@hitachisoft.jp> 18 * Yuichi Nakamura <ynakam@hitachisoft.jp>
19 * 19 *
@@ -3845,6 +3845,29 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3845 return 0; 3845 return 0;
3846} 3846}
3847 3847
3848static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3849 u32 peer_sid,
3850 struct avc_audit_data *ad)
3851{
3852 int err;
3853 u32 if_sid;
3854 u32 node_sid;
3855
3856 err = sel_netif_sid(ifindex, &if_sid);
3857 if (err)
3858 return err;
3859 err = avc_has_perm(peer_sid, if_sid,
3860 SECCLASS_NETIF, NETIF__INGRESS, ad);
3861 if (err)
3862 return err;
3863
3864 err = sel_netnode_sid(addrp, family, &node_sid);
3865 if (err)
3866 return err;
3867 return avc_has_perm(peer_sid, node_sid,
3868 SECCLASS_NODE, NODE__RECVFROM, ad);
3869}
3870
3848static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, 3871static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3849 struct sk_buff *skb, 3872 struct sk_buff *skb,
3850 struct avc_audit_data *ad, 3873 struct avc_audit_data *ad,
@@ -3972,23 +3995,27 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3972 return selinux_sock_rcv_skb_compat(sk, skb, &ad, 3995 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3973 family, addrp); 3996 family, addrp);
3974 3997
3975 if (selinux_secmark_enabled()) {
3976 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3977 PACKET__RECV, &ad);
3978 if (err)
3979 return err;
3980 }
3981
3982 if (netlbl_enabled() || selinux_xfrm_enabled()) { 3998 if (netlbl_enabled() || selinux_xfrm_enabled()) {
3983 u32 peer_sid; 3999 u32 peer_sid;
3984 4000
3985 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4001 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
3986 if (err) 4002 if (err)
3987 return err; 4003 return err;
4004 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4005 peer_sid, &ad);
4006 if (err)
4007 return err;
3988 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, 4008 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
3989 PEER__RECV, &ad); 4009 PEER__RECV, &ad);
3990 } 4010 }
3991 4011
4012 if (selinux_secmark_enabled()) {
4013 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4014 PACKET__RECV, &ad);
4015 if (err)
4016 return err;
4017 }
4018
3992 return err; 4019 return err;
3993} 4020}
3994 4021
@@ -4201,151 +4228,255 @@ out:
4201 4228
4202#ifdef CONFIG_NETFILTER 4229#ifdef CONFIG_NETFILTER
4203 4230
4204static int selinux_ip_postroute_last_compat(struct sock *sk, 4231static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4205 struct net_device *dev, 4232 u16 family)
4206 struct avc_audit_data *ad,
4207 u16 family,
4208 char *addrp)
4209{ 4233{
4210 int err = 0; 4234 char *addrp;
4211 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 4235 u32 peer_sid;
4212 struct socket *sock; 4236 struct avc_audit_data ad;
4213 struct inode *inode; 4237 u8 secmark_active;
4214 struct inode_security_struct *isec; 4238 u8 peerlbl_active;
4215 4239
4216 sock = sk->sk_socket; 4240 if (!selinux_policycap_netpeer)
4217 if (!sock) 4241 return NF_ACCEPT;
4218 goto out;
4219 4242
4220 inode = SOCK_INODE(sock); 4243 secmark_active = selinux_secmark_enabled();
4221 if (!inode) 4244 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4222 goto out; 4245 if (!secmark_active && !peerlbl_active)
4246 return NF_ACCEPT;
4223 4247
4224 isec = inode->i_security; 4248 AVC_AUDIT_DATA_INIT(&ad, NET);
4225 4249 ad.u.net.netif = ifindex;
4226 err = sel_netif_sid(dev->ifindex, &if_sid); 4250 ad.u.net.family = family;
4227 if (err) 4251 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4228 goto out; 4252 return NF_DROP;
4253
4254 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4255 return NF_DROP;
4256
4257 if (peerlbl_active)
4258 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4259 peer_sid, &ad) != 0)
4260 return NF_DROP;
4261
4262 if (secmark_active)
4263 if (avc_has_perm(peer_sid, skb->secmark,
4264 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4265 return NF_DROP;
4266
4267 return NF_ACCEPT;
4268}
4269
4270static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4271 struct sk_buff *skb,
4272 const struct net_device *in,
4273 const struct net_device *out,
4274 int (*okfn)(struct sk_buff *))
4275{
4276 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4277}
4278
4279#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4280static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4281 struct sk_buff *skb,
4282 const struct net_device *in,
4283 const struct net_device *out,
4284 int (*okfn)(struct sk_buff *))
4285{
4286 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4287}
4288#endif /* IPV6 */
4289
4290static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4291 int ifindex,
4292 struct avc_audit_data *ad,
4293 u16 family, char *addrp)
4294{
4295 int err;
4296 struct sk_security_struct *sksec = sk->sk_security;
4297 u16 sk_class;
4298 u32 netif_perm, node_perm, send_perm;
4299 u32 port_sid, node_sid, if_sid, sk_sid;
4300
4301 sk_sid = sksec->sid;
4302 sk_class = sksec->sclass;
4229 4303
4230 switch (isec->sclass) { 4304 switch (sk_class) {
4231 case SECCLASS_UDP_SOCKET: 4305 case SECCLASS_UDP_SOCKET:
4232 netif_perm = NETIF__UDP_SEND; 4306 netif_perm = NETIF__UDP_SEND;
4233 node_perm = NODE__UDP_SEND; 4307 node_perm = NODE__UDP_SEND;
4234 send_perm = UDP_SOCKET__SEND_MSG; 4308 send_perm = UDP_SOCKET__SEND_MSG;
4235 break; 4309 break;
4236
4237 case SECCLASS_TCP_SOCKET: 4310 case SECCLASS_TCP_SOCKET:
4238 netif_perm = NETIF__TCP_SEND; 4311 netif_perm = NETIF__TCP_SEND;
4239 node_perm = NODE__TCP_SEND; 4312 node_perm = NODE__TCP_SEND;
4240 send_perm = TCP_SOCKET__SEND_MSG; 4313 send_perm = TCP_SOCKET__SEND_MSG;
4241 break; 4314 break;
4242
4243 case SECCLASS_DCCP_SOCKET: 4315 case SECCLASS_DCCP_SOCKET:
4244 netif_perm = NETIF__DCCP_SEND; 4316 netif_perm = NETIF__DCCP_SEND;
4245 node_perm = NODE__DCCP_SEND; 4317 node_perm = NODE__DCCP_SEND;
4246 send_perm = DCCP_SOCKET__SEND_MSG; 4318 send_perm = DCCP_SOCKET__SEND_MSG;
4247 break; 4319 break;
4248
4249 default: 4320 default:
4250 netif_perm = NETIF__RAWIP_SEND; 4321 netif_perm = NETIF__RAWIP_SEND;
4251 node_perm = NODE__RAWIP_SEND; 4322 node_perm = NODE__RAWIP_SEND;
4323 send_perm = 0;
4252 break; 4324 break;
4253 } 4325 }
4254 4326
4255 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad); 4327 err = sel_netif_sid(ifindex, &if_sid);
4256 if (err) 4328 if (err)
4257 goto out; 4329 return err;
4330 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4331 return err;
4258 4332
4259 err = sel_netnode_sid(addrp, family, &node_sid); 4333 err = sel_netnode_sid(addrp, family, &node_sid);
4260 if (err) 4334 if (err)
4261 goto out; 4335 return err;
4262 4336 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4263 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
4264 if (err) 4337 if (err)
4265 goto out; 4338 return err;
4266 4339
4267 if (send_perm) { 4340 if (send_perm != 0)
4268 u32 port_sid; 4341 return 0;
4269 4342
4270 err = security_port_sid(sk->sk_family, 4343 err = security_port_sid(sk->sk_family, sk->sk_type,
4271 sk->sk_type, 4344 sk->sk_protocol, ntohs(ad->u.net.dport),
4272 sk->sk_protocol, 4345 &port_sid);
4273 ntohs(ad->u.net.dport), 4346 if (err)
4274 &port_sid); 4347 return err;
4275 if (err) 4348 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
4276 goto out; 4349}
4350
4351static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4352 int ifindex,
4353 struct avc_audit_data *ad,
4354 u16 family,
4355 char *addrp,
4356 u8 proto)
4357{
4358 struct sock *sk = skb->sk;
4359 struct sk_security_struct *sksec;
4277 4360
4278 err = avc_has_perm(isec->sid, port_sid, isec->sclass, 4361 if (sk == NULL)
4279 send_perm, ad); 4362 return NF_ACCEPT;
4363 sksec = sk->sk_security;
4364
4365 if (selinux_compat_net) {
4366 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4367 ad, family, addrp))
4368 return NF_DROP;
4369 } else {
4370 if (avc_has_perm(sksec->sid, skb->secmark,
4371 SECCLASS_PACKET, PACKET__SEND, ad))
4372 return NF_DROP;
4280 } 4373 }
4281out: 4374
4282 return err; 4375 if (selinux_policycap_netpeer)
4376 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4377 return NF_DROP;
4378
4379 return NF_ACCEPT;
4283} 4380}
4284 4381
4285static unsigned int selinux_ip_postroute_last(unsigned int hooknum, 4382static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4286 struct sk_buff *skb, 4383 u16 family)
4287 const struct net_device *in,
4288 const struct net_device *out,
4289 int (*okfn)(struct sk_buff *),
4290 u16 family)
4291{ 4384{
4292 char *addrp; 4385 u32 secmark_perm;
4293 int err = 0; 4386 u32 peer_sid;
4294 struct sock *sk; 4387 struct sock *sk;
4295 struct avc_audit_data ad; 4388 struct avc_audit_data ad;
4296 struct net_device *dev = (struct net_device *)out; 4389 char *addrp;
4297 struct sk_security_struct *sksec;
4298 u8 proto; 4390 u8 proto;
4299 4391 u8 secmark_active;
4300 sk = skb->sk; 4392 u8 peerlbl_active;
4301 if (!sk)
4302 goto out;
4303
4304 sksec = sk->sk_security;
4305 4393
4306 AVC_AUDIT_DATA_INIT(&ad, NET); 4394 AVC_AUDIT_DATA_INIT(&ad, NET);
4307 ad.u.net.netif = dev->ifindex; 4395 ad.u.net.netif = ifindex;
4308 ad.u.net.family = family; 4396 ad.u.net.family = family;
4397 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4398 return NF_DROP;
4309 4399
4310 err = selinux_parse_skb(skb, &ad, &addrp, 0, &proto); 4400 /* If any sort of compatibility mode is enabled then handoff processing
4311 if (err) 4401 * to the selinux_ip_postroute_compat() function to deal with the
4312 goto out; 4402 * special handling. We do this in an attempt to keep this function
4313 4403 * as fast and as clean as possible. */
4314 if (selinux_compat_net) 4404 if (selinux_compat_net || !selinux_policycap_netpeer)
4315 err = selinux_ip_postroute_last_compat(sk, dev, &ad, 4405 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4316 family, addrp); 4406 family, addrp, proto);
4317 else 4407
4318 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, 4408 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4319 PACKET__SEND, &ad); 4409 * packet transformation so allow the packet to pass without any checks
4410 * since we'll have another chance to perform access control checks
4411 * when the packet is on it's final way out.
4412 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4413 * is NULL, in this case go ahead and apply access control. */
4414 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4415 return NF_ACCEPT;
4416
4417 secmark_active = selinux_secmark_enabled();
4418 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4419 if (!secmark_active && !peerlbl_active)
4420 return NF_ACCEPT;
4421
4422 /* if the packet is locally generated (skb->sk != NULL) then use the
4423 * socket's label as the peer label, otherwise the packet is being
4424 * forwarded through this system and we need to fetch the peer label
4425 * directly from the packet */
4426 sk = skb->sk;
4427 if (sk) {
4428 struct sk_security_struct *sksec = sk->sk_security;
4429 peer_sid = sksec->sid;
4430 secmark_perm = PACKET__SEND;
4431 } else {
4432 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4433 return NF_DROP;
4434 secmark_perm = PACKET__FORWARD_OUT;
4435 }
4320 4436
4321 if (err) 4437 if (secmark_active)
4322 goto out; 4438 if (avc_has_perm(peer_sid, skb->secmark,
4439 SECCLASS_PACKET, secmark_perm, &ad))
4440 return NF_DROP;
4441
4442 if (peerlbl_active) {
4443 u32 if_sid;
4444 u32 node_sid;
4445
4446 if (sel_netif_sid(ifindex, &if_sid))
4447 return NF_DROP;
4448 if (avc_has_perm(peer_sid, if_sid,
4449 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4450 return NF_DROP;
4451
4452 if (sel_netnode_sid(addrp, family, &node_sid))
4453 return NF_DROP;
4454 if (avc_has_perm(peer_sid, node_sid,
4455 SECCLASS_NODE, NODE__SENDTO, &ad))
4456 return NF_DROP;
4457 }
4323 4458
4324 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); 4459 return NF_ACCEPT;
4325out:
4326 return err ? NF_DROP : NF_ACCEPT;
4327} 4460}
4328 4461
4329static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, 4462static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4330 struct sk_buff *skb, 4463 struct sk_buff *skb,
4331 const struct net_device *in, 4464 const struct net_device *in,
4332 const struct net_device *out, 4465 const struct net_device *out,
4333 int (*okfn)(struct sk_buff *)) 4466 int (*okfn)(struct sk_buff *))
4334{ 4467{
4335 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); 4468 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
4336} 4469}
4337 4470
4338#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 4471#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4339 4472static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4340static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, 4473 struct sk_buff *skb,
4341 struct sk_buff *skb, 4474 const struct net_device *in,
4342 const struct net_device *in, 4475 const struct net_device *out,
4343 const struct net_device *out, 4476 int (*okfn)(struct sk_buff *))
4344 int (*okfn)(struct sk_buff *))
4345{ 4477{
4346 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); 4478 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
4347} 4479}
4348
4349#endif /* IPV6 */ 4480#endif /* IPV6 */
4350 4481
4351#endif /* CONFIG_NETFILTER */ 4482#endif /* CONFIG_NETFILTER */
@@ -5333,22 +5464,40 @@ security_initcall(selinux_init);
5333 5464
5334#if defined(CONFIG_NETFILTER) 5465#if defined(CONFIG_NETFILTER)
5335 5466
5336static struct nf_hook_ops selinux_ipv4_op = { 5467static struct nf_hook_ops selinux_ipv4_ops[] = {
5337 .hook = selinux_ipv4_postroute_last, 5468 {
5338 .owner = THIS_MODULE, 5469 .hook = selinux_ipv4_postroute,
5339 .pf = PF_INET, 5470 .owner = THIS_MODULE,
5340 .hooknum = NF_INET_POST_ROUTING, 5471 .pf = PF_INET,
5341 .priority = NF_IP_PRI_SELINUX_LAST, 5472 .hooknum = NF_INET_POST_ROUTING,
5473 .priority = NF_IP_PRI_SELINUX_LAST,
5474 },
5475 {
5476 .hook = selinux_ipv4_forward,
5477 .owner = THIS_MODULE,
5478 .pf = PF_INET,
5479 .hooknum = NF_INET_FORWARD,
5480 .priority = NF_IP_PRI_SELINUX_FIRST,
5481 }
5342}; 5482};
5343 5483
5344#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5484#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5345 5485
5346static struct nf_hook_ops selinux_ipv6_op = { 5486static struct nf_hook_ops selinux_ipv6_ops[] = {
5347 .hook = selinux_ipv6_postroute_last, 5487 {
5348 .owner = THIS_MODULE, 5488 .hook = selinux_ipv6_postroute,
5349 .pf = PF_INET6, 5489 .owner = THIS_MODULE,
5350 .hooknum = NF_INET_POST_ROUTING, 5490 .pf = PF_INET6,
5351 .priority = NF_IP6_PRI_SELINUX_LAST, 5491 .hooknum = NF_INET_POST_ROUTING,
5492 .priority = NF_IP6_PRI_SELINUX_LAST,
5493 },
5494 {
5495 .hook = selinux_ipv6_forward,
5496 .owner = THIS_MODULE,
5497 .pf = PF_INET6,
5498 .hooknum = NF_INET_FORWARD,
5499 .priority = NF_IP6_PRI_SELINUX_FIRST,
5500 }
5352}; 5501};
5353 5502
5354#endif /* IPV6 */ 5503#endif /* IPV6 */
@@ -5356,22 +5505,27 @@ static struct nf_hook_ops selinux_ipv6_op = {
5356static int __init selinux_nf_ip_init(void) 5505static int __init selinux_nf_ip_init(void)
5357{ 5506{
5358 int err = 0; 5507 int err = 0;
5508 u32 iter;
5359 5509
5360 if (!selinux_enabled) 5510 if (!selinux_enabled)
5361 goto out; 5511 goto out;
5362 5512
5363 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5513 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5364 5514
5365 err = nf_register_hook(&selinux_ipv4_op); 5515 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5366 if (err) 5516 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5367 panic("SELinux: nf_register_hook for IPv4: error %d\n", err); 5517 if (err)
5518 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5519 err);
5520 }
5368 5521
5369#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5522#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5370 5523 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5371 err = nf_register_hook(&selinux_ipv6_op); 5524 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5372 if (err) 5525 if (err)
5373 panic("SELinux: nf_register_hook for IPv6: error %d\n", err); 5526 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5374 5527 err);
5528 }
5375#endif /* IPV6 */ 5529#endif /* IPV6 */
5376 5530
5377out: 5531out:
@@ -5383,11 +5537,15 @@ __initcall(selinux_nf_ip_init);
5383#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5537#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5384static void selinux_nf_ip_exit(void) 5538static void selinux_nf_ip_exit(void)
5385{ 5539{
5540 u32 iter;
5541
5386 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5542 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5387 5543
5388 nf_unregister_hook(&selinux_ipv4_op); 5544 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5545 nf_unregister_hook(&selinux_ipv4_ops[iter]);
5389#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5546#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5390 nf_unregister_hook(&selinux_ipv6_op); 5547 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5548 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5391#endif /* IPV6 */ 5549#endif /* IPV6 */
5392} 5550}
5393#endif 5551#endif