diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 402 |
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 | ||
3848 | static 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 | |||
3848 | static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, | 3871 | static 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 | ||
4204 | static int selinux_ip_postroute_last_compat(struct sock *sk, | 4231 | static 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 | |||
4270 | static 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) | ||
4280 | static 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 | |||
4290 | static 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 | |||
4351 | static 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 | } |
4281 | out: | 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 | ||
4285 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | 4382 | static 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; |
4325 | out: | ||
4326 | return err ? NF_DROP : NF_ACCEPT; | ||
4327 | } | 4460 | } |
4328 | 4461 | ||
4329 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, | 4462 | static 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 | 4472 | static unsigned int selinux_ipv6_postroute(unsigned int hooknum, | |
4340 | static 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 | ||
5336 | static struct nf_hook_ops selinux_ipv4_op = { | 5467 | static 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 | ||
5346 | static struct nf_hook_ops selinux_ipv6_op = { | 5486 | static 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 = { | |||
5356 | static int __init selinux_nf_ip_init(void) | 5505 | static 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 | ||
5377 | out: | 5531 | out: |
@@ -5383,11 +5537,15 @@ __initcall(selinux_nf_ip_init); | |||
5383 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5537 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5384 | static void selinux_nf_ip_exit(void) | 5538 | static 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 |