diff options
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/services.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8ee04a424df7..7f0ee1b91e1d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2054,6 +2054,91 @@ out: | |||
2054 | return rc; | 2054 | return rc; |
2055 | } | 2055 | } |
2056 | 2056 | ||
2057 | /** | ||
2058 | * security_net_peersid_resolve - Compare and resolve two network peer SIDs | ||
2059 | * @nlbl_sid: NetLabel SID | ||
2060 | * @nlbl_type: NetLabel labeling protocol type | ||
2061 | * @xfrm_sid: XFRM SID | ||
2062 | * | ||
2063 | * Description: | ||
2064 | * Compare the @nlbl_sid and @xfrm_sid values and if the two SIDs can be | ||
2065 | * resolved into a single SID it is returned via @peer_sid and the function | ||
2066 | * returns zero. Otherwise @peer_sid is set to SECSID_NULL and the function | ||
2067 | * returns a negative value. A table summarizing the behavior is below: | ||
2068 | * | ||
2069 | * | function return | @sid | ||
2070 | * ------------------------------+-----------------+----------------- | ||
2071 | * no peer labels | 0 | SECSID_NULL | ||
2072 | * single peer label | 0 | <peer_label> | ||
2073 | * multiple, consistent labels | 0 | <peer_label> | ||
2074 | * multiple, inconsistent labels | -<errno> | SECSID_NULL | ||
2075 | * | ||
2076 | */ | ||
2077 | int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | ||
2078 | u32 xfrm_sid, | ||
2079 | u32 *peer_sid) | ||
2080 | { | ||
2081 | int rc; | ||
2082 | struct context *nlbl_ctx; | ||
2083 | struct context *xfrm_ctx; | ||
2084 | |||
2085 | /* handle the common (which also happens to be the set of easy) cases | ||
2086 | * right away, these two if statements catch everything involving a | ||
2087 | * single or absent peer SID/label */ | ||
2088 | if (xfrm_sid == SECSID_NULL) { | ||
2089 | *peer_sid = nlbl_sid; | ||
2090 | return 0; | ||
2091 | } | ||
2092 | /* NOTE: an nlbl_type == NETLBL_NLTYPE_UNLABELED is a "fallback" label | ||
2093 | * and is treated as if nlbl_sid == SECSID_NULL when a XFRM SID/label | ||
2094 | * is present */ | ||
2095 | if (nlbl_sid == SECSID_NULL || nlbl_type == NETLBL_NLTYPE_UNLABELED) { | ||
2096 | *peer_sid = xfrm_sid; | ||
2097 | return 0; | ||
2098 | } | ||
2099 | |||
2100 | /* we don't need to check ss_initialized here since the only way both | ||
2101 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | ||
2102 | * security server was initialized and ss_initialized was true */ | ||
2103 | if (!selinux_mls_enabled) { | ||
2104 | *peer_sid = SECSID_NULL; | ||
2105 | return 0; | ||
2106 | } | ||
2107 | |||
2108 | POLICY_RDLOCK; | ||
2109 | |||
2110 | nlbl_ctx = sidtab_search(&sidtab, nlbl_sid); | ||
2111 | if (!nlbl_ctx) { | ||
2112 | printk(KERN_ERR | ||
2113 | "security_sid_mls_cmp: unrecognized SID %d\n", | ||
2114 | nlbl_sid); | ||
2115 | rc = -EINVAL; | ||
2116 | goto out_slowpath; | ||
2117 | } | ||
2118 | xfrm_ctx = sidtab_search(&sidtab, xfrm_sid); | ||
2119 | if (!xfrm_ctx) { | ||
2120 | printk(KERN_ERR | ||
2121 | "security_sid_mls_cmp: unrecognized SID %d\n", | ||
2122 | xfrm_sid); | ||
2123 | rc = -EINVAL; | ||
2124 | goto out_slowpath; | ||
2125 | } | ||
2126 | rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); | ||
2127 | |||
2128 | out_slowpath: | ||
2129 | POLICY_RDUNLOCK; | ||
2130 | if (rc == 0) | ||
2131 | /* at present NetLabel SIDs/labels really only carry MLS | ||
2132 | * information so if the MLS portion of the NetLabel SID | ||
2133 | * matches the MLS portion of the labeled XFRM SID/label | ||
2134 | * then pass along the XFRM SID as it is the most | ||
2135 | * expressive */ | ||
2136 | *peer_sid = xfrm_sid; | ||
2137 | else | ||
2138 | *peer_sid = SECSID_NULL; | ||
2139 | return rc; | ||
2140 | } | ||
2141 | |||
2057 | static int get_classes_callback(void *k, void *d, void *args) | 2142 | static int get_classes_callback(void *k, void *d, void *args) |
2058 | { | 2143 | { |
2059 | struct class_datum *datum = d; | 2144 | struct class_datum *datum = d; |