From: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> Order netifcon definitions with a wildcard interface name last in object contexts, so the kernel tries to match literal names first. Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> --- libsepol/cil/src/cil_post.c | 36 ++++++++++++++++++++++++++++++--- libsepol/src/kernel_to_common.c | 36 ++++++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c index d63a5496..70e5b734 100644 --- a/libsepol/cil/src/cil_post.c +++ b/libsepol/cil/src/cil_post.c @@ -316,10 +316,40 @@ int cil_post_genfscon_compare(const void *a, const void *b) int cil_post_netifcon_compare(const void *a, const void *b) { - struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a; - struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b; + /* keep in sync with kernel_to_common.c:netif_data_cmp() */ + const struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a; + const struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b; + const char *a_name = anetifcon->interface_str; + const char *b_name = bnetifcon->interface_str; + size_t a_stem = strcspn(a_name, "*?"); + size_t b_stem = strcspn(b_name, "*?"); + size_t a_len = strlen(a_name); + size_t b_len = strlen(b_name); + int a_iswildcard = a_stem != a_len; + int b_iswildcard = b_stem != b_len; + int rc; + + /* order non-wildcards first */ + rc = spaceship_cmp(a_iswildcard, b_iswildcard); + if (rc) + return rc; + + /* order non-wildcards alphabetically */ + if (!a_iswildcard) + return strcmp(a_name, b_name); + + /* order by decreasing stem length */ + rc = spaceship_cmp(a_stem, b_stem); + if (rc) + return -rc; + + /* order '?' (0x3f) before '*' (0x2A) */ + rc = spaceship_cmp(a_name[a_stem], b_name[b_stem]); + if (rc) + return -rc; - return strcmp(anetifcon->interface_str, bnetifcon->interface_str); + /* order alphabetically */ + return strcmp(a_name, b_name); } int cil_post_ibendportcon_compare(const void *a, const void *b) diff --git a/libsepol/src/kernel_to_common.c b/libsepol/src/kernel_to_common.c index 44f0be23..e4338ec6 100644 --- a/libsepol/src/kernel_to_common.c +++ b/libsepol/src/kernel_to_common.c @@ -441,10 +441,40 @@ static int portcon_data_cmp(const void *a, const void *b) static int netif_data_cmp(const void *a, const void *b) { - struct ocontext *const *aa = a; - struct ocontext *const *bb = b; + /* keep in sync with cil_post.c:cil_post_netifcon_compare() */ + const struct ocontext *const *aa = a; + const struct ocontext *const *bb = b; + const char *a_name = (*aa)->u.name; + const char *b_name = (*bb)->u.name; + size_t a_stem = strcspn(a_name, "*?"); + size_t b_stem = strcspn(b_name, "*?"); + size_t a_len = strlen(a_name); + size_t b_len = strlen(b_name); + int a_iswildcard = a_stem != a_len; + int b_iswildcard = b_stem != b_len; + int rc; - return strcmp((*aa)->u.name, (*bb)->u.name); + /* order non-wildcards first */ + rc = spaceship_cmp(a_iswildcard, b_iswildcard); + if (rc) + return rc; + + /* order non-wildcards alphabetically */ + if (!a_iswildcard) + return strcmp(a_name, b_name); + + /* order by decreasing stem length */ + rc = spaceship_cmp(a_stem, b_stem); + if (rc) + return -rc; + + /* order '?' (0x3f) before '*' (0x2A) */ + rc = spaceship_cmp(a_name[a_stem], b_name[b_stem]); + if (rc) + return -rc; + + /* order alphabetically */ + return strcmp(a_name, b_name); } static int node_data_cmp(const void *a, const void *b) -- 2.45.2