Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: 9p: avoid freeing uninit memory in p9pdu_vreadf

If some of p9pdu_readf() calls inside case 'T' in p9pdu_vreadf() fails,
the error path is not handled properly. *wnames or members of *wnames
array may be left uninitialized and invalidly freed.

Initialize *wnames to NULL in beginning of case 'T'. Initialize the first
*wnames array element to NULL and nullify the failing *wnames element so
that the error path freeing loop stops on the first NULL element and
doesn't proceed further.

Found by Linux Verification Center (linuxtesting.org).

Fixes: ace51c4dd2f9 ("9p: add new protocol support code")
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
Message-ID: <20231206200913.16135-1-pchelkin@ispras.ru>
Cc: stable@vger.kernel.org
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>

authored by

Fedor Pchelkin and committed by
Dominique Martinet
ff49bf18 a931c681

+13 -4
+13 -4
net/9p/protocol.c
··· 394 394 uint16_t *nwname = va_arg(ap, uint16_t *); 395 395 char ***wnames = va_arg(ap, char ***); 396 396 397 + *wnames = NULL; 398 + 397 399 errcode = p9pdu_readf(pdu, proto_version, 398 400 "w", nwname); 399 401 if (!errcode) { ··· 405 403 GFP_NOFS); 406 404 if (!*wnames) 407 405 errcode = -ENOMEM; 406 + else 407 + (*wnames)[0] = NULL; 408 408 } 409 409 410 410 if (!errcode) { ··· 418 414 proto_version, 419 415 "s", 420 416 &(*wnames)[i]); 421 - if (errcode) 417 + if (errcode) { 418 + (*wnames)[i] = NULL; 422 419 break; 420 + } 423 421 } 424 422 } 425 423 ··· 429 423 if (*wnames) { 430 424 int i; 431 425 432 - for (i = 0; i < *nwname; i++) 426 + for (i = 0; i < *nwname; i++) { 427 + if (!(*wnames)[i]) 428 + break; 433 429 kfree((*wnames)[i]); 430 + } 431 + kfree(*wnames); 432 + *wnames = NULL; 434 433 } 435 - kfree(*wnames); 436 - *wnames = NULL; 437 434 } 438 435 } 439 436 break;