OPENAFS-SA-2024-003: xdr: Initialize memory for INOUT args

CVE-2024-10397

Currently, there are a few callers of RPCs that specify some data for
an INOUT parameter, but do not initialize the memory for that data.
This can result in the uninitialized memory being sent to the peer
when the argument is processed as an IN argument. Simply clear the
relevant data before running the RPC to avoid this.

The relevant RPCs and arguments are:

- For RMTSYS_Pioctl, the 'OutData' argument.

- For BUDB_GetVolumes, the 'volumes' argument.
-- via DBLookupByVolume -> bcdb_LookupVolume -> ubik_BUDB_GetVolumes
-- and via bc_Restorer -> bcdb_FindVolumes -> ubik_BUDB_GetVolumes

- For KAA_Authenticate_old / KAA_Authenticate, this can happen with
  the 'answer' argument in ka_Authenticate if KAA_AuthenticateV2 or
  KAA_Authenticate return RXGEN_OPCODE, but the server manages to
  populate oanswer.SeqLen with non-zero.

For all of these, make sure the memory is blanked before running the
relevant RPC. For ka_Authenticate, reset oanswer.SeqLen to 0 to avoid
sending any data, but still blank 'answer' and 'answer_old' just to be
safe.

FIXES 135043

Change-Id: I95ee91a1710d66e2e88c3086d57c279a376f7dc6
Reviewed-on: https://gerrit.openafs.org/15925
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
Andrew Deason 2020-10-15 21:07:17 -05:00 committed by Benjamin Kaduk
parent f31a79d749
commit c4e28c2afe
5 changed files with 10 additions and 2 deletions

View File

@ -466,6 +466,8 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
goto out_idata;
}
memset(odata.rmtbulk_val, 0, out_size);
AFS_GUNLOCK();
code = RMTSYS_Pioctl(rmtsys_conn, &ccred, abspath, com, follow,
&idata, &odata, &err);

View File

@ -2725,6 +2725,8 @@ DBLookupByVolume(char *volumeName)
char vname[BU_MAXNAMELEN];
char ds[50];
memset(volumeEntry, 0, sizeof(volumeEntry));
for (pass = 0; pass < 2; pass++) {
/*p */
/* On second pass, search for backup volume */

View File

@ -191,7 +191,7 @@ bc_Restorer(afs_int32 aindex)
serverAll = HOSTADDR(&dumpTaskPtr->destServer);
partitionAll = dumpTaskPtr->destPartition;
volumeEntries = malloc(MAXTAPESATONCE * sizeof(struct budb_volumeEntry));
volumeEntries = calloc(MAXTAPESATONCE, sizeof(struct budb_volumeEntry));
if (!volumeEntries) {
afs_com_err(whoami, BC_NOMEM, NULL);
ERROR(BC_NOMEM);

View File

@ -524,12 +524,15 @@ ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * con
oanswer.MaxSeqLen = sizeof(answer);
oanswer.SeqLen = 0;
oanswer.SeqBody = (char *)&answer;
memset(&answer, 0, sizeof(answer));
memset(&answer_old, 0, sizeof(answer_old));
version = 2;
code =
kawrap_ubik_Call(KAA_AuthenticateV2, conn, 0, name, instance,
(void*)(uintptr_t)start, (void*)(uintptr_t)end, &arequest, &oanswer, 0, 0);
if (code == RXGEN_OPCODE) {
oanswer.SeqLen = 0;
oanswer.MaxSeqLen = sizeof(answer);
oanswer.SeqBody = (char *)&answer;
version = 1;
@ -537,6 +540,7 @@ ka_Authenticate(char *name, char *instance, char *cell, struct ubik_client * con
ubik_KAA_Authenticate(conn, 0, name, instance, start, end,
&arequest, &oanswer);
if (code == RXGEN_OPCODE) {
oanswer.SeqLen = 0;
oanswer.MaxSeqLen = sizeof(answer_old);
oanswer.SeqBody = (char *)&answer_old;
version = 0;

View File

@ -214,7 +214,7 @@ pioctl(char *path, afs_int32 cmd, struct ViceIoctl *data, afs_int32 follow)
inparam_conversion(cmd, InData.rmtbulk_val, 0);
OutData.rmtbulk_len = MAXBUFFERLEN * sizeof(*OutData.rmtbulk_val);
OutData.rmtbulk_val = malloc(OutData.rmtbulk_len);
OutData.rmtbulk_val = calloc(1, OutData.rmtbulk_len);
if (!OutData.rmtbulk_val) {
free(inbuffer);
return -1;