mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-25 07:49:18 +00:00
ctl: fix Use-After-Free in ctl_write_buffer
The virtio_scsi device allows a guest VM to directly send SCSI commands to the kernel driver exposed on /dev/cam/ctl. This setup makes the vulnerability directly accessible from VMs through the pci_virtio_scsi bhyve device. The function ctl_write_buffer sets the CTL_FLAG_ALLOCATED flag, causing the kern_data_ptr to be freed when the command finishes processing. However, the buffer is still stored in lun->write_buffer, leading to a Use-After-Free vulnerability. Since the buffer needs to persist indefinitely, so it can be accessed by READ BUFFER, do not set CTL_FLAG_ALLOCATED. Reported by: Synacktiv Reviewed by: Pierre Pronchery <pierre@freebsdfoundation.org> Reviewed by: jhb Security: FreeBSD-SA-24:11.ctl Security: CVE-2024-45063 Security: HYP-03 Sponsored by: Axcient Sponsored by: The Alpha-Omega Project Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D46424
This commit is contained in:
parent
5c9308a413
commit
670b582db6
@ -5625,21 +5625,24 @@ ctl_write_buffer(struct ctl_scsiio *ctsio)
|
||||
return (CTL_RETVAL_COMPLETE);
|
||||
}
|
||||
|
||||
if (lun->write_buffer == NULL) {
|
||||
lun->write_buffer = malloc(CTL_WRITE_BUFFER_SIZE,
|
||||
M_CTL, M_WAITOK);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've got a kernel request that hasn't been malloced yet,
|
||||
* malloc it and tell the caller the data buffer is here.
|
||||
* If this kernel request hasn't started yet, initialize the data
|
||||
* buffer to the correct region of the LUN's write buffer. Note that
|
||||
* this doesn't set CTL_FLAG_ALLOCATED since this points into a
|
||||
* persistent buffer belonging to the LUN rather than a buffer
|
||||
* dedicated to this request.
|
||||
*/
|
||||
if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
|
||||
if (lun->write_buffer == NULL) {
|
||||
lun->write_buffer = malloc(CTL_WRITE_BUFFER_SIZE,
|
||||
M_CTL, M_WAITOK);
|
||||
}
|
||||
if (ctsio->kern_data_ptr == NULL) {
|
||||
ctsio->kern_data_ptr = lun->write_buffer + buffer_offset;
|
||||
ctsio->kern_data_len = len;
|
||||
ctsio->kern_total_len = len;
|
||||
ctsio->kern_rel_offset = 0;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
|
||||
ctsio->be_move_done = ctl_config_move_done;
|
||||
ctl_datamove((union ctl_io *)ctsio);
|
||||
|
||||
|
@ -355,6 +355,14 @@ struct ctl_lun {
|
||||
uint8_t pr_res_type;
|
||||
int prevent_count;
|
||||
uint32_t *prevent;
|
||||
|
||||
/*
|
||||
* The READ_BUFFER and WRITE_BUFFER commands permit access to a logical
|
||||
* data buffer associated with a LUN. Accesses to the data buffer do
|
||||
* not affect data stored on the storage medium. To support this,
|
||||
* allocate a buffer on first use that persists until the LUN is
|
||||
* destroyed.
|
||||
*/
|
||||
uint8_t *write_buffer;
|
||||
struct ctl_devid *lun_devid;
|
||||
TAILQ_HEAD(tpc_lists, tpc_list) tpc_lists;
|
||||
|
Loading…
Reference in New Issue
Block a user