diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 144 |
1 files changed, 125 insertions, 19 deletions
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 | |||
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 | } |
@@ -1996,6 +2007,101 @@ out: | |||
1996 | return rc; | 2007 | return rc; |
1997 | } | 2008 | } |
1998 | 2009 | ||
2010 | static 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 | |||
2023 | int 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 | |||
2043 | out: | ||
2044 | POLICY_RDUNLOCK; | ||
2045 | return rc; | ||
2046 | } | ||
2047 | |||
2048 | static 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 | |||
2061 | int 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 | |||
2093 | out: | ||
2094 | POLICY_RDUNLOCK; | ||
2095 | return rc; | ||
2096 | |||
2097 | err: | ||
2098 | POLICY_RDUNLOCK; | ||
2099 | for (i = 0; i < *nperms; i++) | ||
2100 | kfree((*perms)[i]); | ||
2101 | kfree(*perms); | ||
2102 | return rc; | ||
2103 | } | ||
2104 | |||
1999 | struct selinux_audit_rule { | 2105 | struct selinux_audit_rule { |
2000 | u32 au_seqno; | 2106 | u32 au_seqno; |
2001 | struct context au_ctxt; | 2107 | struct context au_ctxt; |