Re: [PATCH 2/2] libselinux: support multiple contexts for the file backend
Stephen Smalley <[email protected]> Tue, 21 Jul 2026 11:45:13 -0400
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAEjxPJ6zcYW7_mGPhnTNV5oq-8uxsmDJxnXFoZjxyYYg7ce76A@mail.gmail.com> |
On Mon, Jul 20, 2026 at 10:11 PM Thiébaud Weksteen <[email protected]> wrote: > > Update the file labeling backend to support specifying multiple > SELABEL_OPT_PATH options in selabel_open(). > > All provided paths are stored in rec->spec_files and processed during > initialization. Derived files, such as substitutions (.subs, .subs_dist) > and auxiliary contexts (.homedirs, .local), continue to be based on the > first path (or default selinux_file_context_path()) when enabled. > > Duplicate checking logic is refactored into a helper function > report_dups(). A duplicate with the same specification result is not > fatal anymore, but a warning is still logged. > > Additionally, duplicate validation is moved after all files (including > .homedirs and .local) are loaded and sorted. For single file context setups, > the only difference in behavior is that duplicate validation now extends to > fc.homedirs and fc.local. > > A similar multiple files setup has been used in Android for 9+ years. > > Signed-off-by: Thiébaud Weksteen <[email protected]> > --- > libselinux/src/label_file.c | 216 ++++++++++++++++++++++-------------- > 1 file changed, 132 insertions(+), 84 deletions(-) > > diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c > index eb2e66da..902c9a25 100644 > --- a/libselinux/src/label_file.c > +++ b/libselinux/src/label_file.c > @@ -1526,66 +1584,56 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, > &data->subs_num, &data->subs_alloc); > if (status) > goto finish; > - path = selinux_file_context_path(); > + rec->spec_files[0] = strdup(selinux_file_context_path()); > + if (rec->spec_files[0] == NULL) > + goto finish; > } else { > - snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path); > + snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", > + rec->spec_files[0]); > status = selabel_subs_init(subs_file, rec->digest, > &data->dist_subs, > &data->dist_subs_num, > &data->dist_subs_alloc); > if (status) > goto finish; > - snprintf(subs_file, sizeof(subs_file), "%s.subs", path); > + snprintf(subs_file, sizeof(subs_file), "%s.subs", > + rec->spec_files[0]); > status = selabel_subs_init(subs_file, rec->digest, &data->subs, > &data->subs_num, &data->subs_alloc); > if (status) > goto finish; > } > - > #endif > > - if (!path) { > - errno = EINVAL; > - goto finish; > - } > - > - rec->spec_files = calloc(1, sizeof(path)); > - if (!rec->spec_files) > - goto finish; > - rec->spec_files[0] = strdup(path); > - if (!rec->spec_files[0]) > - goto finish; > - rec->spec_files_len = 1; > - > /* > - * The do detailed validation of the input and fill the spec array > + * Process each input file. > */ > - status = process_file(path, NULL, rec, prefix, rec->digest, 0); > - if (status) > - goto finish; > - > - if (rec->validating) { > - sort_specs(data); > - > - status = nodups_spec_node(data->root, path); > + for (i = 0; i < num_paths; i++) { > + status = process_file(rec->spec_files[i], NULL, rec, prefix, > + rec->digest, i); process_file() last argument is uint8_t; i and num_paths are size_t. Need to cap the max num_paths somewhere or change the type. > if (status) > goto finish; > } > > if (!baseonly) { > - status = process_file(path, "homedirs", rec, prefix, > - rec->digest, 1); > + status = process_file(rec->spec_files[0], "homedirs", rec, > + prefix, rec->digest, num_paths + 1); Ditto. > if (status && errno != ENOENT) > goto finish; > > - status = process_file(path, "local", rec, prefix, rec->digest, > - 2); > + status = process_file(rec->spec_files[0], "local", rec, prefix, > + rec->digest, num_paths + 2); Ditto > if (status && errno != ENOENT) > goto finish; > } > > - if (!rec->validating || !baseonly) > - sort_specs(data); > + sort_specs(data); > + > + if (rec->validating) { > + status = nodups_spec_node(rec, data->root); > + if (status) > + goto finish; > + } > > digest_gen_hash(rec->digest); > > -- > 2.55.0.229.g6434b31f56-goog >