aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sysctl/vm.txt15
-rw-r--r--include/linux/security.h17
-rw-r--r--kernel/sysctl.c10
-rw-r--r--mm/mmap.c4
-rw-r--r--mm/mremap.c13
-rw-r--r--mm/nommu.c2
-rw-r--r--security/dummy.c6
-rw-r--r--security/security.c1
-rw-r--r--security/selinux/avc.c12
-rw-r--r--security/selinux/hooks.c42
-rw-r--r--security/selinux/include/av_perm_to_string.h1
-rw-r--r--security/selinux/include/av_permissions.h1
-rw-r--r--security/selinux/include/avc.h6
-rw-r--r--security/selinux/include/class_to_string.h1
-rw-r--r--security/selinux/include/flask.h1
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/netlabel.c34
-rw-r--r--security/selinux/selinuxfs.c269
-rw-r--r--security/selinux/ss/policydb.c7
-rw-r--r--security/selinux/ss/services.c144
20 files changed, 504 insertions, 86 deletions
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 1d192565e182..8cfca173d4bc 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
31- min_unmapped_ratio 31- min_unmapped_ratio
32- min_slab_ratio 32- min_slab_ratio
33- panic_on_oom 33- panic_on_oom
34- mmap_min_address
34 35
35============================================================== 36==============================================================
36 37
@@ -216,3 +217,17 @@ above-mentioned.
216The default value is 0. 217The default value is 0.
2171 and 2 are for failover of clustering. Please select either 2181 and 2 are for failover of clustering. Please select either
218according to your policy of failover. 219according to your policy of failover.
220
221==============================================================
222
223mmap_min_addr
224
225This file indicates the amount of address space which a user process will
226be restricted from mmaping. Since kernel null dereference bugs could
227accidentally operate based on the information in the first couple of pages
228of memory userspace processes should not be allowed to write to them. By
229default this value is set to 0 and no protections will be enforced by the
230security module. Setting this value to something like 64k will allow the
231vast majority of applications to work correctly and provide defense in depth
232against future potential kernel bugs.
233
diff --git a/include/linux/security.h b/include/linux/security.h
index 9eb9e0fe0331..c11dc8aa0351 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -71,6 +71,7 @@ struct xfrm_user_sec_ctx;
71extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); 71extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
72extern int cap_netlink_recv(struct sk_buff *skb, int cap); 72extern int cap_netlink_recv(struct sk_buff *skb, int cap);
73 73
74extern unsigned long mmap_min_addr;
74/* 75/*
75 * Values used in the task_security_ops calls 76 * Values used in the task_security_ops calls
76 */ 77 */
@@ -1241,8 +1242,9 @@ struct security_operations {
1241 int (*file_ioctl) (struct file * file, unsigned int cmd, 1242 int (*file_ioctl) (struct file * file, unsigned int cmd,
1242 unsigned long arg); 1243 unsigned long arg);
1243 int (*file_mmap) (struct file * file, 1244 int (*file_mmap) (struct file * file,
1244 unsigned long reqprot, 1245 unsigned long reqprot, unsigned long prot,
1245 unsigned long prot, unsigned long flags); 1246 unsigned long flags, unsigned long addr,
1247 unsigned long addr_only);
1246 int (*file_mprotect) (struct vm_area_struct * vma, 1248 int (*file_mprotect) (struct vm_area_struct * vma,
1247 unsigned long reqprot, 1249 unsigned long reqprot,
1248 unsigned long prot); 1250 unsigned long prot);
@@ -1814,9 +1816,12 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
1814 1816
1815static inline int security_file_mmap (struct file *file, unsigned long reqprot, 1817static inline int security_file_mmap (struct file *file, unsigned long reqprot,
1816 unsigned long prot, 1818 unsigned long prot,
1817 unsigned long flags) 1819 unsigned long flags,
1820 unsigned long addr,
1821 unsigned long addr_only)
1818{ 1822{
1819 return security_ops->file_mmap (file, reqprot, prot, flags); 1823 return security_ops->file_mmap (file, reqprot, prot, flags, addr,
1824 addr_only);
1820} 1825}
1821 1826
1822static inline int security_file_mprotect (struct vm_area_struct *vma, 1827static inline int security_file_mprotect (struct vm_area_struct *vma,
@@ -2489,7 +2494,9 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
2489 2494
2490static inline int security_file_mmap (struct file *file, unsigned long reqprot, 2495static inline int security_file_mmap (struct file *file, unsigned long reqprot,
2491 unsigned long prot, 2496 unsigned long prot,
2492 unsigned long flags) 2497 unsigned long flags,
2498 unsigned long addr,
2499 unsigned long addr_only)
2493{ 2500{
2494 return 0; 2501 return 0;
2495} 2502}
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 51f5dac42a00..d93e13d93f24 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -949,6 +949,16 @@ static ctl_table vm_table[] = {
949 .strategy = &sysctl_jiffies, 949 .strategy = &sysctl_jiffies,
950 }, 950 },
951#endif 951#endif
952#ifdef CONFIG_SECURITY
953 {
954 .ctl_name = CTL_UNNUMBERED,
955 .procname = "mmap_min_addr",
956 .data = &mmap_min_addr,
957 .maxlen = sizeof(unsigned long),
958 .mode = 0644,
959 .proc_handler = &proc_doulongvec_minmax,
960 },
961#endif
952#if defined(CONFIG_X86_32) || \ 962#if defined(CONFIG_X86_32) || \
953 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) 963 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
954 { 964 {
diff --git a/mm/mmap.c b/mm/mmap.c
index 906ed402f7ca..9f70c8e8c871 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1023,10 +1023,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
1023 } 1023 }
1024 } 1024 }
1025 1025
1026 error = security_file_mmap(file, reqprot, prot, flags); 1026 error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
1027 if (error) 1027 if (error)
1028 return error; 1028 return error;
1029 1029
1030 /* Clear old maps */ 1030 /* Clear old maps */
1031 error = -ENOMEM; 1031 error = -ENOMEM;
1032munmap_back: 1032munmap_back:
diff --git a/mm/mremap.c b/mm/mremap.c
index 5d4bd4f95b8e..bc7c52efc71b 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -291,6 +291,10 @@ unsigned long do_mremap(unsigned long addr,
291 if ((addr <= new_addr) && (addr+old_len) > new_addr) 291 if ((addr <= new_addr) && (addr+old_len) > new_addr)
292 goto out; 292 goto out;
293 293
294 ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
295 if (ret)
296 goto out;
297
294 ret = do_munmap(mm, new_addr, new_len); 298 ret = do_munmap(mm, new_addr, new_len);
295 if (ret) 299 if (ret)
296 goto out; 300 goto out;
@@ -390,8 +394,13 @@ unsigned long do_mremap(unsigned long addr,
390 394
391 new_addr = get_unmapped_area(vma->vm_file, 0, new_len, 395 new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
392 vma->vm_pgoff, map_flags); 396 vma->vm_pgoff, map_flags);
393 ret = new_addr; 397 if (new_addr & ~PAGE_MASK) {
394 if (new_addr & ~PAGE_MASK) 398 ret = new_addr;
399 goto out;
400 }
401
402 ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
403 if (ret)
395 goto out; 404 goto out;
396 } 405 }
397 ret = move_vma(vma, addr, old_len, new_len, new_addr); 406 ret = move_vma(vma, addr, old_len, new_len, new_addr);
diff --git a/mm/nommu.c b/mm/nommu.c
index 2b16b00a5b11..989e2e9af5c3 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -639,7 +639,7 @@ static int validate_mmap_request(struct file *file,
639 } 639 }
640 640
641 /* allow the security API to have its say */ 641 /* allow the security API to have its say */
642 ret = security_file_mmap(file, reqprot, prot, flags); 642 ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
643 if (ret < 0) 643 if (ret < 0)
644 return ret; 644 return ret;
645 645
diff --git a/security/dummy.c b/security/dummy.c
index 8ffd76405b5b..d6a112ce2975 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
420 420
421static int dummy_file_mmap (struct file *file, unsigned long reqprot, 421static int dummy_file_mmap (struct file *file, unsigned long reqprot,
422 unsigned long prot, 422 unsigned long prot,
423 unsigned long flags) 423 unsigned long flags,
424 unsigned long addr,
425 unsigned long addr_only)
424{ 426{
427 if (addr < mmap_min_addr)
428 return -EACCES;
425 return 0; 429 return 0;
426} 430}
427 431
diff --git a/security/security.c b/security/security.c
index fc8601b2b7ac..27e5863d30f1 100644
--- a/security/security.c
+++ b/security/security.c
@@ -24,6 +24,7 @@ extern struct security_operations dummy_security_ops;
24extern void security_fixup_ops(struct security_operations *ops); 24extern void security_fixup_ops(struct security_operations *ops);
25 25
26struct security_operations *security_ops; /* Initialized to NULL */ 26struct security_operations *security_ops; /* Initialized to NULL */
27unsigned long mmap_min_addr; /* 0 means no protection */
27 28
28static inline int verify(struct security_operations *ops) 29static inline int verify(struct security_operations *ops)
29{ 30{
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a89edc6..78c408fd2b02 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -586,7 +586,7 @@ void avc_audit(u32 ssid, u32 tsid,
586 } 586 }
587 } 587 }
588 if (inode) 588 if (inode)
589 audit_log_format(ab, " dev=%s ino=%ld", 589 audit_log_format(ab, " dev=%s ino=%lu",
590 inode->i_sb->s_id, 590 inode->i_sb->s_id,
591 inode->i_ino); 591 inode->i_ino);
592 break; 592 break;
@@ -832,6 +832,7 @@ int avc_ss_reset(u32 seqno)
832 * @tsid: target security identifier 832 * @tsid: target security identifier
833 * @tclass: target security class 833 * @tclass: target security class
834 * @requested: requested permissions, interpreted based on @tclass 834 * @requested: requested permissions, interpreted based on @tclass
835 * @flags: AVC_STRICT or 0
835 * @avd: access vector decisions 836 * @avd: access vector decisions
836 * 837 *
837 * Check the AVC to determine whether the @requested permissions are granted 838 * Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@ int avc_ss_reset(u32 seqno)
846 * should be released for the auditing. 847 * should be released for the auditing.
847 */ 848 */
848int avc_has_perm_noaudit(u32 ssid, u32 tsid, 849int avc_has_perm_noaudit(u32 ssid, u32 tsid,
849 u16 tclass, u32 requested, 850 u16 tclass, u32 requested,
850 struct av_decision *avd) 851 unsigned flags,
852 struct av_decision *avd)
851{ 853{
852 struct avc_node *node; 854 struct avc_node *node;
853 struct avc_entry entry, *p_ae; 855 struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
874 denied = requested & ~(p_ae->avd.allowed); 876 denied = requested & ~(p_ae->avd.allowed);
875 877
876 if (!requested || denied) { 878 if (!requested || denied) {
877 if (selinux_enforcing) 879 if (selinux_enforcing || (flags & AVC_STRICT))
878 rc = -EACCES; 880 rc = -EACCES;
879 else 881 else
880 if (node) 882 if (node)
@@ -909,7 +911,7 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
909 struct av_decision avd; 911 struct av_decision avd;
910 int rc; 912 int rc;
911 913
912 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd); 914 rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
913 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); 915 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
914 return rc; 916 return rc;
915} 917}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad8dd4e8657e..aff8f46c2aa2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages)
1592 rc = secondary_ops->capable(current, CAP_SYS_ADMIN); 1592 rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
1593 if (rc == 0) 1593 if (rc == 0)
1594 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, 1594 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
1595 SECCLASS_CAPABILITY, 1595 SECCLASS_CAPABILITY,
1596 CAP_TO_MASK(CAP_SYS_ADMIN), 1596 CAP_TO_MASK(CAP_SYS_ADMIN),
1597 NULL); 1597 0,
1598 NULL);
1598 1599
1599 if (rc == 0) 1600 if (rc == 0)
1600 cap_sys_admin = 1; 1601 cap_sys_admin = 1;
@@ -2568,12 +2569,16 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
2568} 2569}
2569 2570
2570static int selinux_file_mmap(struct file *file, unsigned long reqprot, 2571static int selinux_file_mmap(struct file *file, unsigned long reqprot,
2571 unsigned long prot, unsigned long flags) 2572 unsigned long prot, unsigned long flags,
2573 unsigned long addr, unsigned long addr_only)
2572{ 2574{
2573 int rc; 2575 int rc = 0;
2576 u32 sid = ((struct task_security_struct*)(current->security))->sid;
2574 2577
2575 rc = secondary_ops->file_mmap(file, reqprot, prot, flags); 2578 if (addr < mmap_min_addr)
2576 if (rc) 2579 rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
2580 MEMPROTECT__MMAP_ZERO, NULL);
2581 if (rc || addr_only)
2577 return rc; 2582 return rc;
2578 2583
2579 if (selinux_checkreqprot) 2584 if (selinux_checkreqprot)
@@ -3124,17 +3129,19 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3124/** 3129/**
3125 * selinux_skb_extlbl_sid - Determine the external label of a packet 3130 * selinux_skb_extlbl_sid - Determine the external label of a packet
3126 * @skb: the packet 3131 * @skb: the packet
3127 * @base_sid: the SELinux SID to use as a context for MLS only external labels
3128 * @sid: the packet's SID 3132 * @sid: the packet's SID
3129 * 3133 *
3130 * Description: 3134 * Description:
3131 * Check the various different forms of external packet labeling and determine 3135 * Check the various different forms of external packet labeling and determine
3132 * the external SID for the packet. 3136 * the external SID for the packet. If only one form of external labeling is
3137 * present then it is used, if both labeled IPsec and NetLabel labels are
3138 * present then the SELinux type information is taken from the labeled IPsec
3139 * SA and the MLS sensitivity label information is taken from the NetLabel
3140 * security attributes. This bit of "magic" is done in the call to
3141 * selinux_netlbl_skbuff_getsid().
3133 * 3142 *
3134 */ 3143 */
3135static void selinux_skb_extlbl_sid(struct sk_buff *skb, 3144static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid)
3136 u32 base_sid,
3137 u32 *sid)
3138{ 3145{
3139 u32 xfrm_sid; 3146 u32 xfrm_sid;
3140 u32 nlbl_sid; 3147 u32 nlbl_sid;
@@ -3142,10 +3149,9 @@ static void selinux_skb_extlbl_sid(struct sk_buff *skb,
3142 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3149 selinux_skb_xfrm_sid(skb, &xfrm_sid);
3143 if (selinux_netlbl_skbuff_getsid(skb, 3150 if (selinux_netlbl_skbuff_getsid(skb,
3144 (xfrm_sid == SECSID_NULL ? 3151 (xfrm_sid == SECSID_NULL ?
3145 base_sid : xfrm_sid), 3152 SECINITSID_NETMSG : xfrm_sid),
3146 &nlbl_sid) != 0) 3153 &nlbl_sid) != 0)
3147 nlbl_sid = SECSID_NULL; 3154 nlbl_sid = SECSID_NULL;
3148
3149 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3155 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
3150} 3156}
3151 3157
@@ -3690,7 +3696,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3690 if (sock && sock->sk->sk_family == PF_UNIX) 3696 if (sock && sock->sk->sk_family == PF_UNIX)
3691 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3697 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3692 else if (skb) 3698 else if (skb)
3693 selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid); 3699 selinux_skb_extlbl_sid(skb, &peer_secid);
3694 3700
3695 if (peer_secid == SECSID_NULL) 3701 if (peer_secid == SECSID_NULL)
3696 err = -EINVAL; 3702 err = -EINVAL;
@@ -3751,7 +3757,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3751 u32 newsid; 3757 u32 newsid;
3752 u32 peersid; 3758 u32 peersid;
3753 3759
3754 selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); 3760 selinux_skb_extlbl_sid(skb, &peersid);
3755 if (peersid == SECSID_NULL) { 3761 if (peersid == SECSID_NULL) {
3756 req->secid = sksec->sid; 3762 req->secid = sksec->sid;
3757 req->peer_secid = SECSID_NULL; 3763 req->peer_secid = SECSID_NULL;
@@ -3789,7 +3795,7 @@ static void selinux_inet_conn_established(struct sock *sk,
3789{ 3795{
3790 struct sk_security_struct *sksec = sk->sk_security; 3796 struct sk_security_struct *sksec = sk->sk_security;
3791 3797
3792 selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); 3798 selinux_skb_extlbl_sid(skb, &sksec->peer_sid);
3793} 3799}
3794 3800
3795static void selinux_req_classify_flow(const struct request_sock *req, 3801static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4626,7 +4632,7 @@ static int selinux_setprocattr(struct task_struct *p,
4626 if (p->ptrace & PT_PTRACED) { 4632 if (p->ptrace & PT_PTRACED) {
4627 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, 4633 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
4628 SECCLASS_PROCESS, 4634 SECCLASS_PROCESS,
4629 PROCESS__PTRACE, &avd); 4635 PROCESS__PTRACE, 0, &avd);
4630 if (!error) 4636 if (!error)
4631 tsec->sid = sid; 4637 tsec->sid = sid;
4632 task_unlock(p); 4638 task_unlock(p);
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index b83e74012a97..049bf69429b6 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -158,3 +158,4 @@
158 S_(SECCLASS_KEY, KEY__CREATE, "create") 158 S_(SECCLASS_KEY, KEY__CREATE, "create")
159 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") 159 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
160 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") 160 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
161 S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 5fee1735bffe..eda89a2ec635 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -823,3 +823,4 @@
823#define DCCP_SOCKET__NAME_BIND 0x00200000UL 823#define DCCP_SOCKET__NAME_BIND 0x00200000UL
824#define DCCP_SOCKET__NODE_BIND 0x00400000UL 824#define DCCP_SOCKET__NODE_BIND 0x00400000UL
825#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL 825#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
826#define MEMPROTECT__MMAP_ZERO 0x00000001UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 6ed10c3d3339..e145f6e13b0b 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -102,9 +102,11 @@ void avc_audit(u32 ssid, u32 tsid,
102 u16 tclass, u32 requested, 102 u16 tclass, u32 requested,
103 struct av_decision *avd, int result, struct avc_audit_data *auditdata); 103 struct av_decision *avd, int result, struct avc_audit_data *auditdata);
104 104
105#define AVC_STRICT 1 /* Ignore permissive mode. */
105int avc_has_perm_noaudit(u32 ssid, u32 tsid, 106int avc_has_perm_noaudit(u32 ssid, u32 tsid,
106 u16 tclass, u32 requested, 107 u16 tclass, u32 requested,
107 struct av_decision *avd); 108 unsigned flags,
109 struct av_decision *avd);
108 110
109int avc_has_perm(u32 ssid, u32 tsid, 111int avc_has_perm(u32 ssid, u32 tsid,
110 u16 tclass, u32 requested, 112 u16 tclass, u32 requested,
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 378799068441..e77de0e62ea0 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -63,3 +63,4 @@
63 S_("key") 63 S_("key")
64 S_(NULL) 64 S_(NULL)
65 S_("dccp_socket") 65 S_("dccp_socket")
66 S_("memprotect")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 35f309f47873..a9c2b20f14b5 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -49,6 +49,7 @@
49#define SECCLASS_PACKET 57 49#define SECCLASS_PACKET 57
50#define SECCLASS_KEY 58 50#define SECCLASS_KEY 58
51#define SECCLASS_DCCP_SOCKET 60 51#define SECCLASS_DCCP_SOCKET 60
52#define SECCLASS_MEMPROTECT 61
52 53
53/* 54/*
54 * Security identifier indices for initial entities 55 * Security identifier indices for initial entities
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b94378afea25..83bdd4d2a29e 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -41,6 +41,7 @@ extern int selinux_mls_enabled;
41 41
42int security_load_policy(void * data, size_t len); 42int security_load_policy(void * data, size_t len);
43 43
44#define SEL_VEC_MAX 32
44struct av_decision { 45struct av_decision {
45 u32 allowed; 46 u32 allowed;
46 u32 decided; 47 u32 decided;
@@ -87,6 +88,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
87 88
88int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 89int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
89 90
91int security_get_classes(char ***classes, int *nclasses);
92int security_get_permissions(char *class, char ***perms, int *nperms);
93
90#define SECURITY_FS_USE_XATTR 1 /* use xattr */ 94#define SECURITY_FS_USE_XATTR 1 /* use xattr */
91#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ 95#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
92#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ 96#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index e64eca246f1a..8192e8bc9f5a 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -158,9 +158,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
158 netlbl_secattr_init(&secattr); 158 netlbl_secattr_init(&secattr);
159 rc = netlbl_skbuff_getattr(skb, &secattr); 159 rc = netlbl_skbuff_getattr(skb, &secattr);
160 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 160 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
161 rc = security_netlbl_secattr_to_sid(&secattr, 161 rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid);
162 base_sid,
163 sid);
164 else 162 else
165 *sid = SECSID_NULL; 163 *sid = SECSID_NULL;
166 netlbl_secattr_destroy(&secattr); 164 netlbl_secattr_destroy(&secattr);
@@ -198,7 +196,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
198 if (netlbl_sock_getattr(sk, &secattr) == 0 && 196 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
199 secattr.flags != NETLBL_SECATTR_NONE && 197 secattr.flags != NETLBL_SECATTR_NONE &&
200 security_netlbl_secattr_to_sid(&secattr, 198 security_netlbl_secattr_to_sid(&secattr,
201 SECINITSID_UNLABELED, 199 SECINITSID_NETMSG,
202 &nlbl_peer_sid) == 0) 200 &nlbl_peer_sid) == 0)
203 sksec->peer_sid = nlbl_peer_sid; 201 sksec->peer_sid = nlbl_peer_sid;
204 netlbl_secattr_destroy(&secattr); 202 netlbl_secattr_destroy(&secattr);
@@ -295,38 +293,32 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
295 struct avc_audit_data *ad) 293 struct avc_audit_data *ad)
296{ 294{
297 int rc; 295 int rc;
298 u32 netlbl_sid; 296 u32 nlbl_sid;
299 u32 recv_perm; 297 u32 perm;
300 298
301 rc = selinux_netlbl_skbuff_getsid(skb, 299 rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &nlbl_sid);
302 SECINITSID_UNLABELED,
303 &netlbl_sid);
304 if (rc != 0) 300 if (rc != 0)
305 return rc; 301 return rc;
306 302 if (nlbl_sid == SECSID_NULL)
307 if (netlbl_sid == SECSID_NULL) 303 nlbl_sid = SECINITSID_UNLABELED;
308 return 0;
309 304
310 switch (sksec->sclass) { 305 switch (sksec->sclass) {
311 case SECCLASS_UDP_SOCKET: 306 case SECCLASS_UDP_SOCKET:
312 recv_perm = UDP_SOCKET__RECVFROM; 307 perm = UDP_SOCKET__RECVFROM;
313 break; 308 break;
314 case SECCLASS_TCP_SOCKET: 309 case SECCLASS_TCP_SOCKET:
315 recv_perm = TCP_SOCKET__RECVFROM; 310 perm = TCP_SOCKET__RECVFROM;
316 break; 311 break;
317 default: 312 default:
318 recv_perm = RAWIP_SOCKET__RECVFROM; 313 perm = RAWIP_SOCKET__RECVFROM;
319 } 314 }
320 315
321 rc = avc_has_perm(sksec->sid, 316 rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
322 netlbl_sid,
323 sksec->sclass,
324 recv_perm,
325 ad);
326 if (rc == 0) 317 if (rc == 0)
327 return 0; 318 return 0;
328 319
329 netlbl_skbuff_err(skb, rc); 320 if (nlbl_sid != SECINITSID_UNLABELED)
321 netlbl_skbuff_err(skb, rc);
330 return rc; 322 return rc;
331} 323}
332 324
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index aca099aa2ed3..c9e92daedee2 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -67,6 +67,10 @@ static struct dentry *bool_dir = NULL;
67static int bool_num = 0; 67static int bool_num = 0;
68static int *bool_pending_values = NULL; 68static int *bool_pending_values = NULL;
69 69
70/* global data for classes */
71static struct dentry *class_dir = NULL;
72static unsigned long last_class_ino;
73
70extern void selnl_notify_setenforce(int val); 74extern void selnl_notify_setenforce(int val);
71 75
72/* Check whether a task is allowed to use a security operation. */ 76/* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
106 110
107#define SEL_INITCON_INO_OFFSET 0x01000000 111#define SEL_INITCON_INO_OFFSET 0x01000000
108#define SEL_BOOL_INO_OFFSET 0x02000000 112#define SEL_BOOL_INO_OFFSET 0x02000000
113#define SEL_CLASS_INO_OFFSET 0x04000000
109#define SEL_INO_MASK 0x00ffffff 114#define SEL_INO_MASK 0x00ffffff
110 115
111#define TMPBUFLEN 12 116#define TMPBUFLEN 12
@@ -237,6 +242,11 @@ static const struct file_operations sel_policyvers_ops = {
237 242
238/* declaration for sel_write_load */ 243/* declaration for sel_write_load */
239static int sel_make_bools(void); 244static int sel_make_bools(void);
245static int sel_make_classes(void);
246
247/* declaration for sel_make_class_dirs */
248static int sel_make_dir(struct inode *dir, struct dentry *dentry,
249 unsigned long *ino);
240 250
241static ssize_t sel_read_mls(struct file *filp, char __user *buf, 251static ssize_t sel_read_mls(struct file *filp, char __user *buf,
242 size_t count, loff_t *ppos) 252 size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
287 goto out; 297 goto out;
288 298
289 ret = sel_make_bools(); 299 ret = sel_make_bools();
300 if (ret) {
301 length = ret;
302 goto out1;
303 }
304
305 ret = sel_make_classes();
290 if (ret) 306 if (ret)
291 length = ret; 307 length = ret;
292 else 308 else
293 length = count; 309 length = count;
310
311out1:
294 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, 312 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
295 "policy loaded auid=%u", 313 "policy loaded auid=%u",
296 audit_get_loginuid(current->audit_context)); 314 audit_get_loginuid(current->audit_context));
@@ -940,9 +958,8 @@ static const struct file_operations sel_commit_bools_ops = {
940 .write = sel_commit_bools_write, 958 .write = sel_commit_bools_write,
941}; 959};
942 960
943/* delete booleans - partial revoke() from 961/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
944 * fs/proc/generic.c proc_kill_inodes */ 962static void sel_remove_entries(struct dentry *de)
945static void sel_remove_bools(struct dentry *de)
946{ 963{
947 struct list_head *p, *node; 964 struct list_head *p, *node;
948 struct super_block *sb = de->d_sb; 965 struct super_block *sb = de->d_sb;
@@ -998,7 +1015,7 @@ static int sel_make_bools(void)
998 kfree(bool_pending_values); 1015 kfree(bool_pending_values);
999 bool_pending_values = NULL; 1016 bool_pending_values = NULL;
1000 1017
1001 sel_remove_bools(dir); 1018 sel_remove_entries(dir);
1002 1019
1003 if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) 1020 if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
1004 return -ENOMEM; 1021 return -ENOMEM;
@@ -1048,7 +1065,7 @@ out:
1048 return ret; 1065 return ret;
1049err: 1066err:
1050 kfree(values); 1067 kfree(values);
1051 sel_remove_bools(dir); 1068 sel_remove_entries(dir);
1052 ret = -ENOMEM; 1069 ret = -ENOMEM;
1053 goto out; 1070 goto out;
1054} 1071}
@@ -1294,7 +1311,227 @@ out:
1294 return ret; 1311 return ret;
1295} 1312}
1296 1313
1297static int sel_make_dir(struct inode *dir, struct dentry *dentry) 1314static inline unsigned int sel_div(unsigned long a, unsigned long b)
1315{
1316 return a / b - (a % b < 0);
1317}
1318
1319static inline unsigned long sel_class_to_ino(u16 class)
1320{
1321 return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
1322}
1323
1324static inline u16 sel_ino_to_class(unsigned long ino)
1325{
1326 return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
1327}
1328
1329static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
1330{
1331 return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
1332}
1333
1334static inline u32 sel_ino_to_perm(unsigned long ino)
1335{
1336 return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
1337}
1338
1339static ssize_t sel_read_class(struct file * file, char __user *buf,
1340 size_t count, loff_t *ppos)
1341{
1342 ssize_t rc, len;
1343 char *page;
1344 unsigned long ino = file->f_path.dentry->d_inode->i_ino;
1345
1346 page = (char *)__get_free_page(GFP_KERNEL);
1347 if (!page) {
1348 rc = -ENOMEM;
1349 goto out;
1350 }
1351
1352 len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
1353 rc = simple_read_from_buffer(buf, count, ppos, page, len);
1354 free_page((unsigned long)page);
1355out:
1356 return rc;
1357}
1358
1359static const struct file_operations sel_class_ops = {
1360 .read = sel_read_class,
1361};
1362
1363static ssize_t sel_read_perm(struct file * file, char __user *buf,
1364 size_t count, loff_t *ppos)
1365{
1366 ssize_t rc, len;
1367 char *page;
1368 unsigned long ino = file->f_path.dentry->d_inode->i_ino;
1369
1370 page = (char *)__get_free_page(GFP_KERNEL);
1371 if (!page) {
1372 rc = -ENOMEM;
1373 goto out;
1374 }
1375
1376 len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
1377 rc = simple_read_from_buffer(buf, count, ppos, page, len);
1378 free_page((unsigned long)page);
1379out:
1380 return rc;
1381}
1382
1383static const struct file_operations sel_perm_ops = {
1384 .read = sel_read_perm,
1385};
1386
1387static int sel_make_perm_files(char *objclass, int classvalue,
1388 struct dentry *dir)
1389{
1390 int i, rc = 0, nperms;
1391 char **perms;
1392
1393 rc = security_get_permissions(objclass, &perms, &nperms);
1394 if (rc)
1395 goto out;
1396
1397 for (i = 0; i < nperms; i++) {
1398 struct inode *inode;
1399 struct dentry *dentry;
1400
1401 dentry = d_alloc_name(dir, perms[i]);
1402 if (!dentry) {
1403 rc = -ENOMEM;
1404 goto out1;
1405 }
1406
1407 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
1408 if (!inode) {
1409 rc = -ENOMEM;
1410 goto out1;
1411 }
1412 inode->i_fop = &sel_perm_ops;
1413 /* i+1 since perm values are 1-indexed */
1414 inode->i_ino = sel_perm_to_ino(classvalue, i+1);
1415 d_add(dentry, inode);
1416 }
1417
1418out1:
1419 for (i = 0; i < nperms; i++)
1420 kfree(perms[i]);
1421 kfree(perms);
1422out:
1423 return rc;
1424}
1425
1426static int sel_make_class_dir_entries(char *classname, int index,
1427 struct dentry *dir)
1428{
1429 struct dentry *dentry = NULL;
1430 struct inode *inode = NULL;
1431 int rc;
1432
1433 dentry = d_alloc_name(dir, "index");
1434 if (!dentry) {
1435 rc = -ENOMEM;
1436 goto out;
1437 }
1438
1439 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
1440 if (!inode) {
1441 rc = -ENOMEM;
1442 goto out;
1443 }
1444
1445 inode->i_fop = &sel_class_ops;
1446 inode->i_ino = sel_class_to_ino(index);
1447 d_add(dentry, inode);
1448
1449 dentry = d_alloc_name(dir, "perms");
1450 if (!dentry) {
1451 rc = -ENOMEM;
1452 goto out;
1453 }
1454
1455 rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
1456 if (rc)
1457 goto out;
1458
1459 rc = sel_make_perm_files(classname, index, dentry);
1460
1461out:
1462 return rc;
1463}
1464
1465static void sel_remove_classes(void)
1466{
1467 struct list_head *class_node;
1468
1469 list_for_each(class_node, &class_dir->d_subdirs) {
1470 struct dentry *class_subdir = list_entry(class_node,
1471 struct dentry, d_u.d_child);
1472 struct list_head *class_subdir_node;
1473
1474 list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
1475 struct dentry *d = list_entry(class_subdir_node,
1476 struct dentry, d_u.d_child);
1477
1478 if (d->d_inode)
1479 if (d->d_inode->i_mode & S_IFDIR)
1480 sel_remove_entries(d);
1481 }
1482
1483 sel_remove_entries(class_subdir);
1484 }
1485
1486 sel_remove_entries(class_dir);
1487}
1488
1489static int sel_make_classes(void)
1490{
1491 int rc = 0, nclasses, i;
1492 char **classes;
1493
1494 /* delete any existing entries */
1495 sel_remove_classes();
1496
1497 rc = security_get_classes(&classes, &nclasses);
1498 if (rc < 0)
1499 goto out;
1500
1501 /* +2 since classes are 1-indexed */
1502 last_class_ino = sel_class_to_ino(nclasses+2);
1503
1504 for (i = 0; i < nclasses; i++) {
1505 struct dentry *class_name_dir;
1506
1507 class_name_dir = d_alloc_name(class_dir, classes[i]);
1508 if (!class_name_dir) {
1509 rc = -ENOMEM;
1510 goto out1;
1511 }
1512
1513 rc = sel_make_dir(class_dir->d_inode, class_name_dir,
1514 &last_class_ino);
1515 if (rc)
1516 goto out1;
1517
1518 /* i+1 since class values are 1-indexed */
1519 rc = sel_make_class_dir_entries(classes[i], i+1,
1520 class_name_dir);
1521 if (rc)
1522 goto out1;
1523 }
1524
1525out1:
1526 for (i = 0; i < nclasses; i++)
1527 kfree(classes[i]);
1528 kfree(classes);
1529out:
1530 return rc;
1531}
1532
1533static int sel_make_dir(struct inode *dir, struct dentry *dentry,
1534 unsigned long *ino)
1298{ 1535{
1299 int ret = 0; 1536 int ret = 0;
1300 struct inode *inode; 1537 struct inode *inode;
@@ -1306,7 +1543,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
1306 } 1543 }
1307 inode->i_op = &simple_dir_inode_operations; 1544 inode->i_op = &simple_dir_inode_operations;
1308 inode->i_fop = &simple_dir_operations; 1545 inode->i_fop = &simple_dir_operations;
1309 inode->i_ino = ++sel_last_ino; 1546 inode->i_ino = ++(*ino);
1310 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 1547 /* directory inodes start off with i_nlink == 2 (for "." entry) */
1311 inc_nlink(inode); 1548 inc_nlink(inode);
1312 d_add(dentry, inode); 1549 d_add(dentry, inode);
@@ -1352,7 +1589,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1352 goto err; 1589 goto err;
1353 } 1590 }
1354 1591
1355 ret = sel_make_dir(root_inode, dentry); 1592 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1356 if (ret) 1593 if (ret)
1357 goto err; 1594 goto err;
1358 1595
@@ -1385,7 +1622,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1385 goto err; 1622 goto err;
1386 } 1623 }
1387 1624
1388 ret = sel_make_dir(root_inode, dentry); 1625 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1389 if (ret) 1626 if (ret)
1390 goto err; 1627 goto err;
1391 1628
@@ -1399,7 +1636,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1399 goto err; 1636 goto err;
1400 } 1637 }
1401 1638
1402 ret = sel_make_dir(root_inode, dentry); 1639 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1403 if (ret) 1640 if (ret)
1404 goto err; 1641 goto err;
1405 1642
@@ -1407,6 +1644,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1407 if (ret) 1644 if (ret)
1408 goto err; 1645 goto err;
1409 1646
1647 dentry = d_alloc_name(sb->s_root, "class");
1648 if (!dentry) {
1649 ret = -ENOMEM;
1650 goto err;
1651 }
1652
1653 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1654 if (ret)
1655 goto err;
1656
1657 class_dir = dentry;
1658
1410out: 1659out:
1411 return ret; 1660 return ret;
1412err: 1661err:
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac1021734c0..f05f97a2bc3a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/sched.h>
24#include <linux/slab.h> 25#include <linux/slab.h>
25#include <linux/string.h> 26#include <linux/string.h>
26#include <linux/errno.h> 27#include <linux/errno.h>
@@ -598,6 +599,7 @@ void policydb_destroy(struct policydb *p)
598 struct range_trans *rt, *lrt = NULL; 599 struct range_trans *rt, *lrt = NULL;
599 600
600 for (i = 0; i < SYM_NUM; i++) { 601 for (i = 0; i < SYM_NUM; i++) {
602 cond_resched();
601 hashtab_map(p->symtab[i].table, destroy_f[i], NULL); 603 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
602 hashtab_destroy(p->symtab[i].table); 604 hashtab_destroy(p->symtab[i].table);
603 } 605 }
@@ -612,6 +614,7 @@ void policydb_destroy(struct policydb *p)
612 avtab_destroy(&p->te_avtab); 614 avtab_destroy(&p->te_avtab);
613 615
614 for (i = 0; i < OCON_NUM; i++) { 616 for (i = 0; i < OCON_NUM; i++) {
617 cond_resched();
615 c = p->ocontexts[i]; 618 c = p->ocontexts[i];
616 while (c) { 619 while (c) {
617 ctmp = c; 620 ctmp = c;
@@ -623,6 +626,7 @@ void policydb_destroy(struct policydb *p)
623 626
624 g = p->genfs; 627 g = p->genfs;
625 while (g) { 628 while (g) {
629 cond_resched();
626 kfree(g->fstype); 630 kfree(g->fstype);
627 c = g->head; 631 c = g->head;
628 while (c) { 632 while (c) {
@@ -639,18 +643,21 @@ void policydb_destroy(struct policydb *p)
639 cond_policydb_destroy(p); 643 cond_policydb_destroy(p);
640 644
641 for (tr = p->role_tr; tr; tr = tr->next) { 645 for (tr = p->role_tr; tr; tr = tr->next) {
646 cond_resched();
642 kfree(ltr); 647 kfree(ltr);
643 ltr = tr; 648 ltr = tr;
644 } 649 }
645 kfree(ltr); 650 kfree(ltr);
646 651
647 for (ra = p->role_allow; ra; ra = ra -> next) { 652 for (ra = p->role_allow; ra; ra = ra -> next) {
653 cond_resched();
648 kfree(lra); 654 kfree(lra);
649 lra = ra; 655 lra = ra;
650 } 656 }
651 kfree(lra); 657 kfree(lra);
652 658
653 for (rt = p->range_tr; rt; rt = rt -> next) { 659 for (rt = p->range_tr; rt; rt = rt -> next) {
660 cond_resched();
654 if (lrt) { 661 if (lrt) {
655 ebitmap_destroy(&lrt->target_range.level[0].cat); 662 ebitmap_destroy(&lrt->target_range.level[0].cat);
656 ebitmap_destroy(&lrt->target_range.level[1].cat); 663 ebitmap_destroy(&lrt->target_range.level[1].cat);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 40660ffd49b6..b5f017f07a75 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1587,19 +1587,18 @@ int security_get_user_sids(u32 fromsid,
1587 u32 *nel) 1587 u32 *nel)
1588{ 1588{
1589 struct context *fromcon, usercon; 1589 struct context *fromcon, usercon;
1590 u32 *mysids, *mysids2, sid; 1590 u32 *mysids = NULL, *mysids2, sid;
1591 u32 mynel = 0, maxnel = SIDS_NEL; 1591 u32 mynel = 0, maxnel = SIDS_NEL;
1592 struct user_datum *user; 1592 struct user_datum *user;
1593 struct role_datum *role; 1593 struct role_datum *role;
1594 struct av_decision avd;
1595 struct ebitmap_node *rnode, *tnode; 1594 struct ebitmap_node *rnode, *tnode;
1596 int rc = 0, i, j; 1595 int rc = 0, i, j;
1597 1596
1598 if (!ss_initialized) { 1597 *sids = NULL;
1599 *sids = NULL; 1598 *nel = 0;
1600 *nel = 0; 1599
1600 if (!ss_initialized)
1601 goto out; 1601 goto out;
1602 }
1603 1602
1604 POLICY_RDLOCK; 1603 POLICY_RDLOCK;
1605 1604
@@ -1635,17 +1634,9 @@ int security_get_user_sids(u32 fromsid,
1635 if (mls_setup_user_range(fromcon, user, &usercon)) 1634 if (mls_setup_user_range(fromcon, user, &usercon))
1636 continue; 1635 continue;
1637 1636
1638 rc = context_struct_compute_av(fromcon, &usercon,
1639 SECCLASS_PROCESS,
1640 PROCESS__TRANSITION,
1641 &avd);
1642 if (rc || !(avd.allowed & PROCESS__TRANSITION))
1643 continue;
1644 rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); 1637 rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
1645 if (rc) { 1638 if (rc)
1646 kfree(mysids);
1647 goto out_unlock; 1639 goto out_unlock;
1648 }
1649 if (mynel < maxnel) { 1640 if (mynel < maxnel) {
1650 mysids[mynel++] = sid; 1641 mysids[mynel++] = sid;
1651 } else { 1642 } else {
@@ -1653,7 +1644,6 @@ int security_get_user_sids(u32 fromsid,
1653 mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); 1644 mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
1654 if (!mysids2) { 1645 if (!mysids2) {
1655 rc = -ENOMEM; 1646 rc = -ENOMEM;
1656 kfree(mysids);
1657 goto out_unlock; 1647 goto out_unlock;
1658 } 1648 }
1659 memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); 1649 memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@ int security_get_user_sids(u32 fromsid,
1664 } 1654 }
1665 } 1655 }
1666 1656
1667 *sids = mysids;
1668 *nel = mynel;
1669
1670out_unlock: 1657out_unlock:
1671 POLICY_RDUNLOCK; 1658 POLICY_RDUNLOCK;
1659 if (rc || !mynel) {
1660 kfree(mysids);
1661 goto out;
1662 }
1663
1664 mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
1665 if (!mysids2) {
1666 rc = -ENOMEM;
1667 kfree(mysids);
1668 goto out;
1669 }
1670 for (i = 0, j = 0; i < mynel; i++) {
1671 rc = avc_has_perm_noaudit(fromsid, mysids[i],
1672 SECCLASS_PROCESS,
1673 PROCESS__TRANSITION, AVC_STRICT,
1674 NULL);
1675 if (!rc)
1676 mysids2[j++] = mysids[i];
1677 cond_resched();
1678 }
1679 rc = 0;
1680 kfree(mysids);
1681 *sids = mysids2;
1682 *nel = j;
1672out: 1683out:
1673 return rc; 1684 return rc;
1674} 1685}
@@ -1996,6 +2007,101 @@ out:
1996 return rc; 2007 return rc;
1997} 2008}
1998 2009
2010static int get_classes_callback(void *k, void *d, void *args)
2011{
2012 struct class_datum *datum = d;
2013 char *name = k, **classes = args;
2014 int value = datum->value - 1;
2015
2016 classes[value] = kstrdup(name, GFP_ATOMIC);
2017 if (!classes[value])
2018 return -ENOMEM;
2019
2020 return 0;
2021}
2022
2023int security_get_classes(char ***classes, int *nclasses)
2024{
2025 int rc = -ENOMEM;
2026
2027 POLICY_RDLOCK;
2028
2029 *nclasses = policydb.p_classes.nprim;
2030 *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
2031 if (!*classes)
2032 goto out;
2033
2034 rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
2035 *classes);
2036 if (rc < 0) {
2037 int i;
2038 for (i = 0; i < *nclasses; i++)
2039 kfree((*classes)[i]);
2040 kfree(*classes);
2041 }
2042
2043out:
2044 POLICY_RDUNLOCK;
2045 return rc;
2046}
2047
2048static int get_permissions_callback(void *k, void *d, void *args)
2049{
2050 struct perm_datum *datum = d;
2051 char *name = k, **perms = args;
2052 int value = datum->value - 1;
2053
2054 perms[value] = kstrdup(name, GFP_ATOMIC);
2055 if (!perms[value])
2056 return -ENOMEM;
2057
2058 return 0;
2059}
2060
2061int security_get_permissions(char *class, char ***perms, int *nperms)
2062{
2063 int rc = -ENOMEM, i;
2064 struct class_datum *match;
2065
2066 POLICY_RDLOCK;
2067
2068 match = hashtab_search(policydb.p_classes.table, class);
2069 if (!match) {
2070 printk(KERN_ERR "%s: unrecognized class %s\n",
2071 __FUNCTION__, class);
2072 rc = -EINVAL;
2073 goto out;
2074 }
2075
2076 *nperms = match->permissions.nprim;
2077 *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
2078 if (!*perms)
2079 goto out;
2080
2081 if (match->comdatum) {
2082 rc = hashtab_map(match->comdatum->permissions.table,
2083 get_permissions_callback, *perms);
2084 if (rc < 0)
2085 goto err;
2086 }
2087
2088 rc = hashtab_map(match->permissions.table, get_permissions_callback,
2089 *perms);
2090 if (rc < 0)
2091 goto err;
2092
2093out:
2094 POLICY_RDUNLOCK;
2095 return rc;
2096
2097err:
2098 POLICY_RDUNLOCK;
2099 for (i = 0; i < *nperms; i++)
2100 kfree((*perms)[i]);
2101 kfree(*perms);
2102 return rc;
2103}
2104
1999struct selinux_audit_rule { 2105struct selinux_audit_rule {
2000 u32 au_seqno; 2106 u32 au_seqno;
2001 struct context au_ctxt; 2107 struct context au_ctxt;