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

papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()

Fixes a UAF for src_info as well.

Link: https://patch.msgid.link/20251123-work-fd-prepare-v4-33-b6efa1706cfd@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

+9 -30
+9 -30
arch/powerpc/platforms/pseries/papr-hvpipe.c
··· 479 479 480 480 static int papr_hvpipe_dev_create_handle(u32 srcID) 481 481 { 482 - struct hvpipe_source_info *src_info; 483 - struct file *file; 484 - long err; 485 - int fd; 482 + struct hvpipe_source_info *src_info __free(kfree) = NULL; 486 483 487 484 spin_lock(&hvpipe_src_list_lock); 488 485 /* ··· 503 506 src_info->tsk = current; 504 507 init_waitqueue_head(&src_info->recv_wqh); 505 508 506 - fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); 507 - if (fd < 0) { 508 - err = fd; 509 - goto free_buf; 510 - } 509 + FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, 510 + anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops, 511 + (void *)src_info, O_RDWR)); 512 + if (fdf.err) 513 + return fdf.err; 511 514 512 - file = anon_inode_getfile("[papr-hvpipe]", 513 - &papr_hvpipe_handle_ops, (void *)src_info, 514 - O_RDWR); 515 - if (IS_ERR(file)) { 516 - err = PTR_ERR(file); 517 - goto free_fd; 518 - } 519 - 515 + retain_and_null_ptr(src_info); 520 516 spin_lock(&hvpipe_src_list_lock); 521 517 /* 522 518 * If two processes are executing ioctl() for the same ··· 518 528 */ 519 529 if (hvpipe_find_source(srcID)) { 520 530 spin_unlock(&hvpipe_src_list_lock); 521 - err = -EALREADY; 522 - goto free_file; 531 + return -EALREADY; 523 532 } 524 533 list_add(&src_info->list, &hvpipe_src_list); 525 534 spin_unlock(&hvpipe_src_list_lock); 526 - 527 - fd_install(fd, file); 528 - return fd; 529 - 530 - free_file: 531 - fput(file); 532 - free_fd: 533 - put_unused_fd(fd); 534 - free_buf: 535 - kfree(src_info); 536 - return err; 535 + return fd_publish(fdf); 537 536 } 538 537 539 538 /*