Skip to content

Commit

Permalink
libselinux: support parallel selabel_lookup(3)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cgzones committed Dec 20, 2023
1 parent 427e630 commit 414c040
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 10 deletions.
56 changes: 47 additions & 9 deletions libselinux/src/label.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,30 +121,68 @@ 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 */
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;
Expand Down
2 changes: 2 additions & 0 deletions libselinux/src/label_db.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -354,6 +355,7 @@ db_init(const struct selinux_opt *opts, unsigned nopts,
free(spec->key);
free(spec->lr.ctx_raw);
free(spec->lr.ctx_trans);
__pthread_mutex_destroy(&spec->lr.lock);
}
free(catalog);
fclose(filp);
Expand Down
4 changes: 3 additions & 1 deletion libselinux/src/label_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ static int merge_mmap_spec_nodes(struct spec_node *dest, struct spec_node *sourc
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 {
Expand Down Expand Up @@ -214,9 +215,10 @@ static int merge_mmap_spec_nodes(struct spec_node *dest, struct spec_node *sourc
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);
Expand Down
4 changes: 4 additions & 0 deletions libselinux/src/label_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,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++;
Expand Down Expand Up @@ -781,6 +782,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++;
Expand All @@ -805,6 +807,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;
Expand All @@ -819,6 +822,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);

Expand Down
1 change: 1 addition & 0 deletions libselinux/src/label_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
1 change: 1 addition & 0 deletions libselinux/src/label_media.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,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)
Expand Down
1 change: 1 addition & 0 deletions libselinux/src/label_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,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)
Expand Down

0 comments on commit 414c040

Please sign in to comment.