kernel-interface: Optionally consider security label when allocating reqids

This commit is contained in:
Tobias Brunner
2022-04-14 18:42:01 +02:00
parent 03729958db
commit 6cb83c305e
3 changed files with 64 additions and 31 deletions
+55 -26
View File
@@ -208,6 +208,8 @@ typedef struct {
uint32_t if_id_in; uint32_t if_id_in;
/** outbound interface ID used for SA */ /** outbound interface ID used for SA */
uint32_t if_id_out; uint32_t if_id_out;
/** security label */
sec_label_t *label;
/** local traffic selectors */ /** local traffic selectors */
array_t *local; array_t *local;
/** remote traffic selectors */ /** remote traffic selectors */
@@ -221,19 +223,49 @@ static void reqid_entry_destroy(reqid_entry_t *entry)
{ {
array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy)); array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy));
array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy)); array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy));
DESTROY_IF(entry->label);
free(entry); free(entry);
} }
/**
* Hash the shared data of reqid entries
*/
static u_int entry_hash_shared(reqid_entry_t *entry)
{
u_int hash;
hash = chunk_hash_inc(chunk_from_thing(entry->mark_in),
chunk_hash_inc(chunk_from_thing(entry->mark_out),
chunk_hash_inc(chunk_from_thing(entry->if_id_in),
chunk_hash(chunk_from_thing(entry->if_id_out)))));
if (entry->label)
{
hash = entry->label->hash(entry->label, hash);
}
return hash;
}
/**
* Compare the shared properties of reqid entries
*/
static bool entry_equals_shared(reqid_entry_t *a, reqid_entry_t *b)
{
return a->mark_in.value == b->mark_in.value &&
a->mark_in.mask == b->mark_in.mask &&
a->mark_out.value == b->mark_out.value &&
a->mark_out.mask == b->mark_out.mask &&
a->if_id_in == b->if_id_in &&
a->if_id_out == b->if_id_out &&
sec_labels_equal(a->label, b->label);
}
/** /**
* Hashtable hash function for reqid entries using reqid as key * Hashtable hash function for reqid entries using reqid as key
*/ */
static u_int hash_reqid(reqid_entry_t *entry) static u_int hash_reqid(reqid_entry_t *entry)
{ {
return chunk_hash_inc(chunk_from_thing(entry->reqid), return chunk_hash_inc(chunk_from_thing(entry->reqid),
chunk_hash_inc(chunk_from_thing(entry->mark_in), entry_hash_shared(entry));
chunk_hash_inc(chunk_from_thing(entry->mark_out),
chunk_hash_inc(chunk_from_thing(entry->if_id_in),
chunk_hash(chunk_from_thing(entry->if_id_out))))));
} }
/** /**
@@ -241,13 +273,11 @@ static u_int hash_reqid(reqid_entry_t *entry)
*/ */
static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b) static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b)
{ {
return a->reqid == b->reqid && if (a->reqid == b->reqid)
a->mark_in.value == b->mark_in.value && {
a->mark_in.mask == b->mark_in.mask && return entry_equals_shared(a, b);
a->mark_out.value == b->mark_out.value && }
a->mark_out.mask == b->mark_out.mask && return FALSE;
a->if_id_in == b->if_id_in &&
a->if_id_out == b->if_id_out;
} }
/** /**
@@ -273,11 +303,9 @@ static u_int hash_ts_array(array_t *array, u_int hash)
*/ */
static u_int hash_reqid_by_ts(reqid_entry_t *entry) static u_int hash_reqid_by_ts(reqid_entry_t *entry)
{ {
return hash_ts_array(entry->local, hash_ts_array(entry->remote, return hash_ts_array(entry->local,
chunk_hash_inc(chunk_from_thing(entry->mark_in), hash_ts_array(entry->remote,
chunk_hash_inc(chunk_from_thing(entry->mark_out), entry_hash_shared(entry)));
chunk_hash_inc(chunk_from_thing(entry->if_id_in),
chunk_hash(chunk_from_thing(entry->if_id_out)))))));
} }
/** /**
@@ -311,14 +339,12 @@ static bool ts_array_equals(array_t *a, array_t *b)
*/ */
static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b) static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
{ {
return ts_array_equals(a->local, b->local) && if (ts_array_equals(a->local, b->local) &&
ts_array_equals(a->remote, b->remote) && ts_array_equals(a->remote, b->remote))
a->mark_in.value == b->mark_in.value && {
a->mark_in.mask == b->mark_in.mask && return entry_equals_shared(a, b);
a->mark_out.value == b->mark_out.value && }
a->mark_out.mask == b->mark_out.mask && return FALSE;
a->if_id_in == b->if_id_in &&
a->if_id_out == b->if_id_out;
} }
/** /**
@@ -346,7 +372,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
private_kernel_interface_t *this, private_kernel_interface_t *this,
linked_list_t *local_ts, linked_list_t *remote_ts, linked_list_t *local_ts, linked_list_t *remote_ts,
mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out, mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out,
uint32_t *reqid) sec_label_t *label, uint32_t *reqid)
{ {
static uint32_t counter = 0; static uint32_t counter = 0;
reqid_entry_t *entry = NULL, *tmpl; reqid_entry_t *entry = NULL, *tmpl;
@@ -359,6 +385,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
.mark_out = mark_out, .mark_out = mark_out,
.if_id_in = if_id_in, .if_id_in = if_id_in,
.if_id_out = if_id_out, .if_id_out = if_id_out,
.label = label ? label->clone(label) : NULL,
.reqid = *reqid, .reqid = *reqid,
); );
@@ -404,7 +431,8 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
METHOD(kernel_interface_t, release_reqid, status_t, METHOD(kernel_interface_t, release_reqid, status_t,
private_kernel_interface_t *this, uint32_t reqid, private_kernel_interface_t *this, uint32_t reqid,
mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out) mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out,
sec_label_t *label)
{ {
reqid_entry_t *entry, tmpl = { reqid_entry_t *entry, tmpl = {
.reqid = reqid, .reqid = reqid,
@@ -412,6 +440,7 @@ METHOD(kernel_interface_t, release_reqid, status_t,
.mark_out = mark_out, .mark_out = mark_out,
.if_id_in = if_id_in, .if_id_in = if_id_in,
.if_id_out = if_id_out, .if_id_out = if_id_out,
.label = label,
}; };
this->mutex->lock(this->mutex); this->mutex->lock(this->mutex);
+6 -2
View File
@@ -145,13 +145,15 @@ struct kernel_interface_t {
* @param mark_out outbound mark on SA * @param mark_out outbound mark on SA
* @param if_id_in inbound interface ID on SA * @param if_id_in inbound interface ID on SA
* @param if_id_out outbound interface ID on SA * @param if_id_out outbound interface ID on SA
* @param label security label (usually the one on the policy, not SA)
* @param reqid allocated reqid * @param reqid allocated reqid
* @return SUCCESS if reqid allocated * @return SUCCESS if reqid allocated
*/ */
status_t (*alloc_reqid)(kernel_interface_t *this, status_t (*alloc_reqid)(kernel_interface_t *this,
linked_list_t *local_ts, linked_list_t *remote_ts, linked_list_t *local_ts, linked_list_t *remote_ts,
mark_t mark_in, mark_t mark_out, uint32_t if_id_in, mark_t mark_in, mark_t mark_out, uint32_t if_id_in,
uint32_t if_id_out, uint32_t *reqid); uint32_t if_id_out, sec_label_t *label,
uint32_t *reqid);
/** /**
* Release a previously allocated reqid. * Release a previously allocated reqid.
@@ -161,11 +163,13 @@ struct kernel_interface_t {
* @param mark_out outbound mark on SA * @param mark_out outbound mark on SA
* @param if_id_in inbound interface ID on SA * @param if_id_in inbound interface ID on SA
* @param if_id_out outbound interface ID on SA * @param if_id_out outbound interface ID on SA
* @param label security label (usually the one on the policy, not SA)
* @return SUCCESS if reqid released * @return SUCCESS if reqid released
*/ */
status_t (*release_reqid)(kernel_interface_t *this, uint32_t reqid, status_t (*release_reqid)(kernel_interface_t *this, uint32_t reqid,
mark_t mark_in, mark_t mark_out, mark_t mark_in, mark_t mark_out,
uint32_t if_id_in, uint32_t if_id_out); uint32_t if_id_in, uint32_t if_id_out,
sec_label_t *label);
/** /**
* Add an SA to the SAD. * Add an SA to the SAD.
+3 -3
View File
@@ -856,7 +856,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
{ {
status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts, status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
this->mark_in, this->mark_out, this->if_id_in, this->mark_in, this->mark_out, this->if_id_in,
this->if_id_out, &this->reqid); this->if_id_out, NULL, &this->reqid);
if (status != SUCCESS) if (status != SUCCESS)
{ {
my_ts->destroy(my_ts); my_ts->destroy(my_ts);
@@ -1258,7 +1258,7 @@ METHOD(child_sa_t, install_policies, status_t,
status = charon->kernel->alloc_reqid( status = charon->kernel->alloc_reqid(
charon->kernel, my_ts_list, other_ts_list, charon->kernel, my_ts_list, other_ts_list,
this->mark_in, this->mark_out, this->if_id_in, this->mark_in, this->mark_out, this->if_id_in,
this->if_id_out, &this->reqid); this->if_id_out, NULL, &this->reqid);
my_ts_list->destroy(my_ts_list); my_ts_list->destroy(my_ts_list);
other_ts_list->destroy(other_ts_list); other_ts_list->destroy(other_ts_list);
if (status != SUCCESS) if (status != SUCCESS)
@@ -1744,7 +1744,7 @@ METHOD(child_sa_t, destroy, void,
{ {
if (charon->kernel->release_reqid(charon->kernel, if (charon->kernel->release_reqid(charon->kernel,
this->reqid, this->mark_in, this->mark_out, this->reqid, this->mark_in, this->mark_out,
this->if_id_in, this->if_id_out) != SUCCESS) this->if_id_in, this->if_id_out, NULL) != SUCCESS)
{ {
DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid); DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
} }