libsepol: fix use-after-free in sepol_user_clone()

When sepol_user_add_role() fails to allocate memory for role_cp but
succeeds in reallocating user->roles memory, it frees this reallocated
memory, thus leaving user->roles referencing a free memory block. When
sepol_user_clone() calls sepol_user_free(new_user) because the
allocation failure made sepol_user_add_role() fail, the following code
is executed:

    for (i = 0; i < user->num_roles; i++)
        free(user->roles[i]);
    free(user->roles);

As user->roles has been freed, this code frees pointers which may be
invalid and then tries to free user->roles again.

Fix this flaw by returning right after strdup() failed in
sepol_user_add_role().

This issue has been found using clang's static analyzer.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
This commit is contained in:
Nicolas Iooss 2017-03-28 23:41:49 +02:00 committed by James Carter
parent b6579d262e
commit b251dbba98

View file

@ -178,16 +178,18 @@ int sepol_user_add_role(sepol_handle_t * handle,
{ {
char *role_cp; char *role_cp;
char **roles_realloc; char **roles_realloc = NULL;
if (sepol_user_has_role(user, role)) if (sepol_user_has_role(user, role))
return STATUS_SUCCESS; return STATUS_SUCCESS;
role_cp = strdup(role); role_cp = strdup(role);
if (!role_cp)
goto omem;
roles_realloc = realloc(user->roles, roles_realloc = realloc(user->roles,
sizeof(char *) * (user->num_roles + 1)); sizeof(char *) * (user->num_roles + 1));
if (!roles_realloc)
if (!role_cp || !roles_realloc)
goto omem; goto omem;
user->num_roles++; user->num_roles++;