From: "Christian Göttsche" <cgzones@googlemail.com>
To: selinux@vger.kernel.org
Subject: [RFC PATCH v2 9/9] libselinux: support parallel selabel_lookup(3)
Date: Wed, 31 Jan 2024 14:08:35 +0100 [thread overview]
Message-ID: <20240131130840.48155-10-cgzones@googlemail.com> (raw)
In-Reply-To: <20240131130840.48155-1-cgzones@googlemail.com>
Support the parallel usage of the translated label lookup via
selabel_lookup(3) in multi threaded applications by locking the step
of computing the translated context and the validation state.
A potential use case might can usage from a Rust application via FFI.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v2: add patch
---
libselinux/src/label.c | 56 +++++++++++++++++++++++++++------
libselinux/src/label_db.c | 2 ++
libselinux/src/label_file.c | 4 ++-
libselinux/src/label_file.h | 4 +++
libselinux/src/label_internal.h | 1 +
libselinux/src/label_media.c | 1 +
libselinux/src/label_x.c | 1 +
7 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index d2e703ef..10e78a9b 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -124,18 +124,32 @@ static inline int selabel_is_validate_set(const struct selinux_opt *opts,
int selabel_validate(struct selabel_lookup_rec *contexts)
{
- int rc = 0;
+ bool validated;
+ int rc;
- if (contexts->validated)
- goto out;
+ validated = __atomic_load_n(&contexts->validated, __ATOMIC_ACQUIRE);
+ if (validated)
+ return 0;
+
+ __pthread_mutex_lock(&contexts->lock);
+
+ /* Check if another thread validated the context while we waited on the mutex */
+ validated = __atomic_load_n(&contexts->validated, __ATOMIC_ACQUIRE);
+ if (validated) {
+ __pthread_mutex_unlock(&contexts->lock);
+ return 0;
+ }
rc = selinux_validate(&contexts->ctx_raw);
+ if (rc == 0)
+ __atomic_store_n(&contexts->validated, true, __ATOMIC_RELEASE);
+
+ __pthread_mutex_unlock(&contexts->lock);
+
if (rc < 0)
- goto out;
+ return -1;
- contexts->validated = true;
-out:
- return rc;
+ return 0;
}
/* Public API helpers */
@@ -143,11 +157,35 @@ static int selabel_fini(const struct selabel_handle *rec,
struct selabel_lookup_rec *lr,
bool translating)
{
+ char *ctx_trans;
+ int rc;
+
if (compat_validate(rec, lr, rec->spec_file, lr->lineno))
return -1;
- if (translating && !lr->ctx_trans &&
- selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans))
+ if (!translating)
+ return 0;
+
+ ctx_trans = __atomic_load_n(&lr->ctx_trans, __ATOMIC_ACQUIRE);
+ if (ctx_trans)
+ return 0;
+
+ __pthread_mutex_lock(&lr->lock);
+
+ /* Check if another thread translated the context while we waited on the mutex */
+ ctx_trans = __atomic_load_n(&lr->ctx_trans, __ATOMIC_ACQUIRE);
+ if (ctx_trans) {
+ __pthread_mutex_unlock(&lr->lock);
+ return 0;
+ }
+
+ rc = selinux_raw_to_trans_context(lr->ctx_raw, &ctx_trans);
+ if (rc == 0)
+ __atomic_store_n(&lr->ctx_trans, ctx_trans, __ATOMIC_RELEASE);
+
+ __pthread_mutex_unlock(&lr->lock);
+
+ if (rc)
return -1;
return 0;
diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c
index 2ff10b2f..ed178d34 100644
--- a/libselinux/src/label_db.c
+++ b/libselinux/src/label_db.c
@@ -183,6 +183,7 @@ db_close(struct selabel_handle *rec)
free(spec->key);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
+ __pthread_mutex_destroy(&spec->lr.lock);
}
free(catalog);
}
@@ -355,6 +356,7 @@ out_error:
free(spec->key);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
+ __pthread_mutex_destroy(&spec->lr.lock);
}
free(catalog);
fclose(filp);
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index ac349bc5..3520fe2d 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -175,6 +175,7 @@ static int merge_mmap_spec_nodes(struct spec_node *restrict dest, struct spec_no
for (uint32_t i = 0; i < source->literal_specs_num; i++) {
source->literal_specs[i].lr.ctx_raw = NULL;
source->literal_specs[i].lr.ctx_trans = NULL;
+ __pthread_mutex_destroy(&source->literal_specs[i].lr.lock);
}
} else {
@@ -214,9 +215,10 @@ static int merge_mmap_spec_nodes(struct spec_node *restrict dest, struct spec_no
for (uint32_t i = 0; i < source->regex_specs_num; i++) {
source->regex_specs[i].lr.ctx_raw = NULL;
source->regex_specs[i].lr.ctx_trans = NULL;
+ __pthread_mutex_destroy(&source->regex_specs[i].lr.lock);
source->regex_specs[i].regex = NULL;
source->regex_specs[i].regex_compiled = false;
- __pthread_mutex_init(&source->regex_specs[i].regex_lock, NULL);
+ __pthread_mutex_destroy(&source->regex_specs[i].regex_lock);
}
} else {
assert(dest->regex_specs == NULL);
diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h
index 529a1bd2..de8190f9 100644
--- a/libselinux/src/label_file.h
+++ b/libselinux/src/label_file.h
@@ -661,6 +661,7 @@ static int insert_spec(const struct selabel_handle *rec, struct saved_data *data
.lr.ctx_trans = NULL,
.lr.lineno = lineno,
.lr.validated = false,
+ .lr.lock = PTHREAD_MUTEX_INITIALIZER,
};
data->num_specs++;
@@ -794,6 +795,7 @@ static int insert_spec(const struct selabel_handle *rec, struct saved_data *data
.lr.ctx_trans = NULL,
.lr.lineno = lineno,
.lr.validated = false,
+ .lr.lock = PTHREAD_MUTEX_INITIALIZER,
};
data->num_specs++;
@@ -818,6 +820,7 @@ static inline void free_spec_node(struct spec_node *node)
free(lspec->lr.ctx_raw);
free(lspec->lr.ctx_trans);
+ __pthread_mutex_destroy(&lspec->lr.lock);
if (lspec->from_mmap)
continue;
@@ -832,6 +835,7 @@ static inline void free_spec_node(struct spec_node *node)
free(rspec->lr.ctx_raw);
free(rspec->lr.ctx_trans);
+ __pthread_mutex_destroy(&rspec->lr.lock);
regex_data_free(rspec->regex);
__pthread_mutex_destroy(&rspec->regex_lock);
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index 854f92fa..743dbf94 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -71,6 +71,7 @@ extern void digest_gen_hash(struct selabel_digest *digest);
struct selabel_lookup_rec {
char * ctx_raw;
char * ctx_trans;
+ pthread_mutex_t lock; /* lock for validation and translation */
unsigned int lineno;
bool validated;
};
diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c
index fad5ea6d..7bd85804 100644
--- a/libselinux/src/label_media.c
+++ b/libselinux/src/label_media.c
@@ -172,6 +172,7 @@ static void close(struct selabel_handle *rec)
free(spec->key);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
+ __pthread_mutex_destroy(&spec->lr.lock);
}
if (spec_arr)
diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c
index bf569ca5..49c33b3b 100644
--- a/libselinux/src/label_x.c
+++ b/libselinux/src/label_x.c
@@ -199,6 +199,7 @@ static void close(struct selabel_handle *rec)
free(spec->key);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
+ __pthread_mutex_destroy(&spec->lr.lock);
}
if (spec_arr)
--
2.43.0
prev parent reply other threads:[~2024-01-31 13:08 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-31 13:08 [RFC PATCH v2 0/9] libselinux: rework selabel_file(5) database Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 1/9] policycoreutils: introduce unsetfiles Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 2/9] libselinux/utils: introduce selabel_compare Christian Göttsche
2024-03-07 19:50 ` James Carter
2024-03-11 17:20 ` Christian Göttsche
2024-03-11 20:49 ` James Carter
2024-01-31 13:08 ` [RFC PATCH v2 3/9] libselinux: use more appropriate types in sidtab Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 4/9] libselinux: add unique id to sidtab entries Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 5/9] libselinux: sidtab updates Christian Göttsche
2024-03-07 20:53 ` James Carter
2024-03-11 16:32 ` Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 6/9] libselinux: rework selabel_file(5) database Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 7/9] libselinux: remove unused hashtab code Christian Göttsche
2024-01-31 13:08 ` [RFC PATCH v2 8/9] libselinux: add selabel_file(5) fuzzer Christian Göttsche
2024-01-31 13:08 ` Christian Göttsche [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240131130840.48155-10-cgzones@googlemail.com \
--to=cgzones@googlemail.com \
--cc=selinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox