From: Tobias Brunner Date: Mon, 20 Dec 2021 14:11:37 +0000 (+0100) Subject: kernel-interface: Optionally consider security label when allocating reqids X-Git-Tag: 5.9.6rc1~3^2~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6cb83c305e6a51d25c9c8f9e99f611d23fdf7097;p=thirdparty%2Fstrongswan.git kernel-interface: Optionally consider security label when allocating reqids --- diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c index 8f6c21b615..01c814ab5c 100644 --- a/src/libcharon/kernel/kernel_interface.c +++ b/src/libcharon/kernel/kernel_interface.c @@ -208,6 +208,8 @@ typedef struct { uint32_t if_id_in; /** outbound interface ID used for SA */ uint32_t if_id_out; + /** security label */ + sec_label_t *label; /** local traffic selectors */ array_t *local; /** 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->remote, offsetof(traffic_selector_t, destroy)); + DESTROY_IF(entry->label); 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 */ static u_int hash_reqid(reqid_entry_t *entry) { return chunk_hash_inc(chunk_from_thing(entry->reqid), - 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)))))); + entry_hash_shared(entry)); } /** @@ -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) { - return a->reqid == b->reqid && - 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; + if (a->reqid == b->reqid) + { + return entry_equals_shared(a, b); + } + return FALSE; } /** @@ -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) { - return hash_ts_array(entry->local, hash_ts_array(entry->remote, - 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))))))); + return hash_ts_array(entry->local, + hash_ts_array(entry->remote, + entry_hash_shared(entry))); } /** @@ -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) { - return ts_array_equals(a->local, b->local) && - ts_array_equals(a->remote, b->remote) && - 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; + if (ts_array_equals(a->local, b->local) && + ts_array_equals(a->remote, b->remote)) + { + return entry_equals_shared(a, b); + } + return FALSE; } /** @@ -346,7 +372,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t, private_kernel_interface_t *this, 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, - uint32_t *reqid) + sec_label_t *label, uint32_t *reqid) { static uint32_t counter = 0; reqid_entry_t *entry = NULL, *tmpl; @@ -359,6 +385,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t, .mark_out = mark_out, .if_id_in = if_id_in, .if_id_out = if_id_out, + .label = label ? label->clone(label) : NULL, .reqid = *reqid, ); @@ -404,7 +431,8 @@ METHOD(kernel_interface_t, alloc_reqid, status_t, METHOD(kernel_interface_t, release_reqid, status_t, 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 = reqid, @@ -412,6 +440,7 @@ METHOD(kernel_interface_t, release_reqid, status_t, .mark_out = mark_out, .if_id_in = if_id_in, .if_id_out = if_id_out, + .label = label, }; this->mutex->lock(this->mutex); diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h index dbc863736b..fd56853473 100644 --- a/src/libcharon/kernel/kernel_interface.h +++ b/src/libcharon/kernel/kernel_interface.h @@ -145,13 +145,15 @@ struct kernel_interface_t { * @param mark_out outbound mark on SA * @param if_id_in inbound 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 * @return SUCCESS if reqid allocated */ status_t (*alloc_reqid)(kernel_interface_t *this, 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, uint32_t *reqid); + uint32_t if_id_out, sec_label_t *label, + uint32_t *reqid); /** * Release a previously allocated reqid. @@ -161,11 +163,13 @@ struct kernel_interface_t { * @param mark_out outbound mark on SA * @param if_id_in inbound 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 */ status_t (*release_reqid)(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); + uint32_t if_id_in, uint32_t if_id_out, + sec_label_t *label); /** * Add an SA to the SAD. diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c index f876831382..3c4c1d4393 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -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, 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) { my_ts->destroy(my_ts); @@ -1258,7 +1258,7 @@ METHOD(child_sa_t, install_policies, status_t, status = charon->kernel->alloc_reqid( charon->kernel, my_ts_list, other_ts_list, 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); other_ts_list->destroy(other_ts_list); if (status != SUCCESS) @@ -1744,7 +1744,7 @@ METHOD(child_sa_t, destroy, void, { if (charon->kernel->release_reqid(charon->kernel, 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); }