calipso: Allow the lsm to label the skbuff directly.

In some cases, the lsm needs to add the label to the skbuff directly.
A NF_INET_LOCAL_OUT IPv6 hook is added to selinux to match the IPv4
behaviour.  This allows selinux to label the skbuffs that it requires.

Signed-off-by: Huw Davies <[email protected]>
Signed-off-by: Paul Moore <[email protected]>
This commit is contained in:
Huw Davies 2016-06-27 15:06:15 -04:00 • committed by Paul Moore
commit 2917f57b6b
6 changed files with 308 additions and 4 deletions

View file

@ -618,3 +618,85 @@ void calipso_req_delattr(struct request_sock *req)
if (ops)
ops->req_delattr(req);
}
/**
* calipso_optptr - Find the CALIPSO option in the packet
* @skb: the packet
*
* Description:
* Parse the packet's IP header looking for a CALIPSO option. Returns a pointer
* to the start of the CALIPSO option on success, NULL if one if not found.
*
*/
unsigned char *calipso_optptr(const struct sk_buff *skb)
{
unsigned char *ret_val = NULL;
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ret_val = ops->skbuff_optptr(skb);
return ret_val;
}
/**
* calipso_getattr - Get the security attributes from a memory block.
* @calipso: the CALIPSO option
* @secattr: the security attributes
*
* Description:
* Inspect @calipso and return the security attributes in @secattr.
* Returns zero on success and negative values on failure.
*
*/
int calipso_getattr(const unsigned char *calipso,
struct netlbl_lsm_secattr *secattr)
{
int ret_val = -ENOMSG;
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ret_val = ops->opt_getattr(calipso, secattr);
return ret_val;
}
/**
* calipso_skbuff_setattr - Set the CALIPSO option on a packet
* @skb: the packet
* @doi_def: the CALIPSO DOI to use
* @secattr: the security attributes
*
* Description:
* Set the CALIPSO option on the given packet based on the security attributes.
* Returns a pointer to the IP header on success and NULL on failure.
*
*/
int calipso_skbuff_setattr(struct sk_buff *skb,
const struct calipso_doi *doi_def,
const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -ENOMSG;
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ret_val = ops->skbuff_setattr(skb, doi_def, secattr);
return ret_val;
}
/**
* calipso_skbuff_delattr - Delete any CALIPSO options from a packet
* @skb: the packet
*
* Description:
* Removes any and all CALIPSO options from the given packet. Returns zero on
* success, negative values on failure.
*
*/
int calipso_skbuff_delattr(struct sk_buff *skb)
{
int ret_val = -ENOMSG;
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ret_val = ops->skbuff_delattr(skb);
return ret_val;
}

View file

@ -137,5 +137,12 @@ int calipso_req_setattr(struct request_sock *req,
const struct calipso_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
void calipso_req_delattr(struct request_sock *req);
unsigned char *calipso_optptr(const struct sk_buff *skb);
int calipso_getattr(const unsigned char *calipso,
struct netlbl_lsm_secattr *secattr);
int calipso_skbuff_setattr(struct sk_buff *skb,
const struct calipso_doi *doi_def,
const struct netlbl_lsm_secattr *secattr);
int calipso_skbuff_delattr(struct sk_buff *skb);
#endif

View file

@ -1147,13 +1147,17 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
{
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);
entry = netlbl_domhsh_getentry_af4(secattr->domain,
hdr4->daddr);
if (entry == NULL) {
ret_val = -ENOENT;
goto skbuff_setattr_return;
@ -1174,9 +1178,26 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,
break;
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
/* since we don't support any IPv6 labeling protocols right
* now we can optimize everything away until we do */
ret_val = 0;
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:
@ -1215,6 +1236,9 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
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 */
}