aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r--security/selinux/ss/services.c85
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 */
2077int 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
2128out_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
2057static int get_classes_callback(void *k, void *d, void *args) 2142static int get_classes_callback(void *k, void *d, void *args)
2058{ 2143{
2059 struct class_datum *datum = d; 2144 struct class_datum *datum = d;