aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-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
14 files changed, 453 insertions, 76 deletions
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;