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.c423
1 files changed, 58 insertions, 365 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 1e52356664d6..c8913c5dbe21 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2226,13 +2226,13 @@ void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2226 2226
2227#ifdef CONFIG_NETLABEL 2227#ifdef CONFIG_NETLABEL
2228/* 2228/*
2229 * This is the structure we store inside the NetLabel cache block. 2229 * NetLabel cache structure
2230 */ 2230 */
2231#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x)) 2231#define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x))
2232#define NETLBL_CACHE_T_NONE 0 2232#define NETLBL_CACHE_T_NONE 0
2233#define NETLBL_CACHE_T_SID 1 2233#define NETLBL_CACHE_T_SID 1
2234#define NETLBL_CACHE_T_MLS 2 2234#define NETLBL_CACHE_T_MLS 2
2235struct netlbl_cache { 2235struct selinux_netlbl_cache {
2236 u32 type; 2236 u32 type;
2237 union { 2237 union {
2238 u32 sid; 2238 u32 sid;
@@ -2241,7 +2241,7 @@ struct netlbl_cache {
2241}; 2241};
2242 2242
2243/** 2243/**
2244 * selinux_netlbl_cache_free - Free the NetLabel cached data 2244 * security_netlbl_cache_free - Free the NetLabel cached data
2245 * @data: the data to free 2245 * @data: the data to free
2246 * 2246 *
2247 * Description: 2247 * Description:
@@ -2249,9 +2249,9 @@ struct netlbl_cache {
2249 * netlbl_lsm_cache structure. 2249 * netlbl_lsm_cache structure.
2250 * 2250 *
2251 */ 2251 */
2252static void selinux_netlbl_cache_free(const void *data) 2252static void security_netlbl_cache_free(const void *data)
2253{ 2253{
2254 struct netlbl_cache *cache; 2254 struct selinux_netlbl_cache *cache;
2255 2255
2256 if (data == NULL) 2256 if (data == NULL)
2257 return; 2257 return;
@@ -2266,33 +2266,33 @@ static void selinux_netlbl_cache_free(const void *data)
2266} 2266}
2267 2267
2268/** 2268/**
2269 * selinux_netlbl_cache_add - Add an entry to the NetLabel cache 2269 * security_netlbl_cache_add - Add an entry to the NetLabel cache
2270 * @skb: the packet 2270 * @secattr: the NetLabel packet security attributes
2271 * @ctx: the SELinux context 2271 * @ctx: the SELinux context
2272 * 2272 *
2273 * Description: 2273 * Description:
2274 * Attempt to cache the context in @ctx, which was derived from the packet in 2274 * Attempt to cache the context in @ctx, which was derived from the packet in
2275 * @skb, in the NetLabel subsystem cache. 2275 * @skb, in the NetLabel subsystem cache. This function assumes @secattr has
2276 * already been initialized.
2276 * 2277 *
2277 */ 2278 */
2278static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) 2279static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
2280 struct context *ctx)
2279{ 2281{
2280 struct netlbl_cache *cache = NULL; 2282 struct selinux_netlbl_cache *cache = NULL;
2281 struct netlbl_lsm_secattr secattr;
2282 2283
2283 netlbl_secattr_init(&secattr); 2284 secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
2284 secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); 2285 if (secattr->cache == NULL)
2285 if (secattr.cache == NULL) 2286 return;
2286 goto netlbl_cache_add_return;
2287 2287
2288 cache = kzalloc(sizeof(*cache), GFP_ATOMIC); 2288 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2289 if (cache == NULL) 2289 if (cache == NULL)
2290 goto netlbl_cache_add_return; 2290 return;
2291 2291
2292 cache->type = NETLBL_CACHE_T_MLS; 2292 cache->type = NETLBL_CACHE_T_MLS;
2293 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2293 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
2294 &ctx->range.level[0].cat) != 0) 2294 &ctx->range.level[0].cat) != 0)
2295 goto netlbl_cache_add_return; 2295 return;
2296 cache->data.mls_label.level[1].cat.highbit = 2296 cache->data.mls_label.level[1].cat.highbit =
2297 cache->data.mls_label.level[0].cat.highbit; 2297 cache->data.mls_label.level[0].cat.highbit;
2298 cache->data.mls_label.level[1].cat.node = 2298 cache->data.mls_label.level[1].cat.node =
@@ -2300,52 +2300,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; 2300 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; 2301 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2302 2302
2303 secattr.cache->free = selinux_netlbl_cache_free; 2303 secattr->cache->free = security_netlbl_cache_free;
2304 secattr.cache->data = (void *)cache; 2304 secattr->cache->data = (void *)cache;
2305 secattr.flags = NETLBL_SECATTR_CACHE; 2305 secattr->flags |= NETLBL_SECATTR_CACHE;
2306
2307 netlbl_cache_add(skb, &secattr);
2308
2309netlbl_cache_add_return:
2310 netlbl_secattr_destroy(&secattr);
2311} 2306}
2312 2307
2313/** 2308/**
2314 * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache 2309 * 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 2310 * @secattr: the NetLabel packet security attributes
2329 * @base_sid: the SELinux SID to use as a context for MLS only attributes 2311 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2330 * @sid: the SELinux SID 2312 * @sid: the SELinux SID
2331 * 2313 *
2332 * Description: 2314 * Description:
2333 * Convert the given NetLabel packet security attributes in @secattr into a 2315 * Convert the given NetLabel security attributes in @secattr into a
2334 * SELinux SID. If the @secattr field does not contain a full SELinux 2316 * 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 2317 * 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 2318 * possibile the 'cache' field of @secattr is set and the CACHE flag is set;
2337 * success, negative values on failure. 2319 * this is to allow the @secattr to be used by NetLabel to cache the secattr to
2320 * SID conversion for future lookups. Returns zero on success, negative
2321 * values on failure.
2338 * 2322 *
2339 */ 2323 */
2340static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, 2324int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2341 struct netlbl_lsm_secattr *secattr, 2325 u32 base_sid,
2342 u32 base_sid, 2326 u32 *sid)
2343 u32 *sid)
2344{ 2327{
2345 int rc = -EIDRM; 2328 int rc = -EIDRM;
2346 struct context *ctx; 2329 struct context *ctx;
2347 struct context ctx_new; 2330 struct context ctx_new;
2348 struct netlbl_cache *cache; 2331 struct selinux_netlbl_cache *cache;
2332
2333 if (!ss_initialized) {
2334 *sid = SECSID_NULL;
2335 return 0;
2336 }
2349 2337
2350 POLICY_RDLOCK; 2338 POLICY_RDLOCK;
2351 2339
@@ -2410,8 +2398,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2410 if (rc != 0) 2398 if (rc != 0)
2411 goto netlbl_secattr_to_sid_return_cleanup; 2399 goto netlbl_secattr_to_sid_return_cleanup;
2412 2400
2413 if (skb != NULL) 2401 security_netlbl_cache_add(secattr, &ctx_new);
2414 selinux_netlbl_cache_add(skb, &ctx_new); 2402
2415 ebitmap_destroy(&ctx_new.range.level[0].cat); 2403 ebitmap_destroy(&ctx_new.range.level[0].cat);
2416 } else { 2404 } else {
2417 *sid = SECSID_NULL; 2405 *sid = SECSID_NULL;
@@ -2427,338 +2415,43 @@ netlbl_secattr_to_sid_return_cleanup:
2427} 2415}
2428 2416
2429/** 2417/**
2430 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 2418 * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr
2431 * @skb: the packet 2419 * @sid: the SELinux SID
2432 * @base_sid: the SELinux SID to use as a context for MLS only attributes 2420 * @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 * 2421 *
2465 * Description: 2422 * Description:
2466 * Attempt to label a socket using the NetLabel mechanism using the given 2423 * Convert the given SELinux SID in @sid into a NetLabel security attribute.
2467 * SID. Returns zero values on success, negative values on failure. The 2424 * 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 * 2425 *
2471 */ 2426 */
2472static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) 2427int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2473{ 2428{
2474 int rc = -ENOENT; 2429 int rc = -ENOENT;
2475 struct sk_security_struct *sksec = sock->sk->sk_security;
2476 struct netlbl_lsm_secattr secattr;
2477 struct context *ctx; 2430 struct context *ctx;
2478 2431
2432 netlbl_secattr_init(secattr);
2433
2479 if (!ss_initialized) 2434 if (!ss_initialized)
2480 return 0; 2435 return 0;
2481 2436
2482 netlbl_secattr_init(&secattr);
2483
2484 POLICY_RDLOCK; 2437 POLICY_RDLOCK;
2485
2486 ctx = sidtab_search(&sidtab, sid); 2438 ctx = sidtab_search(&sidtab, sid);
2487 if (ctx == NULL) 2439 if (ctx == NULL)
2488 goto netlbl_socket_setsid_return; 2440 goto netlbl_sid_to_secattr_failure;
2489 2441 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], 2442 GFP_ATOMIC);
2491 GFP_ATOMIC); 2443 secattr->flags |= NETLBL_SECATTR_DOMAIN;
2492 secattr.flags |= NETLBL_SECATTR_DOMAIN; 2444 mls_export_netlbl_lvl(ctx, secattr);
2493 mls_export_netlbl_lvl(ctx, &secattr); 2445 rc = mls_export_netlbl_cat(ctx, secattr);
2494 rc = mls_export_netlbl_cat(ctx, &secattr);
2495 if (rc != 0) 2446 if (rc != 0)
2496 goto netlbl_socket_setsid_return; 2447 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; 2448 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
2530/**
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 2449
2548/** 2450 return 0;
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 2451
2452netlbl_sid_to_secattr_failure:
2453 POLICY_RDUNLOCK;
2454 netlbl_secattr_destroy(secattr);
2762 return rc; 2455 return rc;
2763} 2456}
2764#endif /* CONFIG_NETLABEL */ 2457#endif /* CONFIG_NETLABEL */