ctl_ioctl_frontend: Reject out-of-range initiator IDs

Various places in CTL assume that initiator IDs are not larger than
CTL_MAX_INIT_PER_PORT.  Other IDs such as lun IDs are validated in
places such as ctl_scsiio_precheck, but initiator IDs submitted by
userland were not previously validated.

PR:		291059
Reported by:	Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Reviewed by:	asomers
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D56628
This commit is contained in:
John Baldwin
2026-05-02 12:43:29 -04:00
parent 3e845b1090
commit 6f8312bdff
+8 -3
View File
@@ -588,7 +588,7 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td) struct thread *td)
{ {
struct cfi_port *cfi; struct cfi_port *cfi;
union ctl_io *io; union ctl_io *io, *user_io;
void *pool_tmp, *sc_tmp; void *pool_tmp, *sc_tmp;
int retval = 0; int retval = 0;
@@ -606,6 +606,11 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if ((cfi->port.status & CTL_PORT_STATUS_ONLINE) == 0) if ((cfi->port.status & CTL_PORT_STATUS_ONLINE) == 0)
return (EPERM); return (EPERM);
/* Reject out-of-range initiator IDs. */
user_io = (void *)addr;
if (user_io->io_hdr.nexus.initid >= CTL_MAX_INIT_PER_PORT)
return (EINVAL);
io = ctl_alloc_io(cfi->port.ctl_pool_ref); io = ctl_alloc_io(cfi->port.ctl_pool_ref);
/* /*
@@ -614,7 +619,7 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
*/ */
pool_tmp = io->io_hdr.pool; pool_tmp = io->io_hdr.pool;
sc_tmp = CTL_SOFTC(io); sc_tmp = CTL_SOFTC(io);
memcpy(io, (void *)addr, sizeof(*io)); memcpy(io, user_io, sizeof(*io));
io->io_hdr.pool = pool_tmp; io->io_hdr.pool = pool_tmp;
CTL_SOFTC(io) = sc_tmp; CTL_SOFTC(io) = sc_tmp;
TAILQ_INIT(&io->io_hdr.blocked_queue); TAILQ_INIT(&io->io_hdr.blocked_queue);
@@ -636,7 +641,7 @@ ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
retval = cfi_submit_wait(io); retval = cfi_submit_wait(io);
if (retval == 0) if (retval == 0)
memcpy((void *)addr, io, sizeof(*io)); memcpy(user_io, io, sizeof(*io));
ctl_free_io(io); ctl_free_io(io);
return (retval); return (retval);