[PATCH v3 4/5] libselinux: stringrep: snapshot perm names in security_av_string()
Stephen Smalley <[email protected]>
| Newsgroups | org.kernel.vger.selinux |
|---|---|
| Message-ID | <[email protected]> |
security_av_string() makes two passes, one to compute the length of the string and one to populate it. Internally this calls security_av_perm_to_string() on both passes, but they might not be consistent if there is an interleaving policy reload that triggers a selinux_flush_class_cache(). Save the permission name pointers during the first pass to ensure we use the same ones during the second pass. The pointers remain valid because selinux_flush_class_cache() merely retires the nodes rather than freeing them. Signed-off-by: Stephen Smalley <[email protected]> --- libselinux/src/stringrep.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c index cd9841ca..6a59f1c0 100644 --- a/libselinux/src/stringrep.c +++ b/libselinux/src/stringrep.c @@ -342,16 +342,16 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res) size_t len = 5; access_vector_t tmp = av; int rc = 0; - const char *str; + const char *perm[MAXVECTORS] = { NULL }; char *ptr; /* first pass computes the required length */ for (i = 0; tmp; tmp >>= 1, i++) { if (tmp & 1) { - str = security_av_perm_to_string( + perm[i] = security_av_perm_to_string( tclass, av & (UINT32_C(1) << i)); - if (str) - len += strlen(str) + 1; + if (perm[i]) + len += strlen(perm[i]) + 1; } } @@ -372,12 +372,8 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res) ptr += sprintf(ptr, "{ "); for (i = 0; tmp; tmp >>= 1, i++) { - if (tmp & 1) { - str = security_av_perm_to_string( - tclass, av & (UINT32_C(1) << i)); - if (str) - ptr += sprintf(ptr, "%s ", str); - } + if ((tmp & 1) && perm[i]) + ptr += sprintf(ptr, "%s ", perm[i]); } sprintf(ptr, "}"); out: -- 2.54.0