diff options
| -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 | ||
