Re: [PATCH 2/2] libselinux: support multiple contexts for the file backend
Stephen Smalley <[email protected]> Tue, 21 Jul 2026 12:36:39 -0400
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <CAEjxPJ7OXC8MjBN_o6jm9W6Ewm6u9gj+sxKfy_wYaxt1+qW6=Q@mail.gmail.com> |
On Tue, Jul 21, 2026 at 11:45 AM Stephen Smalley <[email protected]> wrote: > > 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. Also, could use num_paths here since i ends at num_paths - 1. > > > 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 And this could be num_path + 1. > > > 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 > >