Commit a5e34490 authored by Huw Davies's avatar Huw Davies Committed by Paul Moore

netlabel: Add support for querying a CALIPSO DOI.

Query a specified DOI through the NLBL_CALIPSO_C_LIST command.
It requires the attribute:
 NLBL_CALIPSO_A_DOI.

The reply will contain:
 NLBL_CALIPSO_A_MTYPE
Signed-off-by: default avatarHuw Davies <huw@codeweavers.com>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent cb72d382
...@@ -223,6 +223,8 @@ struct netlbl_lsm_secattr { ...@@ -223,6 +223,8 @@ struct netlbl_lsm_secattr {
* struct netlbl_calipso_ops - NetLabel CALIPSO operations * struct netlbl_calipso_ops - NetLabel CALIPSO operations
* @doi_add: add a CALIPSO DOI * @doi_add: add a CALIPSO DOI
* @doi_free: free a CALIPSO DOI * @doi_free: free a CALIPSO DOI
* @doi_getdef: returns a reference to a DOI
* @doi_putdef: releases a reference of a DOI
* *
* Description: * Description:
* This structure is filled out by the CALIPSO engine and passed * This structure is filled out by the CALIPSO engine and passed
...@@ -234,6 +236,8 @@ struct netlbl_calipso_ops { ...@@ -234,6 +236,8 @@ struct netlbl_calipso_ops {
int (*doi_add)(struct calipso_doi *doi_def, int (*doi_add)(struct calipso_doi *doi_def,
struct netlbl_audit *audit_info); struct netlbl_audit *audit_info);
void (*doi_free)(struct calipso_doi *doi_def); void (*doi_free)(struct calipso_doi *doi_def);
struct calipso_doi *(*doi_getdef)(u32 doi);
void (*doi_putdef)(struct calipso_doi *doi_def);
}; };
/* /*
......
...@@ -144,9 +144,77 @@ static void calipso_doi_free(struct calipso_doi *doi_def) ...@@ -144,9 +144,77 @@ static void calipso_doi_free(struct calipso_doi *doi_def)
kfree(doi_def); kfree(doi_def);
} }
/**
* calipso_doi_free_rcu - Frees a DOI definition via the RCU pointer
* @entry: the entry's RCU field
*
* Description:
* This function is designed to be used as a callback to the call_rcu()
* function so that the memory allocated to the DOI definition can be released
* safely.
*
*/
static void calipso_doi_free_rcu(struct rcu_head *entry)
{
struct calipso_doi *doi_def;
doi_def = container_of(entry, struct calipso_doi, rcu);
calipso_doi_free(doi_def);
}
/**
* calipso_doi_getdef - Returns a reference to a valid DOI definition
* @doi: the DOI value
*
* Description:
* Searches for a valid DOI definition and if one is found it is returned to
* the caller. Otherwise NULL is returned. The caller must ensure that
* calipso_doi_putdef() is called when the caller is done.
*
*/
static struct calipso_doi *calipso_doi_getdef(u32 doi)
{
struct calipso_doi *doi_def;
rcu_read_lock();
doi_def = calipso_doi_search(doi);
if (!doi_def)
goto doi_getdef_return;
if (!atomic_inc_not_zero(&doi_def->refcount))
doi_def = NULL;
doi_getdef_return:
rcu_read_unlock();
return doi_def;
}
/**
* calipso_doi_putdef - Releases a reference for the given DOI definition
* @doi_def: the DOI definition
*
* Description:
* Releases a DOI definition reference obtained from calipso_doi_getdef().
*
*/
static void calipso_doi_putdef(struct calipso_doi *doi_def)
{
if (!doi_def)
return;
if (!atomic_dec_and_test(&doi_def->refcount))
return;
spin_lock(&calipso_doi_list_lock);
list_del_rcu(&doi_def->list);
spin_unlock(&calipso_doi_list_lock);
call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
}
static const struct netlbl_calipso_ops ops = { static const struct netlbl_calipso_ops ops = {
.doi_add = calipso_doi_add, .doi_add = calipso_doi_add,
.doi_free = calipso_doi_free, .doi_free = calipso_doi_free,
.doi_getdef = calipso_doi_getdef,
.doi_putdef = calipso_doi_putdef,
}; };
/** /**
......
...@@ -124,6 +124,65 @@ static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info) ...@@ -124,6 +124,65 @@ static int netlbl_calipso_add(struct sk_buff *skb, struct genl_info *info)
return ret_val; return ret_val;
} }
/**
* netlbl_calipso_list - Handle a LIST message
* @skb: the NETLINK buffer
* @info: the Generic NETLINK info block
*
* Description:
* Process a user generated LIST message and respond accordingly.
* Returns zero on success and negative values on error.
*
*/
static int netlbl_calipso_list(struct sk_buff *skb, struct genl_info *info)
{
int ret_val;
struct sk_buff *ans_skb = NULL;
void *data;
u32 doi;
struct calipso_doi *doi_def;
if (!info->attrs[NLBL_CALIPSO_A_DOI]) {
ret_val = -EINVAL;
goto list_failure;
}
doi = nla_get_u32(info->attrs[NLBL_CALIPSO_A_DOI]);
doi_def = calipso_doi_getdef(doi);
if (!doi_def) {
ret_val = -EINVAL;
goto list_failure;
}
ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!ans_skb) {
ret_val = -ENOMEM;
goto list_failure_put;
}
data = genlmsg_put_reply(ans_skb, info, &netlbl_calipso_gnl_family,
0, NLBL_CALIPSO_C_LIST);
if (!data) {
ret_val = -ENOMEM;
goto list_failure_put;
}
ret_val = nla_put_u32(ans_skb, NLBL_CALIPSO_A_MTYPE, doi_def->type);
if (ret_val != 0)
goto list_failure_put;
calipso_doi_putdef(doi_def);
genlmsg_end(ans_skb, data);
return genlmsg_reply(ans_skb, info);
list_failure_put:
calipso_doi_putdef(doi_def);
list_failure:
kfree_skb(ans_skb);
return ret_val;
}
/* NetLabel Generic NETLINK Command Definitions /* NetLabel Generic NETLINK Command Definitions
*/ */
...@@ -135,6 +194,13 @@ static const struct genl_ops netlbl_calipso_ops[] = { ...@@ -135,6 +194,13 @@ static const struct genl_ops netlbl_calipso_ops[] = {
.doit = netlbl_calipso_add, .doit = netlbl_calipso_add,
.dumpit = NULL, .dumpit = NULL,
}, },
{
.cmd = NLBL_CALIPSO_C_LIST,
.flags = 0,
.policy = calipso_genl_policy,
.doit = netlbl_calipso_list,
.dumpit = NULL,
},
}; };
/* NetLabel Generic NETLINK Protocol Functions /* NetLabel Generic NETLINK Protocol Functions
...@@ -214,3 +280,39 @@ void calipso_doi_free(struct calipso_doi *doi_def) ...@@ -214,3 +280,39 @@ void calipso_doi_free(struct calipso_doi *doi_def)
if (ops) if (ops)
ops->doi_free(doi_def); ops->doi_free(doi_def);
} }
/**
* calipso_doi_getdef - Returns a reference to a valid DOI definition
* @doi: the DOI value
*
* Description:
* Searches for a valid DOI definition and if one is found it is returned to
* the caller. Otherwise NULL is returned. The caller must ensure that
* calipso_doi_putdef() is called when the caller is done.
*
*/
struct calipso_doi *calipso_doi_getdef(u32 doi)
{
struct calipso_doi *ret_val = NULL;
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ret_val = ops->doi_getdef(doi);
return ret_val;
}
/**
* calipso_doi_putdef - Releases a reference for the given DOI definition
* @doi_def: the DOI definition
*
* Description:
* Releases a DOI definition reference obtained from calipso_doi_getdef().
*
*/
void calipso_doi_putdef(struct calipso_doi *doi_def)
{
const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
if (ops)
ops->doi_putdef(doi_def);
}
...@@ -46,6 +46,23 @@ ...@@ -46,6 +46,23 @@
* *
* If using CALIPSO_MAP_PASS no additional attributes are required. * If using CALIPSO_MAP_PASS no additional attributes are required.
* *
* o LIST:
* Sent by an application to list the details of a DOI definition. On
* success the kernel should send a response using the following format.
*
* Required attributes:
*
* NLBL_CALIPSO_A_DOI
*
* The valid response message format depends on the type of the DOI mapping,
* the defined formats are shown below.
*
* Required attributes:
*
* NLBL_CALIPSO_A_MTYPE
*
* If using CALIPSO_MAP_PASS no additional attributes are required.
*
*/ */
/* NetLabel CALIPSO commands */ /* NetLabel CALIPSO commands */
...@@ -86,5 +103,7 @@ static inline int netlbl_calipso_genl_init(void) ...@@ -86,5 +103,7 @@ static inline int netlbl_calipso_genl_init(void)
int calipso_doi_add(struct calipso_doi *doi_def, int calipso_doi_add(struct calipso_doi *doi_def,
struct netlbl_audit *audit_info); struct netlbl_audit *audit_info);
void calipso_doi_free(struct calipso_doi *doi_def); void calipso_doi_free(struct calipso_doi *doi_def);
struct calipso_doi *calipso_doi_getdef(u32 doi);
void calipso_doi_putdef(struct calipso_doi *doi_def);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment