// SPDX-License-Identifier: GPL-2.0-or-later /* * NetLabel Kernel API * * This file defines the kernel API for the NetLabel system. The NetLabel * system manages static and dynamic label mappings for network protocols such * as CIPSO and RIPSO. * * Author: Paul Moore <paul@paul-moore.com>
*/
/** * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping * @domain: the domain mapping to remove * @family: address family * @addr: IP address * @mask: IP address mask * @audit_info: NetLabel audit information * * Description: * Removes a NetLabel/LSM domain mapping. A @domain value of NULL causes the * default domain mapping to be removed. Returns zero on success, negative * values on failure. *
*/ int netlbl_cfg_map_del(constchar *domain,
u16 family, constvoid *addr, constvoid *mask, struct netlbl_audit *audit_info)
{ if (addr == NULL && mask == NULL) { return netlbl_domhsh_remove(domain, family, audit_info);
} elseif (addr != NULL && mask != NULL) { switch (family) { case AF_INET: return netlbl_domhsh_remove_af4(domain, addr, mask,
audit_info); #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: return netlbl_domhsh_remove_af6(domain, addr, mask,
audit_info); #endif/* IPv6 */ default: return -EPFNOSUPPORT;
}
} else return -EINVAL;
}
/** * netlbl_cfg_unlbl_map_add - Add a new unlabeled mapping * @domain: the domain mapping to add * @family: address family * @addr: IP address * @mask: IP address mask * @audit_info: NetLabel audit information * * Description: * Adds a new unlabeled NetLabel/LSM domain mapping. A @domain value of NULL * causes a new default domain mapping to be added. Returns zero on success, * negative values on failure. *
*/ int netlbl_cfg_unlbl_map_add(constchar *domain,
u16 family, constvoid *addr, constvoid *mask, struct netlbl_audit *audit_info)
{ int ret_val = -ENOMEM; struct netlbl_dom_map *entry; struct netlbl_domaddr_map *addrmap = NULL; struct netlbl_domaddr4_map *map4 = NULL; struct netlbl_domaddr6_map *map6 = NULL;
entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) return -ENOMEM; if (domain != NULL) {
entry->domain = kstrdup(domain, GFP_ATOMIC); if (entry->domain == NULL) goto cfg_unlbl_map_add_failure;
}
entry->family = family;
/** * netlbl_cfg_unlbl_static_add - Adds a new static label * @net: network namespace * @dev_name: interface name * @addr: IP address in network byte order (struct in[6]_addr) * @mask: address mask in network byte order (struct in[6]_addr) * @family: address family * @secid: LSM secid value for the entry * @audit_info: NetLabel audit information * * Description: * Adds a new NetLabel static label to be used when protocol provided labels * are not present on incoming traffic. If @dev_name is NULL then the default * interface will be used. Returns zero on success, negative values on failure. *
*/ int netlbl_cfg_unlbl_static_add(struct net *net, constchar *dev_name, constvoid *addr, constvoid *mask,
u16 family,
u32 secid, struct netlbl_audit *audit_info)
{
u32 addr_len;
/** * netlbl_cfg_unlbl_static_del - Removes an existing static label * @net: network namespace * @dev_name: interface name * @addr: IP address in network byte order (struct in[6]_addr) * @mask: address mask in network byte order (struct in[6]_addr) * @family: address family * @audit_info: NetLabel audit information * * Description: * Removes an existing NetLabel static label used when protocol provided labels * are not present on incoming traffic. If @dev_name is NULL then the default * interface will be used. Returns zero on success, negative values on failure. *
*/ int netlbl_cfg_unlbl_static_del(struct net *net, constchar *dev_name, constvoid *addr, constvoid *mask,
u16 family, struct netlbl_audit *audit_info)
{
u32 addr_len;
/** * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition * @doi_def: CIPSO DOI definition * @audit_info: NetLabel audit information * * Description: * Add a new CIPSO DOI definition as defined by @doi_def. Returns zero on * success and negative values on failure. *
*/ int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def, struct netlbl_audit *audit_info)
{ return cipso_v4_doi_add(doi_def, audit_info);
}
/** * netlbl_cfg_cipsov4_del - Remove an existing CIPSOv4 DOI definition * @doi: CIPSO DOI * @audit_info: NetLabel audit information * * Description: * Remove an existing CIPSO DOI definition matching @doi. Returns zero on * success and negative values on failure. *
*/ void netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
{
cipso_v4_doi_remove(doi, audit_info);
}
/** * netlbl_cfg_cipsov4_map_add - Add a new CIPSOv4 DOI mapping * @doi: the CIPSO DOI * @domain: the domain mapping to add * @addr: IP address * @mask: IP address mask * @audit_info: NetLabel audit information * * Description: * Add a new NetLabel/LSM domain mapping for the given CIPSO DOI to the NetLabel * subsystem. A @domain value of NULL adds a new default domain mapping. * Returns zero on success, negative values on failure. *
*/ int netlbl_cfg_cipsov4_map_add(u32 doi, constchar *domain, conststruct in_addr *addr, conststruct in_addr *mask, struct netlbl_audit *audit_info)
{ int ret_val = -ENOMEM; struct cipso_v4_doi *doi_def; struct netlbl_dom_map *entry; struct netlbl_domaddr_map *addrmap = NULL; struct netlbl_domaddr4_map *addrinfo = NULL;
doi_def = cipso_v4_doi_getdef(doi); if (doi_def == NULL) return -ENOENT;
entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) goto out_entry;
entry->family = AF_INET; if (domain != NULL) {
entry->domain = kstrdup(domain, GFP_ATOMIC); if (entry->domain == NULL) goto out_domain;
}
/** * netlbl_cfg_calipso_add - Add a new CALIPSO DOI definition * @doi_def: CALIPSO DOI definition * @audit_info: NetLabel audit information * * Description: * Add a new CALIPSO DOI definition as defined by @doi_def. Returns zero on * success and negative values on failure. *
*/ int netlbl_cfg_calipso_add(struct calipso_doi *doi_def, struct netlbl_audit *audit_info)
{ #if IS_ENABLED(CONFIG_IPV6) return calipso_doi_add(doi_def, audit_info); #else/* IPv6 */ return -ENOSYS; #endif/* IPv6 */
}
/** * netlbl_cfg_calipso_del - Remove an existing CALIPSO DOI definition * @doi: CALIPSO DOI * @audit_info: NetLabel audit information * * Description: * Remove an existing CALIPSO DOI definition matching @doi. Returns zero on * success and negative values on failure. *
*/ void netlbl_cfg_calipso_del(u32 doi, struct netlbl_audit *audit_info)
{ #if IS_ENABLED(CONFIG_IPV6)
calipso_doi_remove(doi, audit_info); #endif/* IPv6 */
}
/** * netlbl_cfg_calipso_map_add - Add a new CALIPSO DOI mapping * @doi: the CALIPSO DOI * @domain: the domain mapping to add * @addr: IP address * @mask: IP address mask * @audit_info: NetLabel audit information * * Description: * Add a new NetLabel/LSM domain mapping for the given CALIPSO DOI to the * NetLabel subsystem. A @domain value of NULL adds a new default domain * mapping. Returns zero on success, negative values on failure. *
*/ int netlbl_cfg_calipso_map_add(u32 doi, constchar *domain, conststruct in6_addr *addr, conststruct in6_addr *mask, struct netlbl_audit *audit_info)
{ #if IS_ENABLED(CONFIG_IPV6) int ret_val = -ENOMEM; struct calipso_doi *doi_def; struct netlbl_dom_map *entry; struct netlbl_domaddr_map *addrmap = NULL; struct netlbl_domaddr6_map *addrinfo = NULL;
doi_def = calipso_doi_getdef(doi); if (doi_def == NULL) return -ENOENT;
entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) goto out_entry;
entry->family = AF_INET6; if (domain != NULL) {
entry->domain = kstrdup(domain, GFP_ATOMIC); if (entry->domain == NULL) goto out_domain;
}
/** * _netlbl_catmap_getnode - Get a individual node from a catmap * @catmap: pointer to the category bitmap * @offset: the requested offset * @cm_flags: catmap flags, see _CM_F_* * @gfp_flags: memory allocation flags * * Description: * Iterate through the catmap looking for the node associated with @offset. * If the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node, * one will be created and inserted into the catmap. If the _CM_F_WALK flag is * set in @cm_flags and there is no associated node, the next highest node will * be returned. Returns a pointer to the node on success, NULL on failure. *
*/ staticstruct netlbl_lsm_catmap *_netlbl_catmap_getnode( struct netlbl_lsm_catmap **catmap,
u32 offset, unsignedint cm_flags,
gfp_t gfp_flags)
{ struct netlbl_lsm_catmap *iter = *catmap; struct netlbl_lsm_catmap *prev = NULL;
if (iter == NULL) goto catmap_getnode_alloc; if (offset < iter->startbit) goto catmap_getnode_walk; while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
prev = iter;
iter = iter->next;
} if (iter == NULL || offset < iter->startbit) goto catmap_getnode_walk;
return iter;
catmap_getnode_walk: if (cm_flags & _CM_F_WALK) return iter;
catmap_getnode_alloc: if (!(cm_flags & _CM_F_ALLOC)) return NULL;
iter = netlbl_catmap_alloc(gfp_flags); if (iter == NULL) return NULL;
iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1);
/** * netlbl_catmap_walk - Walk a LSM secattr catmap looking for a bit * @catmap: the category bitmap * @offset: the offset to start searching at, in bits * * Description: * This function walks a LSM secattr category bitmap starting at @offset and * returns the spot of the first set bit or -ENOENT if no bits are set. *
*/ int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap, u32 offset)
{ struct netlbl_lsm_catmap *iter;
u32 idx;
u32 bit;
u64 bitmap;
iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0); if (iter == NULL) return -ENOENT; if (offset > iter->startbit) {
offset -= iter->startbit;
idx = offset / NETLBL_CATMAP_MAPSIZE;
bit = offset % NETLBL_CATMAP_MAPSIZE;
} else {
idx = 0;
bit = 0;
}
bitmap = iter->bitmap[idx] >> bit;
for (;;) { if (bitmap != 0) { while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
bitmap >>= 1;
bit++;
} return iter->startbit +
(NETLBL_CATMAP_MAPSIZE * idx) + bit;
} if (++idx >= NETLBL_CATMAP_MAPCNT) { if (iter->next != NULL) {
iter = iter->next;
idx = 0;
} else return -ENOENT;
}
bitmap = iter->bitmap[idx];
bit = 0;
}
/** * netlbl_catmap_walkrng - Find the end of a string of set bits * @catmap: the category bitmap * @offset: the offset to start searching at, in bits * * Description: * This function walks a LSM secattr category bitmap starting at @offset and * returns the spot of the first cleared bit or -ENOENT if the offset is past * the end of the bitmap. *
*/ int netlbl_catmap_walkrng(struct netlbl_lsm_catmap *catmap, u32 offset)
{ struct netlbl_lsm_catmap *iter; struct netlbl_lsm_catmap *prev = NULL;
u32 idx;
u32 bit;
u64 bitmask;
u64 bitmap;
iter = _netlbl_catmap_getnode(&catmap, offset, _CM_F_WALK, 0); if (iter == NULL) return -ENOENT; if (offset > iter->startbit) {
offset -= iter->startbit;
idx = offset / NETLBL_CATMAP_MAPSIZE;
bit = offset % NETLBL_CATMAP_MAPSIZE;
} else {
idx = 0;
bit = 0;
}
bitmask = NETLBL_CATMAP_BIT << bit;
/** * netlbl_catmap_getlong - Export an unsigned long bitmap * @catmap: pointer to the category bitmap * @offset: pointer to the requested offset * @bitmap: the exported bitmap * * Description: * Export a bitmap with an offset greater than or equal to @offset and return * it in @bitmap. The @offset must be aligned to an unsigned long and will be * updated on return if different from what was requested; if the catmap is * empty at the requested offset and beyond, the @offset is set to (u32)-1. * Returns zero on success, negative values on failure. *
*/ int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap,
u32 *offset, unsignedlong *bitmap)
{ struct netlbl_lsm_catmap *iter;
u32 off = *offset;
u32 idx;
/* only allow aligned offsets */ if ((off & (BITS_PER_LONG - 1)) != 0) return -EINVAL;
/* a null catmap is equivalent to an empty one */ if (!catmap) {
*offset = (u32)-1; return 0;
}
if (off < catmap->startbit) {
off = catmap->startbit;
*offset = off;
}
iter = _netlbl_catmap_getnode(&catmap, off, _CM_F_WALK, 0); if (iter == NULL) {
*offset = (u32)-1; return 0;
}
if (off < iter->startbit) {
*offset = iter->startbit;
off = 0;
} else
off -= iter->startbit;
idx = off / NETLBL_CATMAP_MAPSIZE;
*bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_MAPSIZE);
return 0;
}
/** * netlbl_catmap_setbit - Set a bit in a LSM secattr catmap * @catmap: pointer to the category bitmap * @bit: the bit to set * @flags: memory allocation flags * * Description: * Set the bit specified by @bit in @catmap. Returns zero on success, * negative values on failure. *
*/ int netlbl_catmap_setbit(struct netlbl_lsm_catmap **catmap,
u32 bit,
gfp_t flags)
{ struct netlbl_lsm_catmap *iter;
u32 idx;
iter = _netlbl_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags); if (iter == NULL) return -ENOMEM;
bit -= iter->startbit;
idx = bit / NETLBL_CATMAP_MAPSIZE;
iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE);
return 0;
}
EXPORT_SYMBOL(netlbl_catmap_setbit);
/** * netlbl_catmap_setrng - Set a range of bits in a LSM secattr catmap * @catmap: pointer to the category bitmap * @start: the starting bit * @end: the last bit in the string * @flags: memory allocation flags * * Description: * Set a range of bits, starting at @start and ending with @end. Returns zero * on success, negative values on failure. *
*/ int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
u32 start,
u32 end,
gfp_t flags)
{ int rc = 0;
u32 spot = start;
/** * netlbl_catmap_setlong - Import an unsigned long bitmap * @catmap: pointer to the category bitmap * @offset: offset to the start of the imported bitmap * @bitmap: the bitmap to import * @flags: memory allocation flags * * Description: * Import the bitmap specified in @bitmap into @catmap, using the offset * in @offset. The offset must be aligned to an unsigned long. Returns zero * on success, negative values on failure. *
*/ int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,
u32 offset, unsignedlong bitmap,
gfp_t flags)
{ struct netlbl_lsm_catmap *iter;
u32 idx;
/* only allow aligned offsets */ if ((offset & (BITS_PER_LONG - 1)) != 0) return -EINVAL;
iter = _netlbl_catmap_getnode(catmap, offset, _CM_F_ALLOC, flags); if (iter == NULL) return -ENOMEM;
/** * netlbl_bitmap_walk - Walk a bitmap looking for a bit * @bitmap: the bitmap * @bitmap_len: length in bits * @offset: starting offset * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit * * Description: * Starting at @offset, walk the bitmap from left to right until either the * desired bit is found or we reach the end. Return the bit offset, -1 if * not found.
*/ int netlbl_bitmap_walk(constunsignedchar *bitmap, u32 bitmap_len,
u32 offset, u8 state)
{
u32 bit_spot;
u32 byte_offset; unsignedchar bitmask; unsignedchar byte;
/** * netlbl_bitmap_setbit - Sets a single bit in a bitmap * @bitmap: the bitmap * @bit: the bit * @state: if non-zero, set the bit (1) else clear the bit (0) * * Description: * Set a single bit in the bitmask. Returns zero on success, negative values * on error.
*/ void netlbl_bitmap_setbit(unsignedchar *bitmap, u32 bit, u8 state)
{
u32 byte_spot;
u8 bitmask;
/* gcc always rounds to zero when doing integer division */
byte_spot = bit / 8;
bitmask = 0x80 >> (bit % 8); if (state)
bitmap[byte_spot] |= bitmask; else
bitmap[byte_spot] &= ~bitmask;
}
EXPORT_SYMBOL(netlbl_bitmap_setbit);
/* * LSM Functions
*/
/** * netlbl_enabled - Determine if the NetLabel subsystem is enabled * * Description: * The LSM can use this function to determine if it should use NetLabel * security attributes in it's enforcement mechanism. Currently, NetLabel is * considered to be enabled when it's configuration contains a valid setup for * at least one labeled protocol (i.e. NetLabel can understand incoming * labeled packets of at least one type); otherwise NetLabel is considered to * be disabled. *
*/ int netlbl_enabled(void)
{ /* At some point we probably want to expose this mechanism to the user * as well so that admins can toggle NetLabel regardless of the
* configuration */ return (atomic_read(&netlabel_mgmt_protocount) > 0);
}
/** * netlbl_sock_setattr - Label a socket using the correct protocol * @sk: the socket to label * @family: protocol family * @secattr: the security attributes * @sk_locked: true if caller holds the socket lock * * Description: * Attach the correct label to the given socket using the security attributes * specified in @secattr. This function requires exclusive access to @sk, * which means it either needs to be in the process of being created or locked. * Returns zero on success, -EDESTADDRREQ if the domain is configured to use * network address selectors (can't blindly label the socket), and negative * values on all other failures. *
*/ int netlbl_sock_setattr(struct sock *sk,
u16 family, conststruct netlbl_lsm_secattr *secattr, bool sk_locked)
{ int ret_val; struct netlbl_dom_map *dom_entry;
/** * netlbl_sock_delattr - Delete all the NetLabel labels on a socket * @sk: the socket * * Description: * Remove all the NetLabel labeling from @sk. The caller is responsible for * ensuring that @sk is locked. *
*/ void netlbl_sock_delattr(struct sock *sk)
{ switch (sk->sk_family) { case AF_INET:
cipso_v4_sock_delattr(sk); break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6:
calipso_sock_delattr(sk); break; #endif/* IPv6 */
}
}
/** * netlbl_sock_getattr - Determine the security attributes of a sock * @sk: the sock * @secattr: the security attributes * * Description: * Examines the given sock to see if any NetLabel style labeling has been * applied to the sock, if so it parses the socket label and returns the * security attributes in @secattr. Returns zero on success, negative values * on failure. *
*/ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
{ int ret_val;
/** * netlbl_sk_lock_check - Check if the socket lock has been acquired. * @sk: the socket to be checked * * Return: true if socket @sk is locked or if lock debugging is disabled at * runtime or compile-time; false otherwise *
*/ #ifdef CONFIG_LOCKDEP bool netlbl_sk_lock_check(struct sock *sk)
{ if (debug_locks) return lockdep_sock_is_held(sk); returntrue;
} #else bool netlbl_sk_lock_check(struct sock *sk)
{ returntrue;
} #endif
/** * netlbl_conn_setattr - Label a connected socket using the correct protocol * @sk: the socket to label * @addr: the destination address * @secattr: the security attributes * * Description: * Attach the correct label to the given connected socket using the security * attributes specified in @secattr. The caller is responsible for ensuring * that @sk is locked. Returns zero on success, negative values on failure. *
*/ int netlbl_conn_setattr(struct sock *sk, struct sockaddr *addr, conststruct netlbl_lsm_secattr *secattr)
{ int ret_val; struct sockaddr_in *addr4; #if IS_ENABLED(CONFIG_IPV6) struct sockaddr_in6 *addr6; #endif struct netlbl_dommap_def *entry;
rcu_read_lock(); switch (addr->sa_family) { case AF_INET:
addr4 = (struct sockaddr_in *)addr;
entry = netlbl_domhsh_getentry_af4(secattr->domain,
addr4->sin_addr.s_addr); if (entry == NULL) {
ret_val = -ENOENT; goto conn_setattr_return;
} switch (entry->type) { case NETLBL_NLTYPE_CIPSOV4:
ret_val = cipso_v4_sock_setattr(sk,
entry->cipso, secattr,
netlbl_sk_lock_check(sk)); break; case NETLBL_NLTYPE_UNLABELED: /* just delete the protocols we support for right now
* but we could remove other protocols if needed */
netlbl_sock_delattr(sk);
ret_val = 0; break; default:
ret_val = -ENOENT;
} break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: if (sk->sk_family != AF_INET6) {
ret_val = -EAFNOSUPPORT; goto conn_setattr_return;
}
addr6 = (struct sockaddr_in6 *)addr;
entry = netlbl_domhsh_getentry_af6(secattr->domain,
&addr6->sin6_addr); if (entry == NULL) {
ret_val = -ENOENT; goto conn_setattr_return;
} switch (entry->type) { case NETLBL_NLTYPE_CALIPSO:
ret_val = calipso_sock_setattr(sk,
entry->calipso, secattr); break; case NETLBL_NLTYPE_UNLABELED: /* just delete the protocols we support for right now
* but we could remove other protocols if needed */
netlbl_sock_delattr(sk);
ret_val = 0; break; default:
ret_val = -ENOENT;
} break; #endif/* IPv6 */ default:
ret_val = -EPROTONOSUPPORT;
}
/** * netlbl_req_setattr - Label a request socket using the correct protocol * @req: the request socket to label * @secattr: the security attributes * * Description: * Attach the correct label to the given socket using the security attributes * specified in @secattr. Returns zero on success, negative values on failure. *
*/ int netlbl_req_setattr(struct request_sock *req, conststruct netlbl_lsm_secattr *secattr)
{ int ret_val; struct netlbl_dommap_def *entry; struct inet_request_sock *ireq = inet_rsk(req);
/** * netlbl_req_delattr - Delete all the NetLabel labels on a socket * @req: the socket * * Description: * Remove all the NetLabel labeling from @req. *
*/ void netlbl_req_delattr(struct request_sock *req)
{ switch (req->rsk_ops->family) { case AF_INET:
cipso_v4_req_delattr(req); break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6:
calipso_req_delattr(req); break; #endif/* IPv6 */
}
}
/** * netlbl_skbuff_setattr - Label a packet using the correct protocol * @skb: the packet * @family: protocol family * @secattr: the security attributes * * Description: * Attach the correct label to the given packet using the security attributes * specified in @secattr. Returns zero on success, negative values on failure. *
*/ int netlbl_skbuff_setattr(struct sk_buff *skb,
u16 family, conststruct netlbl_lsm_secattr *secattr)
{ int ret_val; struct iphdr *hdr4; #if IS_ENABLED(CONFIG_IPV6) struct ipv6hdr *hdr6; #endif struct netlbl_dommap_def *entry;
rcu_read_lock(); switch (family) { case AF_INET:
hdr4 = ip_hdr(skb);
entry = netlbl_domhsh_getentry_af4(secattr->domain,
hdr4->daddr); if (entry == NULL) {
ret_val = -ENOENT; goto skbuff_setattr_return;
} switch (entry->type) { case NETLBL_NLTYPE_CIPSOV4:
ret_val = cipso_v4_skbuff_setattr(skb, entry->cipso,
secattr); break; case NETLBL_NLTYPE_UNLABELED: /* just delete the protocols we support for right now
* but we could remove other protocols if needed */
ret_val = cipso_v4_skbuff_delattr(skb); break; default:
ret_val = -ENOENT;
} break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6:
hdr6 = ipv6_hdr(skb);
entry = netlbl_domhsh_getentry_af6(secattr->domain,
&hdr6->daddr); if (entry == NULL) {
ret_val = -ENOENT; goto skbuff_setattr_return;
} switch (entry->type) { case NETLBL_NLTYPE_CALIPSO:
ret_val = calipso_skbuff_setattr(skb, entry->calipso,
secattr); break; case NETLBL_NLTYPE_UNLABELED: /* just delete the protocols we support for right now
* but we could remove other protocols if needed */
ret_val = calipso_skbuff_delattr(skb); break; default:
ret_val = -ENOENT;
} break; #endif/* IPv6 */ default:
ret_val = -EPROTONOSUPPORT;
}
/** * netlbl_skbuff_getattr - Determine the security attributes of a packet * @skb: the packet * @family: protocol family * @secattr: the security attributes * * Description: * Examines the given packet to see if a recognized form of packet labeling * is present, if so it parses the packet label and returns the security * attributes in @secattr. Returns zero on success, negative values on * failure. *
*/ int netlbl_skbuff_getattr(conststruct sk_buff *skb,
u16 family, struct netlbl_lsm_secattr *secattr)
{ unsignedchar *ptr;
switch (family) { case AF_INET:
ptr = cipso_v4_optptr(skb); if (ptr && cipso_v4_getattr(ptr, secattr) == 0) return 0; break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6:
ptr = calipso_optptr(skb); if (ptr && calipso_getattr(ptr, secattr) == 0) return 0; break; #endif/* IPv6 */
}
/** * netlbl_skbuff_err - Handle a LSM error on a sk_buff * @skb: the packet * @family: the family * @error: the error code * @gateway: true if host is acting as a gateway, false otherwise * * Description: * Deal with a LSM problem when handling the packet in @skb, typically this is * a permission denied problem (-EACCES). The correct action is determined * according to the packet's labeling protocol. *
*/ void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway)
{ switch (family) { case AF_INET: if (cipso_v4_optptr(skb))
cipso_v4_error(skb, error, gateway); break;
}
}
/** * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches * * Description: * For all of the NetLabel protocols that support some form of label mapping * cache, invalidate the cache. Returns zero on success, negative values on * error. *
*/ void netlbl_cache_invalidate(void)
{
cipso_v4_cache_invalidate(); #if IS_ENABLED(CONFIG_IPV6)
calipso_cache_invalidate(); #endif/* IPv6 */
}
/** * netlbl_cache_add - Add an entry to a NetLabel protocol cache * @skb: the packet * @family: the family * @secattr: the packet's security attributes * * Description: * Add the LSM security attributes for the given packet to the underlying * NetLabel protocol's label mapping cache. Returns zero on success, negative * values on error. *
*/ int netlbl_cache_add(conststruct sk_buff *skb, u16 family, conststruct netlbl_lsm_secattr *secattr)
{ unsignedchar *ptr;
if ((secattr->flags & NETLBL_SECATTR_CACHE) == 0) return -ENOMSG;
switch (family) { case AF_INET:
ptr = cipso_v4_optptr(skb); if (ptr) return cipso_v4_cache_add(ptr, secattr); break; #if IS_ENABLED(CONFIG_IPV6) case AF_INET6:
ptr = calipso_optptr(skb); if (ptr) return calipso_cache_add(ptr, secattr); break; #endif/* IPv6 */
} return -ENOMSG;
}
/* * Protocol Engine Functions
*/
/** * netlbl_audit_start - Start an audit message * @type: audit message type * @audit_info: NetLabel audit information * * Description: * Start an audit message using the type specified in @type and fill the audit * message with some fields common to all NetLabel audit messages. This * function should only be used by protocol engines, not LSMs. Returns a * pointer to the audit buffer on success, NULL on failure. *
*/ struct audit_buffer *netlbl_audit_start(int type, struct netlbl_audit *audit_info)
{ return netlbl_audit_start_common(type, audit_info);
}
EXPORT_SYMBOL(netlbl_audit_start);
/* * Setup Functions
*/
/** * netlbl_init - Initialize NetLabel * * Description: * Perform the required NetLabel initialization before first use. *
*/ staticint __init netlbl_init(void)
{ int ret_val;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.