OPENAFS-SA-2024-002: make VIOCGETAL consumers stay within string bounds

CVE-2024-10396

After the preceding commits, the data returned by the VIOCGETAL
pioctl (a RXAFS_FetchAcl wrapper) will safely be NUL-terminated.
However, the callers that attempt to parse the ACL string make
assumptions that the returned data will be properly formatted,
and implement a "skip to next line" functionality (under various
names) that blindly increments a char* until it finds a newline
character, which can read past the end of even a properly
NUL-terminated string if there is not a newline where one is
expected.

Adjust the various "skip to next line" functionality to keep
the current string pointer at the trailing NUL if the end of the
string is reached while searching for a newline.

Change-Id: I7fb7f23d7d6f68608f3e656a1530a7fc40b4a567
Reviewed-on: https://gerrit.openafs.org/15916
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
Benjamin Kaduk 2024-11-04 20:50:50 -08:00
parent 7e13414e8e
commit a4ecb05054
7 changed files with 22 additions and 11 deletions

View File

@ -81,9 +81,10 @@ PruneList (struct AclEntry **ae, int dfs)
static char *
SkipLine (char *astr)
{
while (*astr !='\n')
while (*astr != '\0' && *astr !='\n')
astr++;
astr++;
if (*astr == '\n')
astr++;
return astr;
}

View File

@ -190,7 +190,7 @@ find_me(char *arg, char *parent_dir)
return 1; /* found it */
}
#define SkipLine(str) { while (*str !='\n') str++; str++; }
#define SkipLine(str) do { while (*str != '\0' && *str !='\n') str++; if (*str == '\n') str++; } while(0)
/* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
static int

View File

@ -385,9 +385,10 @@ char *
SkipLine(astr)
char *astr;
{
while (*astr != '\n')
while (*astr != '\0' && *astr != '\n')
astr++;
if (*astr == '\n')
astr++;
astr++;
return astr;
}

View File

@ -1652,9 +1652,13 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
cur_acl.cell);
ptr = strchr(old_acl_string, '\n');
if (ptr == NULL)
goto fail_afsclient_ACLEntryAdd;
ptr++;
sscanf(ptr, "%d", &cur_acl.nminus);
ptr = strchr(ptr, '\n');
if (ptr == NULL)
goto fail_afsclient_ACLEntryAdd;
ptr++;
if (is_dfs == 3) {
tst = ADMMISCNODFSACL;
@ -1681,6 +1685,8 @@ afsclient_ACLEntryAdd(const char *directory, const char *user,
if (strcmp(cur_user, user)) {
ptr = strchr(ptr, '\n');
if (ptr == NULL)
goto fail_afsclient_ACLEntryAdd;
ptr++;
sprintf(tmp, "%s %d\n", cur_user, cur_user_acl);
strcat(new_acl_string, tmp);

View File

@ -55,9 +55,10 @@ struct ClearToken {
char *
RSkipLine(char *astr)
{
while (*astr != '\n')
while (*astr != '\0' && *astr != '\n')
astr++;
if (*astr == '\n')
astr++;
astr++;
return astr;
}

View File

@ -339,9 +339,10 @@ static char *
SkipLine(char *a_str)
{ /*SkipLine */
while (*a_str != '\n')
while (*a_str != '\0' && *a_str != '\n')
a_str++;
if (*a_str == '\n')
a_str++;
a_str++;
return (a_str);
} /*SkipLine */

View File

@ -553,9 +553,10 @@ PruneList(struct AclEntry **ae, int dfs)
static char *
SkipLine(char *astr)
{
while (*astr != '\n')
while (*astr != '\0' && *astr != '\n')
astr++;
if (*astr == '\n')
astr++;
astr++;
return astr;
}