[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1450784813-18304-6-git-send-email-huw@codeweavers.com>
Date: Tue, 22 Dec 2015 11:46:41 +0000
From: Huw Davies <huw@...eweavers.com>
To: netdev@...r.kernel.org, linux-security-module@...r.kernel.org,
selinux@...ho.nsa.gov
Cc: Paul Moore <pmoore@...hat.com>
Subject: [RFC PATCH 05/17] netlabel: Add support for enumerating the CALIPSO DOI list.
Enumerate the DOI list through the NLBL_CALIPSO_C_LISTALL command.
It takes no attributes.
Signed-off-by: Huw Davies <huw@...eweavers.com>
---
include/net/netlabel.h | 4 ++
net/ipv6/calipso.c | 41 ++++++++++++++++
net/netlabel/netlabel_calipso.c | 106 ++++++++++++++++++++++++++++++++++++++++
net/netlabel/netlabel_calipso.h | 3 ++
4 files changed, 154 insertions(+)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index e072350..c6e1ce9 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -225,6 +225,7 @@ struct netlbl_lsm_secattr {
* @doi_free: free a CALIPSO DOI
* @doi_getdef: returns a reference to a DOI
* @doi_putdef: releases a reference of a DOI
+ * @doi_walk: enumerate the DOI list
*
* Description:
* This structure is filled out by the CALIPSO engine and passed
@@ -238,6 +239,9 @@ struct netlbl_calipso_ops {
void (*doi_free)(struct calipso_doi *doi_def);
struct calipso_doi *(*doi_getdef)(u32 doi);
void (*doi_putdef)(struct calipso_doi *doi_def);
+ int (*doi_walk)(u32 *skip_cnt,
+ int (*callback)(struct calipso_doi *doi_def, void *arg),
+ void *cb_arg);
};
/*
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 128cc69..fa17c7a 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -210,11 +210,52 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def)
call_rcu(&doi_def->rcu, calipso_doi_free_rcu);
}
+/**
+ * calipso_doi_walk - Iterate through the DOI definitions
+ * @skip_cnt: skip past this number of DOI definitions, updated
+ * @callback: callback for each DOI definition
+ * @cb_arg: argument for the callback function
+ *
+ * Description:
+ * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
+ * For each entry call @callback, if @callback returns a negative value stop
+ * 'walking' through the list and return. Updates the value in @skip_cnt upon
+ * return. Returns zero on success, negative values on failure.
+ *
+ */
+static int calipso_doi_walk(u32 *skip_cnt,
+ int (*callback)(struct calipso_doi *doi_def,
+ void *arg),
+ void *cb_arg)
+{
+ int ret_val = -ENOENT;
+ u32 doi_cnt = 0;
+ struct calipso_doi *iter_doi;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter_doi, &calipso_doi_list, list)
+ if (atomic_read(&iter_doi->refcount) > 0) {
+ if (doi_cnt++ < *skip_cnt)
+ continue;
+ ret_val = callback(iter_doi, cb_arg);
+ if (ret_val < 0) {
+ doi_cnt--;
+ goto doi_walk_return;
+ }
+ }
+
+doi_walk_return:
+ rcu_read_unlock();
+ *skip_cnt = doi_cnt;
+ return ret_val;
+}
+
static const struct netlbl_calipso_ops ops = {
.doi_add = calipso_doi_add,
.doi_free = calipso_doi_free,
.doi_getdef = calipso_doi_getdef,
.doi_putdef = calipso_doi_putdef,
+ .doi_walk = calipso_doi_walk,
};
/**
diff --git a/net/netlabel/netlabel_calipso.c b/net/netlabel/netlabel_calipso.c
index 1effc61..a014ec2 100644
--- a/net/netlabel/netlabel_calipso.c
+++ b/net/netlabel/netlabel_calipso.c
@@ -46,6 +46,13 @@
#include "netlabel_mgmt.h"
#include "netlabel_domainhash.h"
+/* Argument struct for calipso_doi_walk() */
+struct netlbl_calipso_doiwalk_arg {
+ struct netlink_callback *nl_cb;
+ struct sk_buff *skb;
+ u32 seq;
+};
+
/* NetLabel Generic NETLINK CALIPSO family */
static struct genl_family netlbl_calipso_gnl_family = {
.id = GENL_ID_GENERATE,
@@ -187,6 +194,73 @@ list_failure:
return ret_val;
}
+/**
+ * netlbl_calipso_listall_cb - calipso_v4_doi_walk() callback for LISTALL
+ * @doi_def: the CALIPSO DOI definition
+ * @arg: the netlbl_calipso_doiwalk_arg structure
+ *
+ * Description:
+ * This function is designed to be used as a callback to the
+ * calipso_doi_walk() function for use in generating a response for a LISTALL
+ * message. Returns the size of the message on success, negative values on
+ * failure.
+ *
+ */
+static int netlbl_calipso_listall_cb(struct calipso_doi *doi_def, void *arg)
+{
+ int ret_val = -ENOMEM;
+ struct netlbl_calipso_doiwalk_arg *cb_arg = arg;
+ void *data;
+
+ data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
+ cb_arg->seq, &netlbl_calipso_gnl_family,
+ NLM_F_MULTI, NLBL_CALIPSO_C_LISTALL);
+ if (!data)
+ goto listall_cb_failure;
+
+ ret_val = nla_put_u32(cb_arg->skb, NLBL_CALIPSO_A_DOI, doi_def->doi);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+ ret_val = nla_put_u32(cb_arg->skb,
+ NLBL_CALIPSO_A_MTYPE,
+ doi_def->type);
+ if (ret_val != 0)
+ goto listall_cb_failure;
+
+ genlmsg_end(cb_arg->skb, data);
+ return 0;
+
+listall_cb_failure:
+ genlmsg_cancel(cb_arg->skb, data);
+ return ret_val;
+}
+
+/**
+ * netlbl_calipso_listall - Handle a LISTALL message
+ * @skb: the NETLINK buffer
+ * @cb: the NETLINK callback
+ *
+ * Description:
+ * Process a user generated LISTALL message and respond accordingly. Returns
+ * zero on success and negative values on error.
+ *
+ */
+static int netlbl_calipso_listall(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct netlbl_calipso_doiwalk_arg cb_arg;
+ u32 doi_skip = cb->args[0];
+
+ cb_arg.nl_cb = cb;
+ cb_arg.skb = skb;
+ cb_arg.seq = cb->nlh->nlmsg_seq;
+
+ calipso_doi_walk(&doi_skip, netlbl_calipso_listall_cb, &cb_arg);
+
+ cb->args[0] = doi_skip;
+ return skb->len;
+}
+
/* NetLabel Generic NETLINK Command Definitions
*/
@@ -205,6 +279,13 @@ static const struct genl_ops netlbl_calipso_ops[] = {
.doit = netlbl_calipso_list,
.dumpit = NULL,
},
+ {
+ .cmd = NLBL_CALIPSO_C_LISTALL,
+ .flags = 0,
+ .policy = calipso_genl_policy,
+ .doit = NULL,
+ .dumpit = netlbl_calipso_listall,
+ },
};
/* NetLabel Generic NETLINK Protocol Functions
@@ -319,3 +400,28 @@ void calipso_doi_putdef(struct calipso_doi *doi_def)
if (ops)
ops->doi_putdef(doi_def);
}
+
+/**
+ * calipso_doi_walk - Iterate through the DOI definitions
+ * @skip_cnt: skip past this number of DOI definitions, updated
+ * @callback: callback for each DOI definition
+ * @cb_arg: argument for the callback function
+ *
+ * Description:
+ * Iterate over the DOI definition list, skipping the first @skip_cnt entries.
+ * For each entry call @callback, if @callback returns a negative value stop
+ * 'walking' through the list and return. Updates the value in @skip_cnt upon
+ * return. Returns zero on success, negative values on failure.
+ *
+ */
+int calipso_doi_walk(u32 *skip_cnt,
+ int (*callback)(struct calipso_doi *doi_def, void *arg),
+ void *cb_arg)
+{
+ int ret_val = -ENOMSG;
+ const struct netlbl_calipso_ops *ops = netlbl_calipso_ops_get();
+
+ if (ops)
+ ret_val = ops->doi_walk(skip_cnt, callback, cb_arg);
+ return ret_val;
+}
diff --git a/net/netlabel/netlabel_calipso.h b/net/netlabel/netlabel_calipso.h
index 6cf1cad..5d86752 100644
--- a/net/netlabel/netlabel_calipso.h
+++ b/net/netlabel/netlabel_calipso.h
@@ -126,5 +126,8 @@ int calipso_doi_add(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);
+int calipso_doi_walk(u32 *skip_cnt,
+ int (*callback)(struct calipso_doi *doi_def, void *arg),
+ void *cb_arg);
#endif
--
1.8.0
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists