diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/avc.c | 10 | ||||
-rw-r--r-- | security/selinux/hooks.c | 9 | ||||
-rw-r--r-- | security/selinux/include/avc.h | 6 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 49 |
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 | */ |
848 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 849 | int 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. */ | ||
105 | int avc_has_perm_noaudit(u32 ssid, u32 tsid, | 106 | int 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 | ||
109 | int avc_has_perm(u32 ssid, u32 tsid, | 111 | int 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 | |||
1670 | out_unlock: | 1657 | out_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; | ||
1672 | out: | 1683 | out: |
1673 | return rc; | 1684 | return rc; |
1674 | } | 1685 | } |