mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
Remove the CDIOCREADSUBCHANNEL_SYSSPACE ioctl.
This was added for emulation of Linux's CDROMSUBCHNL, but allows users with read access to a cd(4) device to overwrite kernel memory provided that the driver detects some media present. Reimplement CDROMSUBCHNL by bouncing the data from CDIOCREADSUBCHANNEL through the linux_cdrom_subchnl structure passed from userspace. admbugs: 768 Reported by: Alex Fortune Security: CVE-2019-5602 Security: FreeBSD-SA-19:11.cd_ioctl
This commit is contained in:
parent
ce5ec2c559
commit
fc795c25d4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=349627
@ -1314,7 +1314,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
|
||||
|
||||
struct cam_periph *periph;
|
||||
struct cd_softc *softc;
|
||||
int nocopyout, error = 0;
|
||||
int error = 0;
|
||||
|
||||
periph = (struct cam_periph *)dp->d_drv1;
|
||||
cam_periph_lock(periph);
|
||||
@ -1356,7 +1356,6 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
|
||||
*/
|
||||
cam_periph_unlock(periph);
|
||||
|
||||
nocopyout = 0;
|
||||
switch (cmd) {
|
||||
|
||||
case CDIOCPLAYTRACKS:
|
||||
@ -1532,9 +1531,6 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
|
||||
cam_periph_unlock(periph);
|
||||
}
|
||||
break;
|
||||
case CDIOCREADSUBCHANNEL_SYSSPACE:
|
||||
nocopyout = 1;
|
||||
/* Fallthrough */
|
||||
case CDIOCREADSUBCHANNEL:
|
||||
{
|
||||
struct ioc_read_subchannel *args
|
||||
@ -1579,13 +1575,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
|
||||
data->header.data_len[1] +
|
||||
sizeof(struct cd_sub_channel_header)));
|
||||
cam_periph_unlock(periph);
|
||||
if (nocopyout == 0) {
|
||||
if (copyout(data, args->data, len) != 0) {
|
||||
error = EFAULT;
|
||||
}
|
||||
} else {
|
||||
bcopy(data, args->data, len);
|
||||
}
|
||||
error = copyout(data, args->data, len);
|
||||
free(data, M_SCSICD);
|
||||
}
|
||||
break;
|
||||
|
@ -1489,16 +1489,26 @@ linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
|
||||
struct ioc_read_subchannel bsdsc;
|
||||
struct cd_sub_channel_info bsdinfo;
|
||||
|
||||
error = copyin((void *)args->arg, &sc, sizeof(sc));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Invoke the native ioctl and bounce the returned data through
|
||||
* the userspace buffer. This works because the Linux structure
|
||||
* is the same size as our structures for the subchannel header
|
||||
* and position data.
|
||||
*/
|
||||
bsdsc.address_format = CD_LBA_FORMAT;
|
||||
bsdsc.data_format = CD_CURRENT_POSITION;
|
||||
bsdsc.track = 0;
|
||||
bsdsc.data_len = sizeof(bsdinfo);
|
||||
bsdsc.data = &bsdinfo;
|
||||
error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE,
|
||||
(caddr_t)&bsdsc, td->td_ucred, td);
|
||||
bsdsc.data_len = sizeof(sc);
|
||||
bsdsc.data = (void *)args->arg;
|
||||
error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc,
|
||||
td->td_ucred, td);
|
||||
if (error)
|
||||
break;
|
||||
error = copyin((void *)args->arg, &sc, sizeof(sc));
|
||||
error = copyin((void *)args->arg, &bsdinfo, sizeof(bsdinfo));
|
||||
if (error)
|
||||
break;
|
||||
sc.cdsc_audiostatus = bsdinfo.header.audio_status;
|
||||
|
@ -274,11 +274,4 @@ struct ioc_capability { /*<2>*/
|
||||
|
||||
#define CDIOCCAPABILITY _IOR('c',30,struct ioc_capability) /*<2>*/
|
||||
|
||||
/*
|
||||
* Special version of CDIOCREADSUBCHANNEL which assumes that
|
||||
* ioc_read_subchannel->data points to the kernel memory. For
|
||||
* use in compatibility layers.
|
||||
*/
|
||||
#define CDIOCREADSUBCHANNEL_SYSSPACE _IOWR('c', 31, struct ioc_read_subchannel)
|
||||
|
||||
#endif /* !_SYS_CDIO_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user