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.c499
1 files changed, 106 insertions, 393 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 1e52356664d6..40660ffd49b6 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -39,7 +39,6 @@
39#include <linux/sched.h> 39#include <linux/sched.h>
40#include <linux/audit.h> 40#include <linux/audit.h>
41#include <linux/mutex.h> 41#include <linux/mutex.h>
42#include <net/sock.h>
43#include <net/netlabel.h> 42#include <net/netlabel.h>
44 43
45#include "flask.h" 44#include "flask.h"
@@ -53,7 +52,7 @@
53#include "conditional.h" 52#include "conditional.h"
54#include "mls.h" 53#include "mls.h"
55#include "objsec.h" 54#include "objsec.h"
56#include "selinux_netlabel.h" 55#include "netlabel.h"
57#include "xfrm.h" 56#include "xfrm.h"
58#include "ebitmap.h" 57#include "ebitmap.h"
59 58
@@ -594,6 +593,13 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
594 593
595#include "initial_sid_to_string.h" 594#include "initial_sid_to_string.h"
596 595
596const char *security_get_initial_sid_context(u32 sid)
597{
598 if (unlikely(sid > SECINITSID_NUM))
599 return NULL;
600 return initial_sid_to_string[sid];
601}
602
597/** 603/**
598 * security_sid_to_context - Obtain a context for a given SID. 604 * security_sid_to_context - Obtain a context for a given SID.
599 * @sid: security identifier, SID 605 * @sid: security identifier, SID
@@ -1050,6 +1056,8 @@ static int validate_classes(struct policydb *p)
1050 1056
1051 for (i = 1; i < kdefs->cts_len; i++) { 1057 for (i = 1; i < kdefs->cts_len; i++) {
1052 def_class = kdefs->class_to_string[i]; 1058 def_class = kdefs->class_to_string[i];
1059 if (!def_class)
1060 continue;
1053 if (i > p->p_classes.nprim) { 1061 if (i > p->p_classes.nprim) {
1054 printk(KERN_INFO 1062 printk(KERN_INFO
1055 "security: class %s not defined in policy\n", 1063 "security: class %s not defined in policy\n",
@@ -1249,6 +1257,7 @@ bad:
1249} 1257}
1250 1258
1251extern void selinux_complete_init(void); 1259extern void selinux_complete_init(void);
1260static int security_preserve_bools(struct policydb *p);
1252 1261
1253/** 1262/**
1254 * security_load_policy - Load a security policy configuration. 1263 * security_load_policy - Load a security policy configuration.
@@ -1325,6 +1334,12 @@ int security_load_policy(void *data, size_t len)
1325 goto err; 1334 goto err;
1326 } 1335 }
1327 1336
1337 rc = security_preserve_bools(&newpolicydb);
1338 if (rc) {
1339 printk(KERN_ERR "security: unable to preserve booleans\n");
1340 goto err;
1341 }
1342
1328 /* Clone the SID table. */ 1343 /* Clone the SID table. */
1329 sidtab_shutdown(&sidtab); 1344 sidtab_shutdown(&sidtab);
1330 if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { 1345 if (sidtab_map(&sidtab, clone_sid, &newsidtab)) {
@@ -1882,6 +1897,37 @@ out:
1882 return rc; 1897 return rc;
1883} 1898}
1884 1899
1900static int security_preserve_bools(struct policydb *p)
1901{
1902 int rc, nbools = 0, *bvalues = NULL, i;
1903 char **bnames = NULL;
1904 struct cond_bool_datum *booldatum;
1905 struct cond_node *cur;
1906
1907 rc = security_get_bools(&nbools, &bnames, &bvalues);
1908 if (rc)
1909 goto out;
1910 for (i = 0; i < nbools; i++) {
1911 booldatum = hashtab_search(p->p_bools.table, bnames[i]);
1912 if (booldatum)
1913 booldatum->state = bvalues[i];
1914 }
1915 for (cur = p->cond_list; cur != NULL; cur = cur->next) {
1916 rc = evaluate_cond_node(p, cur);
1917 if (rc)
1918 goto out;
1919 }
1920
1921out:
1922 if (bnames) {
1923 for (i = 0; i < nbools; i++)
1924 kfree(bnames[i]);
1925 }
1926 kfree(bnames);
1927 kfree(bvalues);
1928 return rc;
1929}
1930
1885/* 1931/*
1886 * security_sid_mls_copy() - computes a new sid based on the given 1932 * security_sid_mls_copy() - computes a new sid based on the given
1887 * sid and the mls portion of mls_sid. 1933 * sid and the mls portion of mls_sid.
@@ -2198,41 +2244,15 @@ void selinux_audit_set_callback(int (*callback)(void))
2198 aurule_callback = callback; 2244 aurule_callback = callback;
2199} 2245}
2200 2246
2201/**
2202 * security_skb_extlbl_sid - Determine the external label of a packet
2203 * @skb: the packet
2204 * @base_sid: the SELinux SID to use as a context for MLS only external labels
2205 * @sid: the packet's SID
2206 *
2207 * Description:
2208 * Check the various different forms of external packet labeling and determine
2209 * the external SID for the packet.
2210 *
2211 */
2212void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2213{
2214 u32 xfrm_sid;
2215 u32 nlbl_sid;
2216
2217 selinux_skb_xfrm_sid(skb, &xfrm_sid);
2218 if (selinux_netlbl_skbuff_getsid(skb,
2219 (xfrm_sid == SECSID_NULL ?
2220 base_sid : xfrm_sid),
2221 &nlbl_sid) != 0)
2222 nlbl_sid = SECSID_NULL;
2223
2224 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
2225}
2226
2227#ifdef CONFIG_NETLABEL 2247#ifdef CONFIG_NETLABEL
2228/* 2248/*
2229 * This is the structure we store inside the NetLabel cache block. 2249 * NetLabel cache structure
2230 */ 2250 */
2231#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x)) 2251#define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x))
2232#define NETLBL_CACHE_T_NONE 0 2252#define NETLBL_CACHE_T_NONE 0
2233#define NETLBL_CACHE_T_SID 1 2253#define NETLBL_CACHE_T_SID 1
2234#define NETLBL_CACHE_T_MLS 2 2254#define NETLBL_CACHE_T_MLS 2
2235struct netlbl_cache { 2255struct selinux_netlbl_cache {
2236 u32 type; 2256 u32 type;
2237 union { 2257 union {
2238 u32 sid; 2258 u32 sid;
@@ -2241,7 +2261,7 @@ struct netlbl_cache {
2241}; 2261};
2242 2262
2243/** 2263/**
2244 * selinux_netlbl_cache_free - Free the NetLabel cached data 2264 * security_netlbl_cache_free - Free the NetLabel cached data
2245 * @data: the data to free 2265 * @data: the data to free
2246 * 2266 *
2247 * Description: 2267 * Description:
@@ -2249,9 +2269,9 @@ struct netlbl_cache {
2249 * netlbl_lsm_cache structure. 2269 * netlbl_lsm_cache structure.
2250 * 2270 *
2251 */ 2271 */
2252static void selinux_netlbl_cache_free(const void *data) 2272static void security_netlbl_cache_free(const void *data)
2253{ 2273{
2254 struct netlbl_cache *cache; 2274 struct selinux_netlbl_cache *cache;
2255 2275
2256 if (data == NULL) 2276 if (data == NULL)
2257 return; 2277 return;
@@ -2266,33 +2286,33 @@ static void selinux_netlbl_cache_free(const void *data)
2266} 2286}
2267 2287
2268/** 2288/**
2269 * selinux_netlbl_cache_add - Add an entry to the NetLabel cache 2289 * security_netlbl_cache_add - Add an entry to the NetLabel cache
2270 * @skb: the packet 2290 * @secattr: the NetLabel packet security attributes
2271 * @ctx: the SELinux context 2291 * @ctx: the SELinux context
2272 * 2292 *
2273 * Description: 2293 * Description:
2274 * Attempt to cache the context in @ctx, which was derived from the packet in 2294 * Attempt to cache the context in @ctx, which was derived from the packet in
2275 * @skb, in the NetLabel subsystem cache. 2295 * @skb, in the NetLabel subsystem cache. This function assumes @secattr has
2296 * already been initialized.
2276 * 2297 *
2277 */ 2298 */
2278static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) 2299static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
2300 struct context *ctx)
2279{ 2301{
2280 struct netlbl_cache *cache = NULL; 2302 struct selinux_netlbl_cache *cache = NULL;
2281 struct netlbl_lsm_secattr secattr;
2282 2303
2283 netlbl_secattr_init(&secattr); 2304 secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
2284 secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); 2305 if (secattr->cache == NULL)
2285 if (secattr.cache == NULL) 2306 return;
2286 goto netlbl_cache_add_return;
2287 2307
2288 cache = kzalloc(sizeof(*cache), GFP_ATOMIC); 2308 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2289 if (cache == NULL) 2309 if (cache == NULL)
2290 goto netlbl_cache_add_return; 2310 return;
2291 2311
2292 cache->type = NETLBL_CACHE_T_MLS; 2312 cache->type = NETLBL_CACHE_T_MLS;
2293 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2313 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
2294 &ctx->range.level[0].cat) != 0) 2314 &ctx->range.level[0].cat) != 0)
2295 goto netlbl_cache_add_return; 2315 return;
2296 cache->data.mls_label.level[1].cat.highbit = 2316 cache->data.mls_label.level[1].cat.highbit =
2297 cache->data.mls_label.level[0].cat.highbit; 2317 cache->data.mls_label.level[0].cat.highbit;
2298 cache->data.mls_label.level[1].cat.node = 2318 cache->data.mls_label.level[1].cat.node =
@@ -2300,52 +2320,40 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2300 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; 2320 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2301 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; 2321 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2302 2322
2303 secattr.cache->free = selinux_netlbl_cache_free; 2323 secattr->cache->free = security_netlbl_cache_free;
2304 secattr.cache->data = (void *)cache; 2324 secattr->cache->data = (void *)cache;
2305 secattr.flags = NETLBL_SECATTR_CACHE; 2325 secattr->flags |= NETLBL_SECATTR_CACHE;
2306
2307 netlbl_cache_add(skb, &secattr);
2308
2309netlbl_cache_add_return:
2310 netlbl_secattr_destroy(&secattr);
2311} 2326}
2312 2327
2313/** 2328/**
2314 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 2329 * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
2315 *
2316 * Description:
2317 * Invalidate the NetLabel security attribute mapping cache.
2318 *
2319 */
2320void selinux_netlbl_cache_invalidate(void)
2321{
2322 netlbl_cache_invalidate();
2323}
2324
2325/**
2326 * selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
2327 * @skb: the network packet
2328 * @secattr: the NetLabel packet security attributes 2330 * @secattr: the NetLabel packet security attributes
2329 * @base_sid: the SELinux SID to use as a context for MLS only attributes 2331 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2330 * @sid: the SELinux SID 2332 * @sid: the SELinux SID
2331 * 2333 *
2332 * Description: 2334 * Description:
2333 * Convert the given NetLabel packet security attributes in @secattr into a 2335 * Convert the given NetLabel security attributes in @secattr into a
2334 * SELinux SID. If the @secattr field does not contain a full SELinux 2336 * SELinux SID. If the @secattr field does not contain a full SELinux
2335 * SID/context then use the context in @base_sid as the foundation. If @skb 2337 * SID/context then use the context in @base_sid as the foundation. If
2336 * is not NULL attempt to cache as much data as possibile. Returns zero on 2338 * possibile the 'cache' field of @secattr is set and the CACHE flag is set;
2337 * success, negative values on failure. 2339 * this is to allow the @secattr to be used by NetLabel to cache the secattr to
2340 * SID conversion for future lookups. Returns zero on success, negative
2341 * values on failure.
2338 * 2342 *
2339 */ 2343 */
2340static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, 2344int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2341 struct netlbl_lsm_secattr *secattr, 2345 u32 base_sid,
2342 u32 base_sid, 2346 u32 *sid)
2343 u32 *sid)
2344{ 2347{
2345 int rc = -EIDRM; 2348 int rc = -EIDRM;
2346 struct context *ctx; 2349 struct context *ctx;
2347 struct context ctx_new; 2350 struct context ctx_new;
2348 struct netlbl_cache *cache; 2351 struct selinux_netlbl_cache *cache;
2352
2353 if (!ss_initialized) {
2354 *sid = SECSID_NULL;
2355 return 0;
2356 }
2349 2357
2350 POLICY_RDLOCK; 2358 POLICY_RDLOCK;
2351 2359
@@ -2410,8 +2418,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2410 if (rc != 0) 2418 if (rc != 0)
2411 goto netlbl_secattr_to_sid_return_cleanup; 2419 goto netlbl_secattr_to_sid_return_cleanup;
2412 2420
2413 if (skb != NULL) 2421 security_netlbl_cache_add(secattr, &ctx_new);
2414 selinux_netlbl_cache_add(skb, &ctx_new); 2422
2415 ebitmap_destroy(&ctx_new.range.level[0].cat); 2423 ebitmap_destroy(&ctx_new.range.level[0].cat);
2416 } else { 2424 } else {
2417 *sid = SECSID_NULL; 2425 *sid = SECSID_NULL;
@@ -2427,338 +2435,43 @@ netlbl_secattr_to_sid_return_cleanup:
2427} 2435}
2428 2436
2429/** 2437/**
2430 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 2438 * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr
2431 * @skb: the packet 2439 * @sid: the SELinux SID
2432 * @base_sid: the SELinux SID to use as a context for MLS only attributes 2440 * @secattr: the NetLabel packet security attributes
2433 * @sid: the SID
2434 *
2435 * Description:
2436 * Call the NetLabel mechanism to get the security attributes of the given
2437 * packet and use those attributes to determine the correct context/SID to
2438 * assign to the packet. Returns zero on success, negative values on failure.
2439 *
2440 */
2441int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2442{
2443 int rc;
2444 struct netlbl_lsm_secattr secattr;
2445
2446 netlbl_secattr_init(&secattr);
2447 rc = netlbl_skbuff_getattr(skb, &secattr);
2448 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2449 rc = selinux_netlbl_secattr_to_sid(skb,
2450 &secattr,
2451 base_sid,
2452 sid);
2453 else
2454 *sid = SECSID_NULL;
2455 netlbl_secattr_destroy(&secattr);
2456
2457 return rc;
2458}
2459
2460/**
2461 * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
2462 * @sock: the socket to label
2463 * @sid: the SID to use
2464 * 2441 *
2465 * Description: 2442 * Description:
2466 * Attempt to label a socket using the NetLabel mechanism using the given 2443 * Convert the given SELinux SID in @sid into a NetLabel security attribute.
2467 * SID. Returns zero values on success, negative values on failure. The 2444 * Returns zero on success, negative values on failure.
2468 * caller is responsibile for calling rcu_read_lock() before calling this
2469 * this function and rcu_read_unlock() after this function returns.
2470 * 2445 *
2471 */ 2446 */
2472static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) 2447int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2473{ 2448{
2474 int rc = -ENOENT; 2449 int rc = -ENOENT;
2475 struct sk_security_struct *sksec = sock->sk->sk_security;
2476 struct netlbl_lsm_secattr secattr;
2477 struct context *ctx; 2450 struct context *ctx;
2478 2451
2452 netlbl_secattr_init(secattr);
2453
2479 if (!ss_initialized) 2454 if (!ss_initialized)
2480 return 0; 2455 return 0;
2481 2456
2482 netlbl_secattr_init(&secattr);
2483
2484 POLICY_RDLOCK; 2457 POLICY_RDLOCK;
2485
2486 ctx = sidtab_search(&sidtab, sid); 2458 ctx = sidtab_search(&sidtab, sid);
2487 if (ctx == NULL) 2459 if (ctx == NULL)
2488 goto netlbl_socket_setsid_return; 2460 goto netlbl_sid_to_secattr_failure;
2489 2461 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2490 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2462 GFP_ATOMIC);
2491 GFP_ATOMIC); 2463 secattr->flags |= NETLBL_SECATTR_DOMAIN;
2492 secattr.flags |= NETLBL_SECATTR_DOMAIN; 2464 mls_export_netlbl_lvl(ctx, secattr);
2493 mls_export_netlbl_lvl(ctx, &secattr); 2465 rc = mls_export_netlbl_cat(ctx, secattr);
2494 rc = mls_export_netlbl_cat(ctx, &secattr);
2495 if (rc != 0) 2466 if (rc != 0)
2496 goto netlbl_socket_setsid_return; 2467 goto netlbl_sid_to_secattr_failure;
2497
2498 rc = netlbl_socket_setattr(sock, &secattr);
2499 if (rc == 0) {
2500 spin_lock_bh(&sksec->nlbl_lock);
2501 sksec->nlbl_state = NLBL_LABELED;
2502 spin_unlock_bh(&sksec->nlbl_lock);
2503 }
2504
2505netlbl_socket_setsid_return:
2506 POLICY_RDUNLOCK; 2468 POLICY_RDUNLOCK;
2507 netlbl_secattr_destroy(&secattr);
2508 return rc;
2509}
2510
2511/**
2512 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
2513 * @ssec: the sk_security_struct
2514 * @family: the socket family
2515 *
2516 * Description:
2517 * Called when the NetLabel state of a sk_security_struct needs to be reset.
2518 * The caller is responsibile for all the NetLabel sk_security_struct locking.
2519 *
2520 */
2521void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
2522 int family)
2523{
2524 if (family == PF_INET)
2525 ssec->nlbl_state = NLBL_REQUIRE;
2526 else
2527 ssec->nlbl_state = NLBL_UNSET;
2528}
2529 2469
2530/** 2470 return 0;
2531 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
2532 * @ssec: the sk_security_struct
2533 * @family: the socket family
2534 *
2535 * Description:
2536 * Called when a new sk_security_struct is allocated to initialize the NetLabel
2537 * fields.
2538 *
2539 */
2540void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2541 int family)
2542{
2543 /* No locking needed, we are the only one who has access to ssec */
2544 selinux_netlbl_sk_security_reset(ssec, family);
2545 spin_lock_init(&ssec->nlbl_lock);
2546}
2547
2548/**
2549 * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
2550 * @ssec: the original sk_security_struct
2551 * @newssec: the cloned sk_security_struct
2552 *
2553 * Description:
2554 * Clone the NetLabel specific sk_security_struct fields from @ssec to
2555 * @newssec.
2556 *
2557 */
2558void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
2559 struct sk_security_struct *newssec)
2560{
2561 /* We don't need to take newssec->nlbl_lock because we are the only
2562 * thread with access to newssec, but we do need to take the RCU read
2563 * lock as other threads could have access to ssec */
2564 rcu_read_lock();
2565 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
2566 newssec->sclass = ssec->sclass;
2567 rcu_read_unlock();
2568}
2569
2570/**
2571 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2572 * @sock: the socket to label
2573 *
2574 * Description:
2575 * Attempt to label a socket using the NetLabel mechanism using the given
2576 * SID. Returns zero values on success, negative values on failure.
2577 *
2578 */
2579int selinux_netlbl_socket_post_create(struct socket *sock)
2580{
2581 int rc = 0;
2582 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2583 struct sk_security_struct *sksec = sock->sk->sk_security;
2584
2585 sksec->sclass = isec->sclass;
2586
2587 rcu_read_lock();
2588 if (sksec->nlbl_state == NLBL_REQUIRE)
2589 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2590 rcu_read_unlock();
2591
2592 return rc;
2593}
2594
2595/**
2596 * selinux_netlbl_sock_graft - Netlabel the new socket
2597 * @sk: the new connection
2598 * @sock: the new socket
2599 *
2600 * Description:
2601 * The connection represented by @sk is being grafted onto @sock so set the
2602 * socket's NetLabel to match the SID of @sk.
2603 *
2604 */
2605void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2606{
2607 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2608 struct sk_security_struct *sksec = sk->sk_security;
2609 struct netlbl_lsm_secattr secattr;
2610 u32 nlbl_peer_sid;
2611
2612 sksec->sclass = isec->sclass;
2613
2614 rcu_read_lock();
2615
2616 if (sksec->nlbl_state != NLBL_REQUIRE) {
2617 rcu_read_unlock();
2618 return;
2619 }
2620
2621 netlbl_secattr_init(&secattr);
2622 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2623 secattr.flags != NETLBL_SECATTR_NONE &&
2624 selinux_netlbl_secattr_to_sid(NULL,
2625 &secattr,
2626 SECINITSID_UNLABELED,
2627 &nlbl_peer_sid) == 0)
2628 sksec->peer_sid = nlbl_peer_sid;
2629 netlbl_secattr_destroy(&secattr);
2630
2631 /* Try to set the NetLabel on the socket to save time later, if we fail
2632 * here we will pick up the pieces in later calls to
2633 * selinux_netlbl_inode_permission(). */
2634 selinux_netlbl_socket_setsid(sock, sksec->sid);
2635
2636 rcu_read_unlock();
2637}
2638
2639/**
2640 * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
2641 * @inode: the file descriptor's inode
2642 * @mask: the permission mask
2643 *
2644 * Description:
2645 * Looks at a file's inode and if it is marked as a socket protected by
2646 * NetLabel then verify that the socket has been labeled, if not try to label
2647 * the socket now with the inode's SID. Returns zero on success, negative
2648 * values on failure.
2649 *
2650 */
2651int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2652{
2653 int rc;
2654 struct sk_security_struct *sksec;
2655 struct socket *sock;
2656
2657 if (!S_ISSOCK(inode->i_mode) ||
2658 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
2659 return 0;
2660 sock = SOCKET_I(inode);
2661 sksec = sock->sk->sk_security;
2662
2663 rcu_read_lock();
2664 if (sksec->nlbl_state != NLBL_REQUIRE) {
2665 rcu_read_unlock();
2666 return 0;
2667 }
2668 local_bh_disable();
2669 bh_lock_sock_nested(sock->sk);
2670 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2671 bh_unlock_sock(sock->sk);
2672 local_bh_enable();
2673 rcu_read_unlock();
2674
2675 return rc;
2676}
2677
2678/**
2679 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
2680 * @sksec: the sock's sk_security_struct
2681 * @skb: the packet
2682 * @ad: the audit data
2683 *
2684 * Description:
2685 * Fetch the NetLabel security attributes from @skb and perform an access check
2686 * against the receiving socket. Returns zero on success, negative values on
2687 * error.
2688 *
2689 */
2690int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2691 struct sk_buff *skb,
2692 struct avc_audit_data *ad)
2693{
2694 int rc;
2695 u32 netlbl_sid;
2696 u32 recv_perm;
2697
2698 rc = selinux_netlbl_skbuff_getsid(skb,
2699 SECINITSID_UNLABELED,
2700 &netlbl_sid);
2701 if (rc != 0)
2702 return rc;
2703
2704 if (netlbl_sid == SECSID_NULL)
2705 return 0;
2706
2707 switch (sksec->sclass) {
2708 case SECCLASS_UDP_SOCKET:
2709 recv_perm = UDP_SOCKET__RECVFROM;
2710 break;
2711 case SECCLASS_TCP_SOCKET:
2712 recv_perm = TCP_SOCKET__RECVFROM;
2713 break;
2714 default:
2715 recv_perm = RAWIP_SOCKET__RECVFROM;
2716 }
2717
2718 rc = avc_has_perm(sksec->sid,
2719 netlbl_sid,
2720 sksec->sclass,
2721 recv_perm,
2722 ad);
2723 if (rc == 0)
2724 return 0;
2725
2726 netlbl_skbuff_err(skb, rc);
2727 return rc;
2728}
2729
2730/**
2731 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2732 * @sock: the socket
2733 * @level: the socket level or protocol
2734 * @optname: the socket option name
2735 *
2736 * Description:
2737 * Check the setsockopt() call and if the user is trying to replace the IP
2738 * options on a socket and a NetLabel is in place for the socket deny the
2739 * access; otherwise allow the access. Returns zero when the access is
2740 * allowed, -EACCES when denied, and other negative values on error.
2741 *
2742 */
2743int selinux_netlbl_socket_setsockopt(struct socket *sock,
2744 int level,
2745 int optname)
2746{
2747 int rc = 0;
2748 struct sk_security_struct *sksec = sock->sk->sk_security;
2749 struct netlbl_lsm_secattr secattr;
2750
2751 rcu_read_lock();
2752 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2753 sksec->nlbl_state == NLBL_LABELED) {
2754 netlbl_secattr_init(&secattr);
2755 rc = netlbl_socket_getattr(sock, &secattr);
2756 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2757 rc = -EACCES;
2758 netlbl_secattr_destroy(&secattr);
2759 }
2760 rcu_read_unlock();
2761 2471
2472netlbl_sid_to_secattr_failure:
2473 POLICY_RDUNLOCK;
2474 netlbl_secattr_destroy(secattr);
2762 return rc; 2475 return rc;
2763} 2476}
2764#endif /* CONFIG_NETLABEL */ 2477#endif /* CONFIG_NETLABEL */