aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/avc.c10
-rw-r--r--security/selinux/hooks.c9
-rw-r--r--security/selinux/include/avc.h6
-rw-r--r--security/selinux/ss/services.c49
4 files changed, 45 insertions, 29 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a89edc6..cc5fcef9e226 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -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..b29059ecc045 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;
@@ -4626,7 +4627,7 @@ static int selinux_setprocattr(struct task_struct *p,
4626 if (p->ptrace & PT_PTRACED) { 4627 if (p->ptrace & PT_PTRACED) {
4627 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, 4628 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
4628 SECCLASS_PROCESS, 4629 SECCLASS_PROCESS,
4629 PROCESS__PTRACE, &avd); 4630 PROCESS__PTRACE, 0, &avd);
4630 if (!error) 4631 if (!error)
4631 tsec->sid = sid; 4632 tsec->sid = sid;
4632 task_unlock(p); 4633 task_unlock(p);
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/ss/services.c b/security/selinux/ss/services.c
index e4249adaa880..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}