On Tue, Sep 1, 2020 at 7:59 AM liwugang <liwugang@xxxxxxx> wrote: > > The hash of each directory should be determined by the file contexts of > the current directory and subdirectories, but the existing logic also > includes the ancestor directories. The first optimization is to exclude > them. So it should be break When the first complete match found in function > lookup_all. > > If the current directory has corresponding file contexts and subdirectories > have not, subdirectories will use the current direcorty's. There is no need > to calculate the hash for the subdirectories. It will save time, espacially > for user data(/data/media/0/). The second optimization is not to check the > hash of the subdirectories. > > Example: > /data/(.*)? u:object_r:system_data_file:s0 > /data/backup(/.*)? u:object_r:backup_data_file:s0 > > If the file context of "/data/(.*)?" changes and "/data/backup(/.*)?" does not > change, directory(/data/backup) and the subdirectories will restorecon because of > hash changed. But actually there is no need the restorecon. > > Signed-off-by: liwugang <liwugang@xxxxxxx> > --- > libselinux/include/selinux/label.h | 5 +-- > libselinux/src/label.c | 11 +++--- > libselinux/src/label_file.c | 17 +++++++--- > libselinux/src/label_internal.h | 6 ++-- > libselinux/src/selinux_restorecon.c | 34 ++++++++++++++----- > .../selabel_get_digests_all_partial_matches.c | 3 +- > 6 files changed, 55 insertions(+), 21 deletions(-) > > diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h > index e8983606..d91ceb6f 100644 > --- a/libselinux/include/selinux/label.h > +++ b/libselinux/include/selinux/label.h > @@ -110,9 +110,10 @@ extern bool selabel_get_digests_all_partial_matches(struct selabel_handle *rec, > const char *key, > uint8_t **calculated_digest, > uint8_t **xattr_digest, > - size_t *digest_len); > + size_t *digest_len, > + size_t *num_matches); > extern bool selabel_hash_all_partial_matches(struct selabel_handle *rec, > - const char *key, uint8_t* digest); > + const char *key, uint8_t* digest, size_t *num_matches); > > extern int selabel_lookup_best_match(struct selabel_handle *rec, char **con, > const char *key, const char **aliases, int type); This is a public API and a stable ABI for libselinux, so you cannot make incompatible changes to it. You would need to introduce a new API with the extended interface. > diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c > index 6eeeea68..c99eb251 100644 > --- a/libselinux/src/label_file.c > +++ b/libselinux/src/label_file.c > @@ -955,7 +955,10 @@ static const struct spec **lookup_all(struct selabel_handle *rec, > if (match_count) { > result[*match_count] = spec; > *match_count += 1; > - // Continue to find all the matches. > + if (rc == REGEX_MATCH) { > + break; > + } > + // Continue to find the matches until the first full match found. I'm not sure this works the way you intend. /data/(.*)? is a full match for /data/backup. Do you want to stop there and not include /data/backup(/.*)? This also changes behavior of an existing API/ABI in an incompatible manner. > diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c > index 6993be6f..417b619c 100644 > --- a/libselinux/src/selinux_restorecon.c > +++ b/libselinux/src/selinux_restorecon.c Last I looked, Android wasn't using the upstream selinux_restorecon (which was actually a back-port / adaptation of Android's selinux_android_restorecon to upstream) at all, so any changes here won't actually affect Android relabeling AFAIK.