diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /security/selinux/hooks.c | |
parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 390 |
1 files changed, 248 insertions, 142 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 63f131fc42e4..3e3fde7c1d2b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/ptrace.h> | 28 | #include <linux/tracehook.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/security.h> | 31 | #include <linux/security.h> |
@@ -75,6 +75,7 @@ | |||
75 | #include <linux/string.h> | 75 | #include <linux/string.h> |
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | ||
78 | 79 | ||
79 | #include "avc.h" | 80 | #include "avc.h" |
80 | #include "objsec.h" | 81 | #include "objsec.h" |
@@ -291,6 +292,7 @@ static void sk_free_security(struct sock *sk) | |||
291 | struct sk_security_struct *ssec = sk->sk_security; | 292 | struct sk_security_struct *ssec = sk->sk_security; |
292 | 293 | ||
293 | sk->sk_security = NULL; | 294 | sk->sk_security = NULL; |
295 | selinux_netlbl_sk_security_free(ssec); | ||
294 | kfree(ssec); | 296 | kfree(ssec); |
295 | } | 297 | } |
296 | 298 | ||
@@ -324,7 +326,7 @@ enum { | |||
324 | Opt_rootcontext = 4, | 326 | Opt_rootcontext = 4, |
325 | }; | 327 | }; |
326 | 328 | ||
327 | static match_table_t tokens = { | 329 | static const match_table_t tokens = { |
328 | {Opt_context, CONTEXT_STR "%s"}, | 330 | {Opt_context, CONTEXT_STR "%s"}, |
329 | {Opt_fscontext, FSCONTEXT_STR "%s"}, | 331 | {Opt_fscontext, FSCONTEXT_STR "%s"}, |
330 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, | 332 | {Opt_defcontext, DEFCONTEXT_STR "%s"}, |
@@ -957,7 +959,8 @@ out_err: | |||
957 | return rc; | 959 | return rc; |
958 | } | 960 | } |
959 | 961 | ||
960 | void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) | 962 | static void selinux_write_opts(struct seq_file *m, |
963 | struct security_mnt_opts *opts) | ||
961 | { | 964 | { |
962 | int i; | 965 | int i; |
963 | char *prefix; | 966 | char *prefix; |
@@ -998,8 +1001,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) | |||
998 | int rc; | 1001 | int rc; |
999 | 1002 | ||
1000 | rc = selinux_get_mnt_opts(sb, &opts); | 1003 | rc = selinux_get_mnt_opts(sb, &opts); |
1001 | if (rc) | 1004 | if (rc) { |
1005 | /* before policy load we may get EINVAL, don't show anything */ | ||
1006 | if (rc == -EINVAL) | ||
1007 | rc = 0; | ||
1002 | return rc; | 1008 | return rc; |
1009 | } | ||
1003 | 1010 | ||
1004 | selinux_write_opts(m, &opts); | 1011 | selinux_write_opts(m, &opts); |
1005 | 1012 | ||
@@ -1286,7 +1293,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1286 | /* Default to the fs superblock SID. */ | 1293 | /* Default to the fs superblock SID. */ |
1287 | isec->sid = sbsec->sid; | 1294 | isec->sid = sbsec->sid; |
1288 | 1295 | ||
1289 | if (sbsec->proc) { | 1296 | if (sbsec->proc && !S_ISLNK(inode->i_mode)) { |
1290 | struct proc_inode *proci = PROC_I(inode); | 1297 | struct proc_inode *proci = PROC_I(inode); |
1291 | if (proci->pde) { | 1298 | if (proci->pde) { |
1292 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1299 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
@@ -1734,24 +1741,34 @@ static inline u32 file_to_av(struct file *file) | |||
1734 | 1741 | ||
1735 | /* Hook functions begin here. */ | 1742 | /* Hook functions begin here. */ |
1736 | 1743 | ||
1737 | static int selinux_ptrace(struct task_struct *parent, | 1744 | static int selinux_ptrace_may_access(struct task_struct *child, |
1738 | struct task_struct *child, | 1745 | unsigned int mode) |
1739 | unsigned int mode) | ||
1740 | { | 1746 | { |
1741 | int rc; | 1747 | int rc; |
1742 | 1748 | ||
1743 | rc = secondary_ops->ptrace(parent, child, mode); | 1749 | rc = secondary_ops->ptrace_may_access(child, mode); |
1744 | if (rc) | 1750 | if (rc) |
1745 | return rc; | 1751 | return rc; |
1746 | 1752 | ||
1747 | if (mode == PTRACE_MODE_READ) { | 1753 | if (mode == PTRACE_MODE_READ) { |
1748 | struct task_security_struct *tsec = parent->security; | 1754 | struct task_security_struct *tsec = current->security; |
1749 | struct task_security_struct *csec = child->security; | 1755 | struct task_security_struct *csec = child->security; |
1750 | return avc_has_perm(tsec->sid, csec->sid, | 1756 | return avc_has_perm(tsec->sid, csec->sid, |
1751 | SECCLASS_FILE, FILE__READ, NULL); | 1757 | SECCLASS_FILE, FILE__READ, NULL); |
1752 | } | 1758 | } |
1753 | 1759 | ||
1754 | return task_has_perm(parent, child, PROCESS__PTRACE); | 1760 | return task_has_perm(current, child, PROCESS__PTRACE); |
1761 | } | ||
1762 | |||
1763 | static int selinux_ptrace_traceme(struct task_struct *parent) | ||
1764 | { | ||
1765 | int rc; | ||
1766 | |||
1767 | rc = secondary_ops->ptrace_traceme(parent); | ||
1768 | if (rc) | ||
1769 | return rc; | ||
1770 | |||
1771 | return task_has_perm(parent, current, PROCESS__PTRACE); | ||
1755 | } | 1772 | } |
1756 | 1773 | ||
1757 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | 1774 | static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, |
@@ -1971,22 +1988,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
1971 | return __vm_enough_memory(mm, pages, cap_sys_admin); | 1988 | return __vm_enough_memory(mm, pages, cap_sys_admin); |
1972 | } | 1989 | } |
1973 | 1990 | ||
1974 | /** | ||
1975 | * task_tracer_task - return the task that is tracing the given task | ||
1976 | * @task: task to consider | ||
1977 | * | ||
1978 | * Returns NULL if noone is tracing @task, or the &struct task_struct | ||
1979 | * pointer to its tracer. | ||
1980 | * | ||
1981 | * Must be called under rcu_read_lock(). | ||
1982 | */ | ||
1983 | static struct task_struct *task_tracer_task(struct task_struct *task) | ||
1984 | { | ||
1985 | if (task->ptrace & PT_PTRACED) | ||
1986 | return rcu_dereference(task->parent); | ||
1987 | return NULL; | ||
1988 | } | ||
1989 | |||
1990 | /* binprm security operations */ | 1991 | /* binprm security operations */ |
1991 | 1992 | ||
1992 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) | 1993 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) |
@@ -2122,7 +2123,6 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2122 | long j = -1; | 2123 | long j = -1; |
2123 | int drop_tty = 0; | 2124 | int drop_tty = 0; |
2124 | 2125 | ||
2125 | mutex_lock(&tty_mutex); | ||
2126 | tty = get_current_tty(); | 2126 | tty = get_current_tty(); |
2127 | if (tty) { | 2127 | if (tty) { |
2128 | file_list_lock(); | 2128 | file_list_lock(); |
@@ -2140,8 +2140,8 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2140 | } | 2140 | } |
2141 | } | 2141 | } |
2142 | file_list_unlock(); | 2142 | file_list_unlock(); |
2143 | tty_kref_put(tty); | ||
2143 | } | 2144 | } |
2144 | mutex_unlock(&tty_mutex); | ||
2145 | /* Reset controlling tty. */ | 2145 | /* Reset controlling tty. */ |
2146 | if (drop_tty) | 2146 | if (drop_tty) |
2147 | no_tty(); | 2147 | no_tty(); |
@@ -2238,7 +2238,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2238 | u32 ptsid = 0; | 2238 | u32 ptsid = 0; |
2239 | 2239 | ||
2240 | rcu_read_lock(); | 2240 | rcu_read_lock(); |
2241 | tracer = task_tracer_task(current); | 2241 | tracer = tracehook_tracer_task(current); |
2242 | if (likely(tracer != NULL)) { | 2242 | if (likely(tracer != NULL)) { |
2243 | sec = tracer->security; | 2243 | sec = tracer->security; |
2244 | ptsid = sec->sid; | 2244 | ptsid = sec->sid; |
@@ -2323,13 +2323,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) | |||
2323 | initrlim = init_task.signal->rlim+i; | 2323 | initrlim = init_task.signal->rlim+i; |
2324 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2324 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2325 | } | 2325 | } |
2326 | if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { | 2326 | update_rlimit_cpu(rlim->rlim_cur); |
2327 | /* | ||
2328 | * This will cause RLIMIT_CPU calculations | ||
2329 | * to be refigured. | ||
2330 | */ | ||
2331 | current->it_prof_expires = jiffies_to_cputime(1); | ||
2332 | } | ||
2333 | } | 2327 | } |
2334 | 2328 | ||
2335 | /* Wake up the parent if it is waiting so that it can | 2329 | /* Wake up the parent if it is waiting so that it can |
@@ -2640,12 +2634,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2640 | return dentry_has_perm(current, NULL, dentry, FILE__READ); | 2634 | return dentry_has_perm(current, NULL, dentry, FILE__READ); |
2641 | } | 2635 | } |
2642 | 2636 | ||
2643 | static int selinux_inode_permission(struct inode *inode, int mask, | 2637 | static int selinux_inode_permission(struct inode *inode, int mask) |
2644 | struct nameidata *nd) | ||
2645 | { | 2638 | { |
2646 | int rc; | 2639 | int rc; |
2647 | 2640 | ||
2648 | rc = secondary_ops->inode_permission(inode, mask, nd); | 2641 | rc = secondary_ops->inode_permission(inode, mask); |
2649 | if (rc) | 2642 | if (rc) |
2650 | return rc; | 2643 | return rc; |
2651 | 2644 | ||
@@ -3551,38 +3544,44 @@ out: | |||
3551 | #endif /* IPV6 */ | 3544 | #endif /* IPV6 */ |
3552 | 3545 | ||
3553 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3546 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, |
3554 | char **addrp, int src, u8 *proto) | 3547 | char **_addrp, int src, u8 *proto) |
3555 | { | 3548 | { |
3556 | int ret = 0; | 3549 | char *addrp; |
3550 | int ret; | ||
3557 | 3551 | ||
3558 | switch (ad->u.net.family) { | 3552 | switch (ad->u.net.family) { |
3559 | case PF_INET: | 3553 | case PF_INET: |
3560 | ret = selinux_parse_skb_ipv4(skb, ad, proto); | 3554 | ret = selinux_parse_skb_ipv4(skb, ad, proto); |
3561 | if (ret || !addrp) | 3555 | if (ret) |
3562 | break; | 3556 | goto parse_error; |
3563 | *addrp = (char *)(src ? &ad->u.net.v4info.saddr : | 3557 | addrp = (char *)(src ? &ad->u.net.v4info.saddr : |
3564 | &ad->u.net.v4info.daddr); | 3558 | &ad->u.net.v4info.daddr); |
3565 | break; | 3559 | goto okay; |
3566 | 3560 | ||
3567 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 3561 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3568 | case PF_INET6: | 3562 | case PF_INET6: |
3569 | ret = selinux_parse_skb_ipv6(skb, ad, proto); | 3563 | ret = selinux_parse_skb_ipv6(skb, ad, proto); |
3570 | if (ret || !addrp) | 3564 | if (ret) |
3571 | break; | 3565 | goto parse_error; |
3572 | *addrp = (char *)(src ? &ad->u.net.v6info.saddr : | 3566 | addrp = (char *)(src ? &ad->u.net.v6info.saddr : |
3573 | &ad->u.net.v6info.daddr); | 3567 | &ad->u.net.v6info.daddr); |
3574 | break; | 3568 | goto okay; |
3575 | #endif /* IPV6 */ | 3569 | #endif /* IPV6 */ |
3576 | default: | 3570 | default: |
3577 | break; | 3571 | addrp = NULL; |
3572 | goto okay; | ||
3578 | } | 3573 | } |
3579 | 3574 | ||
3580 | if (unlikely(ret)) | 3575 | parse_error: |
3581 | printk(KERN_WARNING | 3576 | printk(KERN_WARNING |
3582 | "SELinux: failure in selinux_parse_skb()," | 3577 | "SELinux: failure in selinux_parse_skb()," |
3583 | " unable to parse packet\n"); | 3578 | " unable to parse packet\n"); |
3584 | |||
3585 | return ret; | 3579 | return ret; |
3580 | |||
3581 | okay: | ||
3582 | if (_addrp) | ||
3583 | *_addrp = addrp; | ||
3584 | return 0; | ||
3586 | } | 3585 | } |
3587 | 3586 | ||
3588 | /** | 3587 | /** |
@@ -3797,6 +3796,7 @@ out: | |||
3797 | 3796 | ||
3798 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3797 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3799 | { | 3798 | { |
3799 | struct sock *sk = sock->sk; | ||
3800 | struct inode_security_struct *isec; | 3800 | struct inode_security_struct *isec; |
3801 | int err; | 3801 | int err; |
3802 | 3802 | ||
@@ -3810,7 +3810,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3810 | isec = SOCK_INODE(sock)->i_security; | 3810 | isec = SOCK_INODE(sock)->i_security; |
3811 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3811 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
3812 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3812 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
3813 | struct sock *sk = sock->sk; | ||
3814 | struct avc_audit_data ad; | 3813 | struct avc_audit_data ad; |
3815 | struct sockaddr_in *addr4 = NULL; | 3814 | struct sockaddr_in *addr4 = NULL; |
3816 | struct sockaddr_in6 *addr6 = NULL; | 3815 | struct sockaddr_in6 *addr6 = NULL; |
@@ -3844,6 +3843,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3844 | goto out; | 3843 | goto out; |
3845 | } | 3844 | } |
3846 | 3845 | ||
3846 | err = selinux_netlbl_socket_connect(sk, address); | ||
3847 | |||
3847 | out: | 3848 | out: |
3848 | return err; | 3849 | return err; |
3849 | } | 3850 | } |
@@ -4073,20 +4074,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, | |||
4073 | } | 4074 | } |
4074 | 4075 | ||
4075 | static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | 4076 | static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, |
4076 | struct avc_audit_data *ad, | 4077 | u16 family) |
4077 | u16 family, char *addrp) | ||
4078 | { | 4078 | { |
4079 | int err; | 4079 | int err; |
4080 | struct sk_security_struct *sksec = sk->sk_security; | 4080 | struct sk_security_struct *sksec = sk->sk_security; |
4081 | u32 peer_sid; | 4081 | u32 peer_sid; |
4082 | u32 sk_sid = sksec->sid; | 4082 | u32 sk_sid = sksec->sid; |
4083 | struct avc_audit_data ad; | ||
4084 | char *addrp; | ||
4085 | |||
4086 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
4087 | ad.u.net.netif = skb->iif; | ||
4088 | ad.u.net.family = family; | ||
4089 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | ||
4090 | if (err) | ||
4091 | return err; | ||
4083 | 4092 | ||
4084 | if (selinux_compat_net) | 4093 | if (selinux_compat_net) |
4085 | err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, | 4094 | err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad, |
4086 | family, addrp); | 4095 | family, addrp); |
4087 | else | 4096 | else |
4088 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 4097 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, |
4089 | PACKET__RECV, ad); | 4098 | PACKET__RECV, &ad); |
4090 | if (err) | 4099 | if (err) |
4091 | return err; | 4100 | return err; |
4092 | 4101 | ||
@@ -4095,12 +4104,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4095 | if (err) | 4104 | if (err) |
4096 | return err; | 4105 | return err; |
4097 | err = avc_has_perm(sk_sid, peer_sid, | 4106 | err = avc_has_perm(sk_sid, peer_sid, |
4098 | SECCLASS_PEER, PEER__RECV, ad); | 4107 | SECCLASS_PEER, PEER__RECV, &ad); |
4108 | if (err) | ||
4109 | selinux_netlbl_err(skb, err, 0); | ||
4099 | } else { | 4110 | } else { |
4100 | err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); | 4111 | err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); |
4101 | if (err) | 4112 | if (err) |
4102 | return err; | 4113 | return err; |
4103 | err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); | 4114 | err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); |
4104 | } | 4115 | } |
4105 | 4116 | ||
4106 | return err; | 4117 | return err; |
@@ -4114,6 +4125,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4114 | u32 sk_sid = sksec->sid; | 4125 | u32 sk_sid = sksec->sid; |
4115 | struct avc_audit_data ad; | 4126 | struct avc_audit_data ad; |
4116 | char *addrp; | 4127 | char *addrp; |
4128 | u8 secmark_active; | ||
4129 | u8 peerlbl_active; | ||
4117 | 4130 | ||
4118 | if (family != PF_INET && family != PF_INET6) | 4131 | if (family != PF_INET && family != PF_INET6) |
4119 | return 0; | 4132 | return 0; |
@@ -4122,6 +4135,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4122 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 4135 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
4123 | family = PF_INET; | 4136 | family = PF_INET; |
4124 | 4137 | ||
4138 | /* If any sort of compatibility mode is enabled then handoff processing | ||
4139 | * to the selinux_sock_rcv_skb_compat() function to deal with the | ||
4140 | * special handling. We do this in an attempt to keep this function | ||
4141 | * as fast and as clean as possible. */ | ||
4142 | if (selinux_compat_net || !selinux_policycap_netpeer) | ||
4143 | return selinux_sock_rcv_skb_compat(sk, skb, family); | ||
4144 | |||
4145 | secmark_active = selinux_secmark_enabled(); | ||
4146 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); | ||
4147 | if (!secmark_active && !peerlbl_active) | ||
4148 | return 0; | ||
4149 | |||
4125 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4150 | AVC_AUDIT_DATA_INIT(&ad, NET); |
4126 | ad.u.net.netif = skb->iif; | 4151 | ad.u.net.netif = skb->iif; |
4127 | ad.u.net.family = family; | 4152 | ad.u.net.family = family; |
@@ -4129,15 +4154,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4129 | if (err) | 4154 | if (err) |
4130 | return err; | 4155 | return err; |
4131 | 4156 | ||
4132 | /* If any sort of compatibility mode is enabled then handoff processing | 4157 | if (peerlbl_active) { |
4133 | * to the selinux_sock_rcv_skb_compat() function to deal with the | ||
4134 | * special handling. We do this in an attempt to keep this function | ||
4135 | * as fast and as clean as possible. */ | ||
4136 | if (selinux_compat_net || !selinux_policycap_netpeer) | ||
4137 | return selinux_sock_rcv_skb_compat(sk, skb, &ad, | ||
4138 | family, addrp); | ||
4139 | |||
4140 | if (netlbl_enabled() || selinux_xfrm_enabled()) { | ||
4141 | u32 peer_sid; | 4158 | u32 peer_sid; |
4142 | 4159 | ||
4143 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4160 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
@@ -4145,13 +4162,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4145 | return err; | 4162 | return err; |
4146 | err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, | 4163 | err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, |
4147 | peer_sid, &ad); | 4164 | peer_sid, &ad); |
4148 | if (err) | 4165 | if (err) { |
4166 | selinux_netlbl_err(skb, err, 0); | ||
4149 | return err; | 4167 | return err; |
4168 | } | ||
4150 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, | 4169 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, |
4151 | PEER__RECV, &ad); | 4170 | PEER__RECV, &ad); |
4171 | if (err) | ||
4172 | selinux_netlbl_err(skb, err, 0); | ||
4152 | } | 4173 | } |
4153 | 4174 | ||
4154 | if (selinux_secmark_enabled()) { | 4175 | if (secmark_active) { |
4155 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, | 4176 | err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, |
4156 | PACKET__RECV, &ad); | 4177 | PACKET__RECV, &ad); |
4157 | if (err) | 4178 | if (err) |
@@ -4210,10 +4231,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * | |||
4210 | u32 peer_secid = SECSID_NULL; | 4231 | u32 peer_secid = SECSID_NULL; |
4211 | u16 family; | 4232 | u16 family; |
4212 | 4233 | ||
4213 | if (sock) | 4234 | if (skb && skb->protocol == htons(ETH_P_IP)) |
4235 | family = PF_INET; | ||
4236 | else if (skb && skb->protocol == htons(ETH_P_IPV6)) | ||
4237 | family = PF_INET6; | ||
4238 | else if (sock) | ||
4214 | family = sock->sk->sk_family; | 4239 | family = sock->sk->sk_family; |
4215 | else if (skb && skb->sk) | ||
4216 | family = skb->sk->sk_family; | ||
4217 | else | 4240 | else |
4218 | goto out; | 4241 | goto out; |
4219 | 4242 | ||
@@ -4271,8 +4294,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent) | |||
4271 | sk->sk_family == PF_UNIX) | 4294 | sk->sk_family == PF_UNIX) |
4272 | isec->sid = sksec->sid; | 4295 | isec->sid = sksec->sid; |
4273 | sksec->sclass = isec->sclass; | 4296 | sksec->sclass = isec->sclass; |
4274 | |||
4275 | selinux_netlbl_sock_graft(sk, parent); | ||
4276 | } | 4297 | } |
4277 | 4298 | ||
4278 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | 4299 | static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, |
@@ -4280,10 +4301,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
4280 | { | 4301 | { |
4281 | struct sk_security_struct *sksec = sk->sk_security; | 4302 | struct sk_security_struct *sksec = sk->sk_security; |
4282 | int err; | 4303 | int err; |
4304 | u16 family = sk->sk_family; | ||
4283 | u32 newsid; | 4305 | u32 newsid; |
4284 | u32 peersid; | 4306 | u32 peersid; |
4285 | 4307 | ||
4286 | err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); | 4308 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
4309 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | ||
4310 | family = PF_INET; | ||
4311 | |||
4312 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); | ||
4287 | if (err) | 4313 | if (err) |
4288 | return err; | 4314 | return err; |
4289 | if (peersid == SECSID_NULL) { | 4315 | if (peersid == SECSID_NULL) { |
@@ -4318,12 +4344,18 @@ static void selinux_inet_csk_clone(struct sock *newsk, | |||
4318 | selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); | 4344 | selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); |
4319 | } | 4345 | } |
4320 | 4346 | ||
4321 | static void selinux_inet_conn_established(struct sock *sk, | 4347 | static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) |
4322 | struct sk_buff *skb) | ||
4323 | { | 4348 | { |
4349 | u16 family = sk->sk_family; | ||
4324 | struct sk_security_struct *sksec = sk->sk_security; | 4350 | struct sk_security_struct *sksec = sk->sk_security; |
4325 | 4351 | ||
4326 | selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); | 4352 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
4353 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | ||
4354 | family = PF_INET; | ||
4355 | |||
4356 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | ||
4357 | |||
4358 | selinux_netlbl_inet_conn_established(sk, family); | ||
4327 | } | 4359 | } |
4328 | 4360 | ||
4329 | static void selinux_req_classify_flow(const struct request_sock *req, | 4361 | static void selinux_req_classify_flow(const struct request_sock *req, |
@@ -4373,39 +4405,54 @@ out: | |||
4373 | static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | 4405 | static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, |
4374 | u16 family) | 4406 | u16 family) |
4375 | { | 4407 | { |
4408 | int err; | ||
4376 | char *addrp; | 4409 | char *addrp; |
4377 | u32 peer_sid; | 4410 | u32 peer_sid; |
4378 | struct avc_audit_data ad; | 4411 | struct avc_audit_data ad; |
4379 | u8 secmark_active; | 4412 | u8 secmark_active; |
4413 | u8 netlbl_active; | ||
4380 | u8 peerlbl_active; | 4414 | u8 peerlbl_active; |
4381 | 4415 | ||
4382 | if (!selinux_policycap_netpeer) | 4416 | if (!selinux_policycap_netpeer) |
4383 | return NF_ACCEPT; | 4417 | return NF_ACCEPT; |
4384 | 4418 | ||
4385 | secmark_active = selinux_secmark_enabled(); | 4419 | secmark_active = selinux_secmark_enabled(); |
4386 | peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); | 4420 | netlbl_active = netlbl_enabled(); |
4421 | peerlbl_active = netlbl_active || selinux_xfrm_enabled(); | ||
4387 | if (!secmark_active && !peerlbl_active) | 4422 | if (!secmark_active && !peerlbl_active) |
4388 | return NF_ACCEPT; | 4423 | return NF_ACCEPT; |
4389 | 4424 | ||
4425 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | ||
4426 | return NF_DROP; | ||
4427 | |||
4390 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4428 | AVC_AUDIT_DATA_INIT(&ad, NET); |
4391 | ad.u.net.netif = ifindex; | 4429 | ad.u.net.netif = ifindex; |
4392 | ad.u.net.family = family; | 4430 | ad.u.net.family = family; |
4393 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4431 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
4394 | return NF_DROP; | 4432 | return NF_DROP; |
4395 | 4433 | ||
4396 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4434 | if (peerlbl_active) { |
4397 | return NF_DROP; | 4435 | err = selinux_inet_sys_rcv_skb(ifindex, addrp, family, |
4398 | 4436 | peer_sid, &ad); | |
4399 | if (peerlbl_active) | 4437 | if (err) { |
4400 | if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, | 4438 | selinux_netlbl_err(skb, err, 1); |
4401 | peer_sid, &ad) != 0) | ||
4402 | return NF_DROP; | 4439 | return NF_DROP; |
4440 | } | ||
4441 | } | ||
4403 | 4442 | ||
4404 | if (secmark_active) | 4443 | if (secmark_active) |
4405 | if (avc_has_perm(peer_sid, skb->secmark, | 4444 | if (avc_has_perm(peer_sid, skb->secmark, |
4406 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) | 4445 | SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) |
4407 | return NF_DROP; | 4446 | return NF_DROP; |
4408 | 4447 | ||
4448 | if (netlbl_active) | ||
4449 | /* we do this in the FORWARD path and not the POST_ROUTING | ||
4450 | * path because we want to make sure we apply the necessary | ||
4451 | * labeling before IPsec is applied so we can leverage AH | ||
4452 | * protection */ | ||
4453 | if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0) | ||
4454 | return NF_DROP; | ||
4455 | |||
4409 | return NF_ACCEPT; | 4456 | return NF_ACCEPT; |
4410 | } | 4457 | } |
4411 | 4458 | ||
@@ -4429,6 +4476,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum, | |||
4429 | } | 4476 | } |
4430 | #endif /* IPV6 */ | 4477 | #endif /* IPV6 */ |
4431 | 4478 | ||
4479 | static unsigned int selinux_ip_output(struct sk_buff *skb, | ||
4480 | u16 family) | ||
4481 | { | ||
4482 | u32 sid; | ||
4483 | |||
4484 | if (!netlbl_enabled()) | ||
4485 | return NF_ACCEPT; | ||
4486 | |||
4487 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path | ||
4488 | * because we want to make sure we apply the necessary labeling | ||
4489 | * before IPsec is applied so we can leverage AH protection */ | ||
4490 | if (skb->sk) { | ||
4491 | struct sk_security_struct *sksec = skb->sk->sk_security; | ||
4492 | sid = sksec->sid; | ||
4493 | } else | ||
4494 | sid = SECINITSID_KERNEL; | ||
4495 | if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0) | ||
4496 | return NF_DROP; | ||
4497 | |||
4498 | return NF_ACCEPT; | ||
4499 | } | ||
4500 | |||
4501 | static unsigned int selinux_ipv4_output(unsigned int hooknum, | ||
4502 | struct sk_buff *skb, | ||
4503 | const struct net_device *in, | ||
4504 | const struct net_device *out, | ||
4505 | int (*okfn)(struct sk_buff *)) | ||
4506 | { | ||
4507 | return selinux_ip_output(skb, PF_INET); | ||
4508 | } | ||
4509 | |||
4432 | static int selinux_ip_postroute_iptables_compat(struct sock *sk, | 4510 | static int selinux_ip_postroute_iptables_compat(struct sock *sk, |
4433 | int ifindex, | 4511 | int ifindex, |
4434 | struct avc_audit_data *ad, | 4512 | struct avc_audit_data *ad, |
@@ -4496,30 +4574,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk, | |||
4496 | 4574 | ||
4497 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | 4575 | static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, |
4498 | int ifindex, | 4576 | int ifindex, |
4499 | struct avc_audit_data *ad, | 4577 | u16 family) |
4500 | u16 family, | ||
4501 | char *addrp, | ||
4502 | u8 proto) | ||
4503 | { | 4578 | { |
4504 | struct sock *sk = skb->sk; | 4579 | struct sock *sk = skb->sk; |
4505 | struct sk_security_struct *sksec; | 4580 | struct sk_security_struct *sksec; |
4581 | struct avc_audit_data ad; | ||
4582 | char *addrp; | ||
4583 | u8 proto; | ||
4506 | 4584 | ||
4507 | if (sk == NULL) | 4585 | if (sk == NULL) |
4508 | return NF_ACCEPT; | 4586 | return NF_ACCEPT; |
4509 | sksec = sk->sk_security; | 4587 | sksec = sk->sk_security; |
4510 | 4588 | ||
4589 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
4590 | ad.u.net.netif = ifindex; | ||
4591 | ad.u.net.family = family; | ||
4592 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | ||
4593 | return NF_DROP; | ||
4594 | |||
4511 | if (selinux_compat_net) { | 4595 | if (selinux_compat_net) { |
4512 | if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, | 4596 | if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, |
4513 | ad, family, addrp)) | 4597 | &ad, family, addrp)) |
4514 | return NF_DROP; | 4598 | return NF_DROP; |
4515 | } else { | 4599 | } else { |
4516 | if (avc_has_perm(sksec->sid, skb->secmark, | 4600 | if (avc_has_perm(sksec->sid, skb->secmark, |
4517 | SECCLASS_PACKET, PACKET__SEND, ad)) | 4601 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4518 | return NF_DROP; | 4602 | return NF_DROP; |
4519 | } | 4603 | } |
4520 | 4604 | ||
4521 | if (selinux_policycap_netpeer) | 4605 | if (selinux_policycap_netpeer) |
4522 | if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) | 4606 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4523 | return NF_DROP; | 4607 | return NF_DROP; |
4524 | 4608 | ||
4525 | return NF_ACCEPT; | 4609 | return NF_ACCEPT; |
@@ -4533,23 +4617,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4533 | struct sock *sk; | 4617 | struct sock *sk; |
4534 | struct avc_audit_data ad; | 4618 | struct avc_audit_data ad; |
4535 | char *addrp; | 4619 | char *addrp; |
4536 | u8 proto; | ||
4537 | u8 secmark_active; | 4620 | u8 secmark_active; |
4538 | u8 peerlbl_active; | 4621 | u8 peerlbl_active; |
4539 | 4622 | ||
4540 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
4541 | ad.u.net.netif = ifindex; | ||
4542 | ad.u.net.family = family; | ||
4543 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | ||
4544 | return NF_DROP; | ||
4545 | |||
4546 | /* If any sort of compatibility mode is enabled then handoff processing | 4623 | /* If any sort of compatibility mode is enabled then handoff processing |
4547 | * to the selinux_ip_postroute_compat() function to deal with the | 4624 | * to the selinux_ip_postroute_compat() function to deal with the |
4548 | * special handling. We do this in an attempt to keep this function | 4625 | * special handling. We do this in an attempt to keep this function |
4549 | * as fast and as clean as possible. */ | 4626 | * as fast and as clean as possible. */ |
4550 | if (selinux_compat_net || !selinux_policycap_netpeer) | 4627 | if (selinux_compat_net || !selinux_policycap_netpeer) |
4551 | return selinux_ip_postroute_compat(skb, ifindex, &ad, | 4628 | return selinux_ip_postroute_compat(skb, ifindex, family); |
4552 | family, addrp, proto); | ||
4553 | 4629 | ||
4554 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec | 4630 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec |
4555 | * packet transformation so allow the packet to pass without any checks | 4631 | * packet transformation so allow the packet to pass without any checks |
@@ -4565,21 +4641,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4565 | if (!secmark_active && !peerlbl_active) | 4641 | if (!secmark_active && !peerlbl_active) |
4566 | return NF_ACCEPT; | 4642 | return NF_ACCEPT; |
4567 | 4643 | ||
4568 | /* if the packet is locally generated (skb->sk != NULL) then use the | 4644 | /* if the packet is being forwarded then get the peer label from the |
4569 | * socket's label as the peer label, otherwise the packet is being | 4645 | * packet itself; otherwise check to see if it is from a local |
4570 | * forwarded through this system and we need to fetch the peer label | 4646 | * application or the kernel, if from an application get the peer label |
4571 | * directly from the packet */ | 4647 | * from the sending socket, otherwise use the kernel's sid */ |
4572 | sk = skb->sk; | 4648 | sk = skb->sk; |
4573 | if (sk) { | 4649 | if (sk == NULL) { |
4650 | switch (family) { | ||
4651 | case PF_INET: | ||
4652 | if (IPCB(skb)->flags & IPSKB_FORWARDED) | ||
4653 | secmark_perm = PACKET__FORWARD_OUT; | ||
4654 | else | ||
4655 | secmark_perm = PACKET__SEND; | ||
4656 | break; | ||
4657 | case PF_INET6: | ||
4658 | if (IP6CB(skb)->flags & IP6SKB_FORWARDED) | ||
4659 | secmark_perm = PACKET__FORWARD_OUT; | ||
4660 | else | ||
4661 | secmark_perm = PACKET__SEND; | ||
4662 | break; | ||
4663 | default: | ||
4664 | return NF_DROP; | ||
4665 | } | ||
4666 | if (secmark_perm == PACKET__FORWARD_OUT) { | ||
4667 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | ||
4668 | return NF_DROP; | ||
4669 | } else | ||
4670 | peer_sid = SECINITSID_KERNEL; | ||
4671 | } else { | ||
4574 | struct sk_security_struct *sksec = sk->sk_security; | 4672 | struct sk_security_struct *sksec = sk->sk_security; |
4575 | peer_sid = sksec->sid; | 4673 | peer_sid = sksec->sid; |
4576 | secmark_perm = PACKET__SEND; | 4674 | secmark_perm = PACKET__SEND; |
4577 | } else { | ||
4578 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | ||
4579 | return NF_DROP; | ||
4580 | secmark_perm = PACKET__FORWARD_OUT; | ||
4581 | } | 4675 | } |
4582 | 4676 | ||
4677 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
4678 | ad.u.net.netif = ifindex; | ||
4679 | ad.u.net.family = family; | ||
4680 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | ||
4681 | return NF_DROP; | ||
4682 | |||
4583 | if (secmark_active) | 4683 | if (secmark_active) |
4584 | if (avc_has_perm(peer_sid, skb->secmark, | 4684 | if (avc_has_perm(peer_sid, skb->secmark, |
4585 | SECCLASS_PACKET, secmark_perm, &ad)) | 4685 | SECCLASS_PACKET, secmark_perm, &ad)) |
@@ -5222,8 +5322,12 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5222 | 5322 | ||
5223 | if (sid == 0) | 5323 | if (sid == 0) |
5224 | return -EINVAL; | 5324 | return -EINVAL; |
5225 | 5325 | /* | |
5226 | /* Only allow single threaded processes to change context */ | 5326 | * SELinux allows to change context in the following case only. |
5327 | * - Single threaded processes. | ||
5328 | * - Multi threaded processes intend to change its context into | ||
5329 | * more restricted domain (defined by TYPEBOUNDS statement). | ||
5330 | */ | ||
5227 | if (atomic_read(&p->mm->mm_users) != 1) { | 5331 | if (atomic_read(&p->mm->mm_users) != 1) { |
5228 | struct task_struct *g, *t; | 5332 | struct task_struct *g, *t; |
5229 | struct mm_struct *mm = p->mm; | 5333 | struct mm_struct *mm = p->mm; |
@@ -5231,11 +5335,16 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5231 | do_each_thread(g, t) { | 5335 | do_each_thread(g, t) { |
5232 | if (t->mm == mm && t != p) { | 5336 | if (t->mm == mm && t != p) { |
5233 | read_unlock(&tasklist_lock); | 5337 | read_unlock(&tasklist_lock); |
5234 | return -EPERM; | 5338 | error = security_bounded_transition(tsec->sid, sid); |
5339 | if (!error) | ||
5340 | goto boundary_ok; | ||
5341 | |||
5342 | return error; | ||
5235 | } | 5343 | } |
5236 | } while_each_thread(g, t); | 5344 | } while_each_thread(g, t); |
5237 | read_unlock(&tasklist_lock); | 5345 | read_unlock(&tasklist_lock); |
5238 | } | 5346 | } |
5347 | boundary_ok: | ||
5239 | 5348 | ||
5240 | /* Check permissions for the transition. */ | 5349 | /* Check permissions for the transition. */ |
5241 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5350 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |
@@ -5247,7 +5356,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5247 | Otherwise, leave SID unchanged and fail. */ | 5356 | Otherwise, leave SID unchanged and fail. */ |
5248 | task_lock(p); | 5357 | task_lock(p); |
5249 | rcu_read_lock(); | 5358 | rcu_read_lock(); |
5250 | tracer = task_tracer_task(p); | 5359 | tracer = tracehook_tracer_task(p); |
5251 | if (tracer != NULL) { | 5360 | if (tracer != NULL) { |
5252 | struct task_security_struct *ptsec = tracer->security; | 5361 | struct task_security_struct *ptsec = tracer->security; |
5253 | u32 ptsid = ptsec->sid; | 5362 | u32 ptsid = ptsec->sid; |
@@ -5359,7 +5468,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5359 | static struct security_operations selinux_ops = { | 5468 | static struct security_operations selinux_ops = { |
5360 | .name = "selinux", | 5469 | .name = "selinux", |
5361 | 5470 | ||
5362 | .ptrace = selinux_ptrace, | 5471 | .ptrace_may_access = selinux_ptrace_may_access, |
5472 | .ptrace_traceme = selinux_ptrace_traceme, | ||
5363 | .capget = selinux_capget, | 5473 | .capget = selinux_capget, |
5364 | .capset_check = selinux_capset_check, | 5474 | .capset_check = selinux_capset_check, |
5365 | .capset_set = selinux_capset_set, | 5475 | .capset_set = selinux_capset_set, |
@@ -5643,6 +5753,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = { | |||
5643 | .pf = PF_INET, | 5753 | .pf = PF_INET, |
5644 | .hooknum = NF_INET_FORWARD, | 5754 | .hooknum = NF_INET_FORWARD, |
5645 | .priority = NF_IP_PRI_SELINUX_FIRST, | 5755 | .priority = NF_IP_PRI_SELINUX_FIRST, |
5756 | }, | ||
5757 | { | ||
5758 | .hook = selinux_ipv4_output, | ||
5759 | .owner = THIS_MODULE, | ||
5760 | .pf = PF_INET, | ||
5761 | .hooknum = NF_INET_LOCAL_OUT, | ||
5762 | .priority = NF_IP_PRI_SELINUX_FIRST, | ||
5646 | } | 5763 | } |
5647 | }; | 5764 | }; |
5648 | 5765 | ||
@@ -5670,27 +5787,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = { | |||
5670 | static int __init selinux_nf_ip_init(void) | 5787 | static int __init selinux_nf_ip_init(void) |
5671 | { | 5788 | { |
5672 | int err = 0; | 5789 | int err = 0; |
5673 | u32 iter; | ||
5674 | 5790 | ||
5675 | if (!selinux_enabled) | 5791 | if (!selinux_enabled) |
5676 | goto out; | 5792 | goto out; |
5677 | 5793 | ||
5678 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); | 5794 | printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); |
5679 | 5795 | ||
5680 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { | 5796 | err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5681 | err = nf_register_hook(&selinux_ipv4_ops[iter]); | 5797 | if (err) |
5682 | if (err) | 5798 | panic("SELinux: nf_register_hooks for IPv4: error %d\n", err); |
5683 | panic("SELinux: nf_register_hook for IPv4: error %d\n", | ||
5684 | err); | ||
5685 | } | ||
5686 | 5799 | ||
5687 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5800 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5688 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { | 5801 | err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5689 | err = nf_register_hook(&selinux_ipv6_ops[iter]); | 5802 | if (err) |
5690 | if (err) | 5803 | panic("SELinux: nf_register_hooks for IPv6: error %d\n", err); |
5691 | panic("SELinux: nf_register_hook for IPv6: error %d\n", | ||
5692 | err); | ||
5693 | } | ||
5694 | #endif /* IPV6 */ | 5804 | #endif /* IPV6 */ |
5695 | 5805 | ||
5696 | out: | 5806 | out: |
@@ -5702,15 +5812,11 @@ __initcall(selinux_nf_ip_init); | |||
5702 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE | 5812 | #ifdef CONFIG_SECURITY_SELINUX_DISABLE |
5703 | static void selinux_nf_ip_exit(void) | 5813 | static void selinux_nf_ip_exit(void) |
5704 | { | 5814 | { |
5705 | u32 iter; | ||
5706 | |||
5707 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); | 5815 | printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); |
5708 | 5816 | ||
5709 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) | 5817 | nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops)); |
5710 | nf_unregister_hook(&selinux_ipv4_ops[iter]); | ||
5711 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 5818 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
5712 | for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) | 5819 | nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops)); |
5713 | nf_unregister_hook(&selinux_ipv6_ops[iter]); | ||
5714 | #endif /* IPV6 */ | 5820 | #endif /* IPV6 */ |
5715 | } | 5821 | } |
5716 | #endif | 5822 | #endif |