diff options
author | sobomax <sobomax@FreeBSD.org> | 2005-01-30 08:12:37 +0000 |
---|---|---|
committer | sobomax <sobomax@FreeBSD.org> | 2005-01-30 08:12:37 +0000 |
commit | 69aa6843efc6c9eeb6337b4d4ea4111c5ccd9ea7 (patch) | |
tree | 60c80029e1db66c753066e1ca06309b6a56d0ce6 /sys/cam | |
parent | 357d55c30bf33ab6d5042b919803aac27999084a (diff) | |
download | FreeBSD-src-69aa6843efc6c9eeb6337b4d4ea4111c5ccd9ea7.zip FreeBSD-src-69aa6843efc6c9eeb6337b4d4ea4111c5ccd9ea7.tar.gz |
Boot away another stackgap (one of the lest ones in linuxlator/i386) by
providing special version of CDIOCREADSUBCHANNEL ioctl(), which assumes that
result has to be placed into kernel space not user space. In the long run
more generic solution has to be designed WRT emulating various ioctl()s
that operate on userspace buffers, but right now there is only one such
ioctl() is emulated, so that it makes little sense.
MFC after: 2 weeks
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/scsi/scsi_cd.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index 012e3a2..11a64a7 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -1909,7 +1909,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) struct cam_periph *periph; struct cd_softc *softc; - int error; + int error, nocopyout; periph = (struct cam_periph *)dp->d_drv1; if (periph == NULL) @@ -1940,6 +1940,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) } } + nocopyout = 0; switch (cmd) { case CDIOCPLAYTRACKS: @@ -2098,6 +2099,9 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) error = cdplay(periph, args->blk, args->len); } break; + case CDIOCREADSUBCHANNEL_SYSSPACE: + nocopyout = 1; + /* Fallthrough */ case CDIOCREADSUBCHANNEL: { struct ioc_read_subchannel *args @@ -2138,8 +2142,12 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) len = min(len, ((data->header.data_len[0] << 8) + data->header.data_len[1] + sizeof(struct cd_sub_channel_header))); - if (copyout(data, args->data, len) != 0) { - error = EFAULT; + if (nocopyout == 0) { + if (copyout(data, args->data, len) != 0) { + error = EFAULT; + } + } else { + bcopy(data, args->data, len); } free(data, M_TEMP); } |