diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 49 |
1 files changed, 30 insertions, 19 deletions
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 | } |