diff options
author | Ondrej Mosnacek <omosnace@redhat.com> | 2018-11-30 10:24:07 -0500 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2018-12-05 15:36:12 -0500 |
commit | 24ed7fdae669feda4c5e0dadba2467c4c0d297d3 (patch) | |
tree | a26c76596744dab9c762d6d5915e9dc67b20e906 | |
parent | 89f5bebcf0401dac470756869587a50dd72ff7b5 (diff) |
selinux: use separate table for initial SID lookup
This moves handling of initial SIDs into a separate table. Note that the
SIDs stored in the main table are now shifted by SECINITSID_NUM and
converted to/from the actual SIDs transparently by helper functions.
This change doesn't make much sense on its own, but it simplifies
further sidtab overhaul in a succeeding patch.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Reviewed-by: Stephen Smalley <sds@tycho.nsa.gov>
[PM: fixed some checkpatch warnings on line length, whitespace]
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | security/selinux/ss/policydb.c | 10 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 88 | ||||
-rw-r--r-- | security/selinux/ss/services.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.c | 168 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.h | 15 |
5 files changed, 173 insertions, 110 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index b63ef865ce1e..a50d625e7946 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -909,13 +909,21 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) | |||
909 | if (!c->context[0].user) { | 909 | if (!c->context[0].user) { |
910 | pr_err("SELinux: SID %s was never defined.\n", | 910 | pr_err("SELinux: SID %s was never defined.\n", |
911 | c->u.name); | 911 | c->u.name); |
912 | sidtab_destroy(s); | ||
913 | goto out; | ||
914 | } | ||
915 | if (c->sid[0] == SECSID_NULL || c->sid[0] > SECINITSID_NUM) { | ||
916 | pr_err("SELinux: Initial SID %s out of range.\n", | ||
917 | c->u.name); | ||
918 | sidtab_destroy(s); | ||
912 | goto out; | 919 | goto out; |
913 | } | 920 | } |
914 | 921 | ||
915 | rc = sidtab_insert(s, c->sid[0], &c->context[0]); | 922 | rc = sidtab_set_initial(s, c->sid[0], &c->context[0]); |
916 | if (rc) { | 923 | if (rc) { |
917 | pr_err("SELinux: unable to load initial SID %s.\n", | 924 | pr_err("SELinux: unable to load initial SID %s.\n", |
918 | c->u.name); | 925 | c->u.name); |
926 | sidtab_destroy(s); | ||
919 | goto out; | 927 | goto out; |
920 | } | 928 | } |
921 | } | 929 | } |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 0458f4cecff8..4ff4b0edbf6b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -776,7 +776,7 @@ static int security_compute_validatetrans(struct selinux_state *state, | |||
776 | read_lock(&state->ss->policy_rwlock); | 776 | read_lock(&state->ss->policy_rwlock); |
777 | 777 | ||
778 | policydb = &state->ss->policydb; | 778 | policydb = &state->ss->policydb; |
779 | sidtab = &state->ss->sidtab; | 779 | sidtab = state->ss->sidtab; |
780 | 780 | ||
781 | if (!user) | 781 | if (!user) |
782 | tclass = unmap_class(&state->ss->map, orig_tclass); | 782 | tclass = unmap_class(&state->ss->map, orig_tclass); |
@@ -876,7 +876,7 @@ int security_bounded_transition(struct selinux_state *state, | |||
876 | read_lock(&state->ss->policy_rwlock); | 876 | read_lock(&state->ss->policy_rwlock); |
877 | 877 | ||
878 | policydb = &state->ss->policydb; | 878 | policydb = &state->ss->policydb; |
879 | sidtab = &state->ss->sidtab; | 879 | sidtab = state->ss->sidtab; |
880 | 880 | ||
881 | rc = -EINVAL; | 881 | rc = -EINVAL; |
882 | old_context = sidtab_search(sidtab, old_sid); | 882 | old_context = sidtab_search(sidtab, old_sid); |
@@ -1034,7 +1034,7 @@ void security_compute_xperms_decision(struct selinux_state *state, | |||
1034 | goto allow; | 1034 | goto allow; |
1035 | 1035 | ||
1036 | policydb = &state->ss->policydb; | 1036 | policydb = &state->ss->policydb; |
1037 | sidtab = &state->ss->sidtab; | 1037 | sidtab = state->ss->sidtab; |
1038 | 1038 | ||
1039 | scontext = sidtab_search(sidtab, ssid); | 1039 | scontext = sidtab_search(sidtab, ssid); |
1040 | if (!scontext) { | 1040 | if (!scontext) { |
@@ -1123,7 +1123,7 @@ void security_compute_av(struct selinux_state *state, | |||
1123 | goto allow; | 1123 | goto allow; |
1124 | 1124 | ||
1125 | policydb = &state->ss->policydb; | 1125 | policydb = &state->ss->policydb; |
1126 | sidtab = &state->ss->sidtab; | 1126 | sidtab = state->ss->sidtab; |
1127 | 1127 | ||
1128 | scontext = sidtab_search(sidtab, ssid); | 1128 | scontext = sidtab_search(sidtab, ssid); |
1129 | if (!scontext) { | 1129 | if (!scontext) { |
@@ -1177,7 +1177,7 @@ void security_compute_av_user(struct selinux_state *state, | |||
1177 | goto allow; | 1177 | goto allow; |
1178 | 1178 | ||
1179 | policydb = &state->ss->policydb; | 1179 | policydb = &state->ss->policydb; |
1180 | sidtab = &state->ss->sidtab; | 1180 | sidtab = state->ss->sidtab; |
1181 | 1181 | ||
1182 | scontext = sidtab_search(sidtab, ssid); | 1182 | scontext = sidtab_search(sidtab, ssid); |
1183 | if (!scontext) { | 1183 | if (!scontext) { |
@@ -1315,7 +1315,7 @@ static int security_sid_to_context_core(struct selinux_state *state, | |||
1315 | } | 1315 | } |
1316 | read_lock(&state->ss->policy_rwlock); | 1316 | read_lock(&state->ss->policy_rwlock); |
1317 | policydb = &state->ss->policydb; | 1317 | policydb = &state->ss->policydb; |
1318 | sidtab = &state->ss->sidtab; | 1318 | sidtab = state->ss->sidtab; |
1319 | if (force) | 1319 | if (force) |
1320 | context = sidtab_search_force(sidtab, sid); | 1320 | context = sidtab_search_force(sidtab, sid); |
1321 | else | 1321 | else |
@@ -1483,7 +1483,7 @@ static int security_context_to_sid_core(struct selinux_state *state, | |||
1483 | } | 1483 | } |
1484 | read_lock(&state->ss->policy_rwlock); | 1484 | read_lock(&state->ss->policy_rwlock); |
1485 | policydb = &state->ss->policydb; | 1485 | policydb = &state->ss->policydb; |
1486 | sidtab = &state->ss->sidtab; | 1486 | sidtab = state->ss->sidtab; |
1487 | rc = string_to_context_struct(policydb, sidtab, scontext2, | 1487 | rc = string_to_context_struct(policydb, sidtab, scontext2, |
1488 | &context, def_sid); | 1488 | &context, def_sid); |
1489 | if (rc == -EINVAL && force) { | 1489 | if (rc == -EINVAL && force) { |
@@ -1668,7 +1668,7 @@ static int security_compute_sid(struct selinux_state *state, | |||
1668 | } | 1668 | } |
1669 | 1669 | ||
1670 | policydb = &state->ss->policydb; | 1670 | policydb = &state->ss->policydb; |
1671 | sidtab = &state->ss->sidtab; | 1671 | sidtab = state->ss->sidtab; |
1672 | 1672 | ||
1673 | scontext = sidtab_search(sidtab, ssid); | 1673 | scontext = sidtab_search(sidtab, ssid); |
1674 | if (!scontext) { | 1674 | if (!scontext) { |
@@ -1925,10 +1925,7 @@ static int convert_context(u32 key, | |||
1925 | struct user_datum *usrdatum; | 1925 | struct user_datum *usrdatum; |
1926 | char *s; | 1926 | char *s; |
1927 | u32 len; | 1927 | u32 len; |
1928 | int rc = 0; | 1928 | int rc; |
1929 | |||
1930 | if (key <= SECINITSID_NUM) | ||
1931 | goto out; | ||
1932 | 1929 | ||
1933 | args = p; | 1930 | args = p; |
1934 | 1931 | ||
@@ -2090,9 +2087,8 @@ static int security_preserve_bools(struct selinux_state *state, | |||
2090 | int security_load_policy(struct selinux_state *state, void *data, size_t len) | 2087 | int security_load_policy(struct selinux_state *state, void *data, size_t len) |
2091 | { | 2088 | { |
2092 | struct policydb *policydb; | 2089 | struct policydb *policydb; |
2093 | struct sidtab *sidtab; | 2090 | struct sidtab *oldsidtab, *newsidtab; |
2094 | struct policydb *oldpolicydb, *newpolicydb; | 2091 | struct policydb *oldpolicydb, *newpolicydb; |
2095 | struct sidtab oldsidtab, newsidtab; | ||
2096 | struct selinux_mapping *oldmapping; | 2092 | struct selinux_mapping *oldmapping; |
2097 | struct selinux_map newmap; | 2093 | struct selinux_map newmap; |
2098 | struct convert_context_args args; | 2094 | struct convert_context_args args; |
@@ -2108,27 +2104,37 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2108 | newpolicydb = oldpolicydb + 1; | 2104 | newpolicydb = oldpolicydb + 1; |
2109 | 2105 | ||
2110 | policydb = &state->ss->policydb; | 2106 | policydb = &state->ss->policydb; |
2111 | sidtab = &state->ss->sidtab; | 2107 | |
2108 | newsidtab = kmalloc(sizeof(*newsidtab), GFP_KERNEL); | ||
2109 | if (!newsidtab) { | ||
2110 | rc = -ENOMEM; | ||
2111 | goto out; | ||
2112 | } | ||
2112 | 2113 | ||
2113 | if (!state->initialized) { | 2114 | if (!state->initialized) { |
2114 | rc = policydb_read(policydb, fp); | 2115 | rc = policydb_read(policydb, fp); |
2115 | if (rc) | 2116 | if (rc) { |
2117 | kfree(newsidtab); | ||
2116 | goto out; | 2118 | goto out; |
2119 | } | ||
2117 | 2120 | ||
2118 | policydb->len = len; | 2121 | policydb->len = len; |
2119 | rc = selinux_set_mapping(policydb, secclass_map, | 2122 | rc = selinux_set_mapping(policydb, secclass_map, |
2120 | &state->ss->map); | 2123 | &state->ss->map); |
2121 | if (rc) { | 2124 | if (rc) { |
2125 | kfree(newsidtab); | ||
2122 | policydb_destroy(policydb); | 2126 | policydb_destroy(policydb); |
2123 | goto out; | 2127 | goto out; |
2124 | } | 2128 | } |
2125 | 2129 | ||
2126 | rc = policydb_load_isids(policydb, sidtab); | 2130 | rc = policydb_load_isids(policydb, newsidtab); |
2127 | if (rc) { | 2131 | if (rc) { |
2132 | kfree(newsidtab); | ||
2128 | policydb_destroy(policydb); | 2133 | policydb_destroy(policydb); |
2129 | goto out; | 2134 | goto out; |
2130 | } | 2135 | } |
2131 | 2136 | ||
2137 | state->ss->sidtab = newsidtab; | ||
2132 | security_load_policycaps(state); | 2138 | security_load_policycaps(state); |
2133 | state->initialized = 1; | 2139 | state->initialized = 1; |
2134 | seqno = ++state->ss->latest_granting; | 2140 | seqno = ++state->ss->latest_granting; |
@@ -2141,13 +2147,17 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2141 | goto out; | 2147 | goto out; |
2142 | } | 2148 | } |
2143 | 2149 | ||
2150 | oldsidtab = state->ss->sidtab; | ||
2151 | |||
2144 | #if 0 | 2152 | #if 0 |
2145 | sidtab_hash_eval(sidtab, "sids"); | 2153 | sidtab_hash_eval(oldsidtab, "sids"); |
2146 | #endif | 2154 | #endif |
2147 | 2155 | ||
2148 | rc = policydb_read(newpolicydb, fp); | 2156 | rc = policydb_read(newpolicydb, fp); |
2149 | if (rc) | 2157 | if (rc) { |
2158 | kfree(newsidtab); | ||
2150 | goto out; | 2159 | goto out; |
2160 | } | ||
2151 | 2161 | ||
2152 | newpolicydb->len = len; | 2162 | newpolicydb->len = len; |
2153 | /* If switching between different policy types, log MLS status */ | 2163 | /* If switching between different policy types, log MLS status */ |
@@ -2156,10 +2166,11 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2156 | else if (!policydb->mls_enabled && newpolicydb->mls_enabled) | 2166 | else if (!policydb->mls_enabled && newpolicydb->mls_enabled) |
2157 | pr_info("SELinux: Enabling MLS support...\n"); | 2167 | pr_info("SELinux: Enabling MLS support...\n"); |
2158 | 2168 | ||
2159 | rc = policydb_load_isids(newpolicydb, &newsidtab); | 2169 | rc = policydb_load_isids(newpolicydb, newsidtab); |
2160 | if (rc) { | 2170 | if (rc) { |
2161 | pr_err("SELinux: unable to load the initial SIDs\n"); | 2171 | pr_err("SELinux: unable to load the initial SIDs\n"); |
2162 | policydb_destroy(newpolicydb); | 2172 | policydb_destroy(newpolicydb); |
2173 | kfree(newsidtab); | ||
2163 | goto out; | 2174 | goto out; |
2164 | } | 2175 | } |
2165 | 2176 | ||
@@ -2180,7 +2191,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2180 | args.state = state; | 2191 | args.state = state; |
2181 | args.oldp = policydb; | 2192 | args.oldp = policydb; |
2182 | args.newp = newpolicydb; | 2193 | args.newp = newpolicydb; |
2183 | rc = sidtab_convert(sidtab, &newsidtab, convert_context, &args); | 2194 | rc = sidtab_convert(oldsidtab, newsidtab, convert_context, &args); |
2184 | if (rc) { | 2195 | if (rc) { |
2185 | pr_err("SELinux: unable to convert the internal" | 2196 | pr_err("SELinux: unable to convert the internal" |
2186 | " representation of contexts in the new SID" | 2197 | " representation of contexts in the new SID" |
@@ -2190,12 +2201,11 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2190 | 2201 | ||
2191 | /* Save the old policydb and SID table to free later. */ | 2202 | /* Save the old policydb and SID table to free later. */ |
2192 | memcpy(oldpolicydb, policydb, sizeof(*policydb)); | 2203 | memcpy(oldpolicydb, policydb, sizeof(*policydb)); |
2193 | sidtab_set(&oldsidtab, sidtab); | ||
2194 | 2204 | ||
2195 | /* Install the new policydb and SID table. */ | 2205 | /* Install the new policydb and SID table. */ |
2196 | write_lock_irq(&state->ss->policy_rwlock); | 2206 | write_lock_irq(&state->ss->policy_rwlock); |
2197 | memcpy(policydb, newpolicydb, sizeof(*policydb)); | 2207 | memcpy(policydb, newpolicydb, sizeof(*policydb)); |
2198 | sidtab_set(sidtab, &newsidtab); | 2208 | state->ss->sidtab = newsidtab; |
2199 | security_load_policycaps(state); | 2209 | security_load_policycaps(state); |
2200 | oldmapping = state->ss->map.mapping; | 2210 | oldmapping = state->ss->map.mapping; |
2201 | state->ss->map.mapping = newmap.mapping; | 2211 | state->ss->map.mapping = newmap.mapping; |
@@ -2205,7 +2215,8 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2205 | 2215 | ||
2206 | /* Free the old policydb and SID table. */ | 2216 | /* Free the old policydb and SID table. */ |
2207 | policydb_destroy(oldpolicydb); | 2217 | policydb_destroy(oldpolicydb); |
2208 | sidtab_destroy(&oldsidtab); | 2218 | sidtab_destroy(oldsidtab); |
2219 | kfree(oldsidtab); | ||
2209 | kfree(oldmapping); | 2220 | kfree(oldmapping); |
2210 | 2221 | ||
2211 | avc_ss_reset(state->avc, seqno); | 2222 | avc_ss_reset(state->avc, seqno); |
@@ -2219,7 +2230,8 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) | |||
2219 | 2230 | ||
2220 | err: | 2231 | err: |
2221 | kfree(newmap.mapping); | 2232 | kfree(newmap.mapping); |
2222 | sidtab_destroy(&newsidtab); | 2233 | sidtab_destroy(newsidtab); |
2234 | kfree(newsidtab); | ||
2223 | policydb_destroy(newpolicydb); | 2235 | policydb_destroy(newpolicydb); |
2224 | 2236 | ||
2225 | out: | 2237 | out: |
@@ -2256,7 +2268,7 @@ int security_port_sid(struct selinux_state *state, | |||
2256 | read_lock(&state->ss->policy_rwlock); | 2268 | read_lock(&state->ss->policy_rwlock); |
2257 | 2269 | ||
2258 | policydb = &state->ss->policydb; | 2270 | policydb = &state->ss->policydb; |
2259 | sidtab = &state->ss->sidtab; | 2271 | sidtab = state->ss->sidtab; |
2260 | 2272 | ||
2261 | c = policydb->ocontexts[OCON_PORT]; | 2273 | c = policydb->ocontexts[OCON_PORT]; |
2262 | while (c) { | 2274 | while (c) { |
@@ -2302,7 +2314,7 @@ int security_ib_pkey_sid(struct selinux_state *state, | |||
2302 | read_lock(&state->ss->policy_rwlock); | 2314 | read_lock(&state->ss->policy_rwlock); |
2303 | 2315 | ||
2304 | policydb = &state->ss->policydb; | 2316 | policydb = &state->ss->policydb; |
2305 | sidtab = &state->ss->sidtab; | 2317 | sidtab = state->ss->sidtab; |
2306 | 2318 | ||
2307 | c = policydb->ocontexts[OCON_IBPKEY]; | 2319 | c = policydb->ocontexts[OCON_IBPKEY]; |
2308 | while (c) { | 2320 | while (c) { |
@@ -2348,7 +2360,7 @@ int security_ib_endport_sid(struct selinux_state *state, | |||
2348 | read_lock(&state->ss->policy_rwlock); | 2360 | read_lock(&state->ss->policy_rwlock); |
2349 | 2361 | ||
2350 | policydb = &state->ss->policydb; | 2362 | policydb = &state->ss->policydb; |
2351 | sidtab = &state->ss->sidtab; | 2363 | sidtab = state->ss->sidtab; |
2352 | 2364 | ||
2353 | c = policydb->ocontexts[OCON_IBENDPORT]; | 2365 | c = policydb->ocontexts[OCON_IBENDPORT]; |
2354 | while (c) { | 2366 | while (c) { |
@@ -2394,7 +2406,7 @@ int security_netif_sid(struct selinux_state *state, | |||
2394 | read_lock(&state->ss->policy_rwlock); | 2406 | read_lock(&state->ss->policy_rwlock); |
2395 | 2407 | ||
2396 | policydb = &state->ss->policydb; | 2408 | policydb = &state->ss->policydb; |
2397 | sidtab = &state->ss->sidtab; | 2409 | sidtab = state->ss->sidtab; |
2398 | 2410 | ||
2399 | c = policydb->ocontexts[OCON_NETIF]; | 2411 | c = policydb->ocontexts[OCON_NETIF]; |
2400 | while (c) { | 2412 | while (c) { |
@@ -2459,7 +2471,7 @@ int security_node_sid(struct selinux_state *state, | |||
2459 | read_lock(&state->ss->policy_rwlock); | 2471 | read_lock(&state->ss->policy_rwlock); |
2460 | 2472 | ||
2461 | policydb = &state->ss->policydb; | 2473 | policydb = &state->ss->policydb; |
2462 | sidtab = &state->ss->sidtab; | 2474 | sidtab = state->ss->sidtab; |
2463 | 2475 | ||
2464 | switch (domain) { | 2476 | switch (domain) { |
2465 | case AF_INET: { | 2477 | case AF_INET: { |
@@ -2559,7 +2571,7 @@ int security_get_user_sids(struct selinux_state *state, | |||
2559 | read_lock(&state->ss->policy_rwlock); | 2571 | read_lock(&state->ss->policy_rwlock); |
2560 | 2572 | ||
2561 | policydb = &state->ss->policydb; | 2573 | policydb = &state->ss->policydb; |
2562 | sidtab = &state->ss->sidtab; | 2574 | sidtab = state->ss->sidtab; |
2563 | 2575 | ||
2564 | context_init(&usercon); | 2576 | context_init(&usercon); |
2565 | 2577 | ||
@@ -2661,7 +2673,7 @@ static inline int __security_genfs_sid(struct selinux_state *state, | |||
2661 | u32 *sid) | 2673 | u32 *sid) |
2662 | { | 2674 | { |
2663 | struct policydb *policydb = &state->ss->policydb; | 2675 | struct policydb *policydb = &state->ss->policydb; |
2664 | struct sidtab *sidtab = &state->ss->sidtab; | 2676 | struct sidtab *sidtab = state->ss->sidtab; |
2665 | int len; | 2677 | int len; |
2666 | u16 sclass; | 2678 | u16 sclass; |
2667 | struct genfs *genfs; | 2679 | struct genfs *genfs; |
@@ -2747,7 +2759,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) | |||
2747 | read_lock(&state->ss->policy_rwlock); | 2759 | read_lock(&state->ss->policy_rwlock); |
2748 | 2760 | ||
2749 | policydb = &state->ss->policydb; | 2761 | policydb = &state->ss->policydb; |
2750 | sidtab = &state->ss->sidtab; | 2762 | sidtab = state->ss->sidtab; |
2751 | 2763 | ||
2752 | c = policydb->ocontexts[OCON_FSUSE]; | 2764 | c = policydb->ocontexts[OCON_FSUSE]; |
2753 | while (c) { | 2765 | while (c) { |
@@ -2953,7 +2965,7 @@ int security_sid_mls_copy(struct selinux_state *state, | |||
2953 | u32 sid, u32 mls_sid, u32 *new_sid) | 2965 | u32 sid, u32 mls_sid, u32 *new_sid) |
2954 | { | 2966 | { |
2955 | struct policydb *policydb = &state->ss->policydb; | 2967 | struct policydb *policydb = &state->ss->policydb; |
2956 | struct sidtab *sidtab = &state->ss->sidtab; | 2968 | struct sidtab *sidtab = state->ss->sidtab; |
2957 | struct context *context1; | 2969 | struct context *context1; |
2958 | struct context *context2; | 2970 | struct context *context2; |
2959 | struct context newcon; | 2971 | struct context newcon; |
@@ -3044,7 +3056,7 @@ int security_net_peersid_resolve(struct selinux_state *state, | |||
3044 | u32 *peer_sid) | 3056 | u32 *peer_sid) |
3045 | { | 3057 | { |
3046 | struct policydb *policydb = &state->ss->policydb; | 3058 | struct policydb *policydb = &state->ss->policydb; |
3047 | struct sidtab *sidtab = &state->ss->sidtab; | 3059 | struct sidtab *sidtab = state->ss->sidtab; |
3048 | int rc; | 3060 | int rc; |
3049 | struct context *nlbl_ctx; | 3061 | struct context *nlbl_ctx; |
3050 | struct context *xfrm_ctx; | 3062 | struct context *xfrm_ctx; |
@@ -3405,7 +3417,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
3405 | goto out; | 3417 | goto out; |
3406 | } | 3418 | } |
3407 | 3419 | ||
3408 | ctxt = sidtab_search(&state->ss->sidtab, sid); | 3420 | ctxt = sidtab_search(state->ss->sidtab, sid); |
3409 | if (unlikely(!ctxt)) { | 3421 | if (unlikely(!ctxt)) { |
3410 | WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", | 3422 | WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", |
3411 | sid); | 3423 | sid); |
@@ -3568,7 +3580,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, | |||
3568 | u32 *sid) | 3580 | u32 *sid) |
3569 | { | 3581 | { |
3570 | struct policydb *policydb = &state->ss->policydb; | 3582 | struct policydb *policydb = &state->ss->policydb; |
3571 | struct sidtab *sidtab = &state->ss->sidtab; | 3583 | struct sidtab *sidtab = state->ss->sidtab; |
3572 | int rc; | 3584 | int rc; |
3573 | struct context *ctx; | 3585 | struct context *ctx; |
3574 | struct context ctx_new; | 3586 | struct context ctx_new; |
@@ -3646,7 +3658,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state, | |||
3646 | read_lock(&state->ss->policy_rwlock); | 3658 | read_lock(&state->ss->policy_rwlock); |
3647 | 3659 | ||
3648 | rc = -ENOENT; | 3660 | rc = -ENOENT; |
3649 | ctx = sidtab_search(&state->ss->sidtab, sid); | 3661 | ctx = sidtab_search(state->ss->sidtab, sid); |
3650 | if (ctx == NULL) | 3662 | if (ctx == NULL) |
3651 | goto out; | 3663 | goto out; |
3652 | 3664 | ||
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index 24c7bdcc8075..9a36de860368 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h | |||
@@ -24,7 +24,7 @@ struct selinux_map { | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | struct selinux_ss { | 26 | struct selinux_ss { |
27 | struct sidtab sidtab; | 27 | struct sidtab *sidtab; |
28 | struct policydb policydb; | 28 | struct policydb policydb; |
29 | rwlock_t policy_rwlock; | 29 | rwlock_t policy_rwlock; |
30 | u32 latest_granting; | 30 | u32 latest_granting; |
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index ccc0ea230df4..e44e7cec630c 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
@@ -22,16 +22,24 @@ int sidtab_init(struct sidtab *s) | |||
22 | s->htable = kmalloc_array(SIDTAB_SIZE, sizeof(*s->htable), GFP_ATOMIC); | 22 | s->htable = kmalloc_array(SIDTAB_SIZE, sizeof(*s->htable), GFP_ATOMIC); |
23 | if (!s->htable) | 23 | if (!s->htable) |
24 | return -ENOMEM; | 24 | return -ENOMEM; |
25 | |||
26 | for (i = 0; i < SECINITSID_NUM; i++) | ||
27 | s->isids[i].set = 0; | ||
28 | |||
25 | for (i = 0; i < SIDTAB_SIZE; i++) | 29 | for (i = 0; i < SIDTAB_SIZE; i++) |
26 | s->htable[i] = NULL; | 30 | s->htable[i] = NULL; |
31 | |||
32 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) | ||
33 | s->cache[i] = NULL; | ||
34 | |||
27 | s->nel = 0; | 35 | s->nel = 0; |
28 | s->next_sid = 1; | 36 | s->next_sid = 0; |
29 | s->shutdown = 0; | 37 | s->shutdown = 0; |
30 | spin_lock_init(&s->lock); | 38 | spin_lock_init(&s->lock); |
31 | return 0; | 39 | return 0; |
32 | } | 40 | } |
33 | 41 | ||
34 | int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) | 42 | static int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) |
35 | { | 43 | { |
36 | int hvalue; | 44 | int hvalue; |
37 | struct sidtab_node *prev, *cur, *newnode; | 45 | struct sidtab_node *prev, *cur, *newnode; |
@@ -76,34 +84,62 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context) | |||
76 | return 0; | 84 | return 0; |
77 | } | 85 | } |
78 | 86 | ||
79 | static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) | 87 | int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context) |
88 | { | ||
89 | struct sidtab_isid_entry *entry; | ||
90 | int rc; | ||
91 | |||
92 | if (sid == 0 || sid > SECINITSID_NUM) | ||
93 | return -EINVAL; | ||
94 | |||
95 | entry = &s->isids[sid - 1]; | ||
96 | |||
97 | rc = context_cpy(&entry->context, context); | ||
98 | if (rc) | ||
99 | return rc; | ||
100 | |||
101 | entry->set = 1; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static struct context *sidtab_lookup(struct sidtab *s, u32 sid) | ||
80 | { | 106 | { |
81 | int hvalue; | 107 | int hvalue; |
82 | struct sidtab_node *cur; | 108 | struct sidtab_node *cur; |
83 | 109 | ||
84 | if (!s) | ||
85 | return NULL; | ||
86 | |||
87 | hvalue = SIDTAB_HASH(sid); | 110 | hvalue = SIDTAB_HASH(sid); |
88 | cur = s->htable[hvalue]; | 111 | cur = s->htable[hvalue]; |
89 | while (cur && sid > cur->sid) | 112 | while (cur && sid > cur->sid) |
90 | cur = cur->next; | 113 | cur = cur->next; |
91 | 114 | ||
92 | if (force && cur && sid == cur->sid && cur->context.len) | 115 | if (!cur || sid != cur->sid) |
93 | return &cur->context; | 116 | return NULL; |
94 | 117 | ||
95 | if (!cur || sid != cur->sid || cur->context.len) { | 118 | return &cur->context; |
96 | /* Remap invalid SIDs to the unlabeled SID. */ | 119 | } |
97 | sid = SECINITSID_UNLABELED; | 120 | |
98 | hvalue = SIDTAB_HASH(sid); | 121 | static struct context *sidtab_lookup_initial(struct sidtab *s, u32 sid) |
99 | cur = s->htable[hvalue]; | 122 | { |
100 | while (cur && sid > cur->sid) | 123 | return s->isids[sid - 1].set ? &s->isids[sid - 1].context : NULL; |
101 | cur = cur->next; | 124 | } |
102 | if (!cur || sid != cur->sid) | 125 | |
103 | return NULL; | 126 | static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force) |
127 | { | ||
128 | struct context *context; | ||
129 | |||
130 | if (!s) | ||
131 | return NULL; | ||
132 | |||
133 | if (sid != 0) { | ||
134 | if (sid > SECINITSID_NUM) | ||
135 | context = sidtab_lookup(s, sid - (SECINITSID_NUM + 1)); | ||
136 | else | ||
137 | context = sidtab_lookup_initial(s, sid); | ||
138 | if (context && (!context->len || force)) | ||
139 | return context; | ||
104 | } | 140 | } |
105 | 141 | ||
106 | return &cur->context; | 142 | return sidtab_lookup_initial(s, SECINITSID_UNLABELED); |
107 | } | 143 | } |
108 | 144 | ||
109 | struct context *sidtab_search(struct sidtab *s, u32 sid) | 145 | struct context *sidtab_search(struct sidtab *s, u32 sid) |
@@ -145,11 +181,7 @@ out: | |||
145 | static int clone_sid(u32 sid, struct context *context, void *arg) | 181 | static int clone_sid(u32 sid, struct context *context, void *arg) |
146 | { | 182 | { |
147 | struct sidtab *s = arg; | 183 | struct sidtab *s = arg; |
148 | 184 | return sidtab_insert(s, sid, context); | |
149 | if (sid > SECINITSID_NUM) | ||
150 | return sidtab_insert(s, sid, context); | ||
151 | else | ||
152 | return 0; | ||
153 | } | 185 | } |
154 | 186 | ||
155 | int sidtab_convert(struct sidtab *s, struct sidtab *news, | 187 | int sidtab_convert(struct sidtab *s, struct sidtab *news, |
@@ -183,8 +215,8 @@ static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc | |||
183 | s->cache[0] = n; | 215 | s->cache[0] = n; |
184 | } | 216 | } |
185 | 217 | ||
186 | static inline u32 sidtab_search_context(struct sidtab *s, | 218 | static inline int sidtab_search_context(struct sidtab *s, |
187 | struct context *context) | 219 | struct context *context, u32 *sid) |
188 | { | 220 | { |
189 | int i; | 221 | int i; |
190 | struct sidtab_node *cur; | 222 | struct sidtab_node *cur; |
@@ -194,15 +226,17 @@ static inline u32 sidtab_search_context(struct sidtab *s, | |||
194 | while (cur) { | 226 | while (cur) { |
195 | if (context_cmp(&cur->context, context)) { | 227 | if (context_cmp(&cur->context, context)) { |
196 | sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1); | 228 | sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1); |
197 | return cur->sid; | 229 | *sid = cur->sid; |
230 | return 0; | ||
198 | } | 231 | } |
199 | cur = cur->next; | 232 | cur = cur->next; |
200 | } | 233 | } |
201 | } | 234 | } |
202 | return 0; | 235 | return -ENOENT; |
203 | } | 236 | } |
204 | 237 | ||
205 | static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context) | 238 | static inline int sidtab_search_cache(struct sidtab *s, struct context *context, |
239 | u32 *sid) | ||
206 | { | 240 | { |
207 | int i; | 241 | int i; |
208 | struct sidtab_node *node; | 242 | struct sidtab_node *node; |
@@ -210,54 +244,69 @@ static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context) | |||
210 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) { | 244 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) { |
211 | node = s->cache[i]; | 245 | node = s->cache[i]; |
212 | if (unlikely(!node)) | 246 | if (unlikely(!node)) |
213 | return 0; | 247 | return -ENOENT; |
214 | if (context_cmp(&node->context, context)) { | 248 | if (context_cmp(&node->context, context)) { |
215 | sidtab_update_cache(s, node, i); | 249 | sidtab_update_cache(s, node, i); |
216 | return node->sid; | 250 | *sid = node->sid; |
251 | return 0; | ||
217 | } | 252 | } |
218 | } | 253 | } |
219 | return 0; | 254 | return -ENOENT; |
220 | } | 255 | } |
221 | 256 | ||
222 | int sidtab_context_to_sid(struct sidtab *s, | 257 | static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, |
223 | struct context *context, | 258 | u32 *sid) |
224 | u32 *out_sid) | ||
225 | { | 259 | { |
226 | u32 sid; | 260 | int ret; |
227 | int ret = 0; | ||
228 | unsigned long flags; | 261 | unsigned long flags; |
229 | 262 | ||
230 | *out_sid = SECSID_NULL; | 263 | ret = sidtab_search_cache(s, context, sid); |
231 | 264 | if (ret) | |
232 | sid = sidtab_search_cache(s, context); | 265 | ret = sidtab_search_context(s, context, sid); |
233 | if (!sid) | 266 | if (ret) { |
234 | sid = sidtab_search_context(s, context); | ||
235 | if (!sid) { | ||
236 | spin_lock_irqsave(&s->lock, flags); | 267 | spin_lock_irqsave(&s->lock, flags); |
237 | /* Rescan now that we hold the lock. */ | 268 | /* Rescan now that we hold the lock. */ |
238 | sid = sidtab_search_context(s, context); | 269 | ret = sidtab_search_context(s, context, sid); |
239 | if (sid) | 270 | if (!ret) |
240 | goto unlock_out; | 271 | goto unlock_out; |
241 | /* No SID exists for the context. Allocate a new one. */ | 272 | /* No SID exists for the context. Allocate a new one. */ |
242 | if (s->next_sid == UINT_MAX || s->shutdown) { | 273 | if (s->next_sid == (UINT_MAX - SECINITSID_NUM - 1) || |
274 | s->shutdown) { | ||
243 | ret = -ENOMEM; | 275 | ret = -ENOMEM; |
244 | goto unlock_out; | 276 | goto unlock_out; |
245 | } | 277 | } |
246 | sid = s->next_sid++; | 278 | *sid = s->next_sid++; |
247 | if (context->len) | 279 | if (context->len) |
248 | pr_info("SELinux: Context %s is not valid (left unmapped).\n", | 280 | pr_info("SELinux: Context %s is not valid (left unmapped).\n", |
249 | context->str); | 281 | context->str); |
250 | ret = sidtab_insert(s, sid, context); | 282 | ret = sidtab_insert(s, *sid, context); |
251 | if (ret) | 283 | if (ret) |
252 | s->next_sid--; | 284 | s->next_sid--; |
253 | unlock_out: | 285 | unlock_out: |
254 | spin_unlock_irqrestore(&s->lock, flags); | 286 | spin_unlock_irqrestore(&s->lock, flags); |
255 | } | 287 | } |
256 | 288 | ||
257 | if (ret) | 289 | return ret; |
258 | return ret; | 290 | } |
291 | |||
292 | int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid) | ||
293 | { | ||
294 | int rc; | ||
295 | u32 i; | ||
259 | 296 | ||
260 | *out_sid = sid; | 297 | for (i = 0; i < SECINITSID_NUM; i++) { |
298 | struct sidtab_isid_entry *entry = &s->isids[i]; | ||
299 | |||
300 | if (entry->set && context_cmp(context, &entry->context)) { | ||
301 | *sid = i + 1; | ||
302 | return 0; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | rc = sidtab_reverse_lookup(s, context, sid); | ||
307 | if (rc) | ||
308 | return rc; | ||
309 | *sid += SECINITSID_NUM + 1; | ||
261 | return 0; | 310 | return 0; |
262 | } | 311 | } |
263 | 312 | ||
@@ -296,6 +345,10 @@ void sidtab_destroy(struct sidtab *s) | |||
296 | if (!s) | 345 | if (!s) |
297 | return; | 346 | return; |
298 | 347 | ||
348 | for (i = 0; i < SECINITSID_NUM; i++) | ||
349 | if (s->isids[i].set) | ||
350 | context_destroy(&s->isids[i].context); | ||
351 | |||
299 | for (i = 0; i < SIDTAB_SIZE; i++) { | 352 | for (i = 0; i < SIDTAB_SIZE; i++) { |
300 | cur = s->htable[i]; | 353 | cur = s->htable[i]; |
301 | while (cur) { | 354 | while (cur) { |
@@ -311,18 +364,3 @@ void sidtab_destroy(struct sidtab *s) | |||
311 | s->nel = 0; | 364 | s->nel = 0; |
312 | s->next_sid = 1; | 365 | s->next_sid = 1; |
313 | } | 366 | } |
314 | |||
315 | void sidtab_set(struct sidtab *dst, struct sidtab *src) | ||
316 | { | ||
317 | unsigned long flags; | ||
318 | int i; | ||
319 | |||
320 | spin_lock_irqsave(&src->lock, flags); | ||
321 | dst->htable = src->htable; | ||
322 | dst->nel = src->nel; | ||
323 | dst->next_sid = src->next_sid; | ||
324 | dst->shutdown = 0; | ||
325 | for (i = 0; i < SIDTAB_CACHE_LEN; i++) | ||
326 | dst->cache[i] = NULL; | ||
327 | spin_unlock_irqrestore(&src->lock, flags); | ||
328 | } | ||
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index e1d1f0beb17c..e657ae6bf996 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h | |||
@@ -22,6 +22,11 @@ struct sidtab_node { | |||
22 | 22 | ||
23 | #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS | 23 | #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS |
24 | 24 | ||
25 | struct sidtab_isid_entry { | ||
26 | int set; | ||
27 | struct context context; | ||
28 | }; | ||
29 | |||
25 | struct sidtab { | 30 | struct sidtab { |
26 | struct sidtab_node **htable; | 31 | struct sidtab_node **htable; |
27 | unsigned int nel; /* number of elements */ | 32 | unsigned int nel; /* number of elements */ |
@@ -30,10 +35,13 @@ struct sidtab { | |||
30 | #define SIDTAB_CACHE_LEN 3 | 35 | #define SIDTAB_CACHE_LEN 3 |
31 | struct sidtab_node *cache[SIDTAB_CACHE_LEN]; | 36 | struct sidtab_node *cache[SIDTAB_CACHE_LEN]; |
32 | spinlock_t lock; | 37 | spinlock_t lock; |
38 | |||
39 | /* index == SID - 1 (no entry for SECSID_NULL) */ | ||
40 | struct sidtab_isid_entry isids[SECINITSID_NUM]; | ||
33 | }; | 41 | }; |
34 | 42 | ||
35 | int sidtab_init(struct sidtab *s); | 43 | int sidtab_init(struct sidtab *s); |
36 | int sidtab_insert(struct sidtab *s, u32 sid, struct context *context); | 44 | int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context); |
37 | struct context *sidtab_search(struct sidtab *s, u32 sid); | 45 | struct context *sidtab_search(struct sidtab *s, u32 sid); |
38 | struct context *sidtab_search_force(struct sidtab *s, u32 sid); | 46 | struct context *sidtab_search_force(struct sidtab *s, u32 sid); |
39 | 47 | ||
@@ -43,13 +51,10 @@ int sidtab_convert(struct sidtab *s, struct sidtab *news, | |||
43 | void *args), | 51 | void *args), |
44 | void *args); | 52 | void *args); |
45 | 53 | ||
46 | int sidtab_context_to_sid(struct sidtab *s, | 54 | int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); |
47 | struct context *context, | ||
48 | u32 *sid); | ||
49 | 55 | ||
50 | void sidtab_hash_eval(struct sidtab *h, char *tag); | 56 | void sidtab_hash_eval(struct sidtab *h, char *tag); |
51 | void sidtab_destroy(struct sidtab *s); | 57 | void sidtab_destroy(struct sidtab *s); |
52 | void sidtab_set(struct sidtab *dst, struct sidtab *src); | ||
53 | 58 | ||
54 | #endif /* _SS_SIDTAB_H_ */ | 59 | #endif /* _SS_SIDTAB_H_ */ |
55 | 60 | ||