libselinux: introduce context_to_str(3)

Currently context_t offers the function context_str(3) to get the
formatted security context of the internal representation. The return
value is a pointer to an internally, on call allocated, stored cache.
This can lead to invalidation issues and if the caller wants to store
the result duplicate allocations.

Introduce context_to_str(3) not using any internal cache and moving
ownership of the string to the client.

Use in appropriate places.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: James Carter <jwcart2@gmail.com>
This commit is contained in:
Christian Göttsche 2025-02-26 10:44:08 +01:00 committed by James Carter
parent f3a7a2e8a9
commit 79abfc65e6
6 changed files with 52 additions and 10 deletions

View File

@ -27,6 +27,14 @@ extern "C" {
extern const char *context_str(context_t con);
/*
* Return the string value of the context_t.
* Similar to context_str(3), but the client owns the string
* and needs to free it via free(3).
*/
extern char *context_to_str(context_t con);
/* Free the storage used by a context */
extern void context_free(context_t con);

View File

@ -141,6 +141,36 @@ const char *context_str(context_t context)
}
/*
* Return a new string value of the context.
*/
char *context_to_str(context_t context)
{
const context_private_t *n = context->ptr;
char *buf;
size_t total = 0;
for (int i = 0; i < 4; i++) {
if (n->component[i]) {
total += strlen(n->component[i]) + 1;
}
}
buf = malloc(total);
if (buf != NULL) {
char *cp = buf;
cp = stpcpy(cp, n->component[0]);
for (int i = 1; i < 4; i++) {
if (n->component[i]) {
*cp++ = ':';
cp = stpcpy(cp, n->component[i]);
}
}
}
return buf;
}
/* Returns nonzero iff failed */
static int set_comp(context_private_t * n, int idx, const char *str)
{

View File

@ -145,7 +145,7 @@ static int get_context_user(FILE * fp,
char *linerole, *linetype;
char **new_reachable = NULL;
char *usercon_str;
const char *usercon_str2;
char *usercon_str2;
context_t usercon;
int rc;
@ -255,7 +255,7 @@ static int get_context_user(FILE * fp,
rc = -1;
goto out;
}
usercon_str2 = context_str(usercon);
usercon_str2 = context_to_str(usercon);
if (!usercon_str2) {
context_free(usercon);
rc = -1;
@ -264,6 +264,7 @@ static int get_context_user(FILE * fp,
/* check whether usercon is already in reachable */
if (is_in_reachable(*reachable, usercon_str2)) {
free(usercon_str2);
context_free(usercon);
start = end;
continue;
@ -271,20 +272,18 @@ static int get_context_user(FILE * fp,
if (security_check_context(usercon_str2) == 0) {
new_reachable = reallocarray(*reachable, *nreachable + 2, sizeof(char *));
if (!new_reachable) {
free(usercon_str2);
context_free(usercon);
rc = -1;
goto out;
}
*reachable = new_reachable;
new_reachable[*nreachable] = strdup(usercon_str2);
if (new_reachable[*nreachable] == NULL) {
context_free(usercon);
rc = -1;
goto out;
}
new_reachable[*nreachable] = usercon_str2;
usercon_str2 = NULL;
new_reachable[*nreachable + 1] = 0;
*nreachable += 1;
}
free(usercon_str2);
context_free(usercon);
start = end;
}

View File

@ -257,3 +257,8 @@ LIBSELINUX_3.8 {
global:
matchpathcon_filespec_add64;
} LIBSELINUX_3.5;
LIBSELINUX_3.9 {
global:
context_to_str;
} LIBSELINUX_3.8;

View File

@ -633,7 +633,7 @@ static int compare_portions(const char *curcon, const char *newcon,
}
if (update) {
*newtypecon = strdup(context_str(curctx));
*newtypecon = context_to_str(curctx);
if (!*newtypecon) {
rc = -1;
goto err;

View File

@ -34,7 +34,7 @@ int setexecfilecon(const char *filename, const char *fallback_type)
if (context_type_set(con, fallback_type))
goto out;
freecon(newcon);
newcon = strdup(context_str(con));
newcon = context_to_str(con);
if (!newcon)
goto out;
}