Loading block/compat_ioctl.c +0 −340 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ #include <linux/cdrom.h> #include <linux/compat.h> #include <linux/elevator.h> #include <linux/fd.h> #include <linux/hdreg.h> #include <linux/slab.h> #include <linux/syscalls.h> Loading Loading @@ -209,318 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) struct compat_floppy_drive_params { char cmos; compat_ulong_t max_dtr; compat_ulong_t hlt; compat_ulong_t hut; compat_ulong_t srt; compat_ulong_t spinup; compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; compat_int_t checkfreq; compat_int_t native_format; }; struct compat_floppy_drive_struct { signed char flags; compat_ulong_t spinup_date; compat_ulong_t select_date; compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; compat_int_t generation; compat_int_t keep_data; compat_int_t fd_ref; compat_int_t fd_device; compat_int_t last_checked; compat_caddr_t dmabuf; compat_int_t bufblocks; }; struct compat_floppy_fdc_state { compat_int_t spec1; compat_int_t spec2; compat_int_t dtr; unsigned char version; unsigned char dor; compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; unsigned int perp_mode:2; unsigned int has_fifo:1; unsigned int driver_version; unsigned char track[4]; }; struct compat_floppy_write_errors { unsigned int write_errors; compat_ulong_t first_error_sector; compat_int_t first_error_generation; compat_ulong_t last_error_sector; compat_int_t last_error_generation; compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) static struct { unsigned int cmd32; unsigned int cmd; } fd_ioctl_trans_table[] = { { FDSETPRM32, FDSETPRM }, { FDDEFPRM32, FDDEFPRM }, { FDGETPRM32, FDGETPRM }, { FDSETDRVPRM32, FDSETDRVPRM }, { FDGETDRVPRM32, FDGETDRVPRM }, { FDGETDRVSTAT32, FDGETDRVSTAT }, { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, { FDGETFDCSTAT32, FDGETFDCSTAT }, { FDWERRORGET32, FDWERRORGET } }; #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); void *karg = NULL; unsigned int kcmd = 0; int i, err; for (i = 0; i < NR_FD_IOCTL_TRANS; i++) if (cmd == fd_ioctl_trans_table[i].cmd32) { kcmd = fd_ioctl_trans_table[i].cmd; break; } if (!kcmd) return -EINVAL; switch (cmd) { case FDSETPRM32: case FDDEFPRM32: case FDGETPRM32: { compat_uptr_t name; struct compat_floppy_struct __user *uf; struct floppy_struct *f; uf = compat_ptr(arg); f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); if (!karg) return -ENOMEM; if (cmd == FDGETPRM32) break; err = __get_user(f->size, &uf->size); err |= __get_user(f->sect, &uf->sect); err |= __get_user(f->head, &uf->head); err |= __get_user(f->track, &uf->track); err |= __get_user(f->stretch, &uf->stretch); err |= __get_user(f->gap, &uf->gap); err |= __get_user(f->rate, &uf->rate); err |= __get_user(f->spec1, &uf->spec1); err |= __get_user(f->fmt_gap, &uf->fmt_gap); err |= __get_user(name, &uf->name); f->name = compat_ptr(name); if (err) { err = -EFAULT; goto out; } break; } case FDSETDRVPRM32: case FDGETDRVPRM32: { struct compat_floppy_drive_params __user *uf; struct floppy_drive_params *f; uf = compat_ptr(arg); f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); if (!karg) return -ENOMEM; if (cmd == FDGETDRVPRM32) break; err = __get_user(f->cmos, &uf->cmos); err |= __get_user(f->max_dtr, &uf->max_dtr); err |= __get_user(f->hlt, &uf->hlt); err |= __get_user(f->hut, &uf->hut); err |= __get_user(f->srt, &uf->srt); err |= __get_user(f->spinup, &uf->spinup); err |= __get_user(f->spindown, &uf->spindown); err |= __get_user(f->spindown_offset, &uf->spindown_offset); err |= __get_user(f->select_delay, &uf->select_delay); err |= __get_user(f->rps, &uf->rps); err |= __get_user(f->tracks, &uf->tracks); err |= __get_user(f->timeout, &uf->timeout); err |= __get_user(f->interleave_sect, &uf->interleave_sect); err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); err |= __get_user(f->flags, &uf->flags); err |= __get_user(f->read_track, &uf->read_track); err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); err |= __get_user(f->checkfreq, &uf->checkfreq); err |= __get_user(f->native_format, &uf->native_format); if (err) { err = -EFAULT; goto out; } break; } case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); if (!karg) return -ENOMEM; break; case FDGETFDCSTAT32: karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); if (!karg) return -ENOMEM; break; case FDWERRORGET32: karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); if (!karg) return -ENOMEM; break; default: return -EINVAL; } set_fs(KERNEL_DS); err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); set_fs(old_fs); if (err) goto out; switch (cmd) { case FDGETPRM32: { struct floppy_struct *f = karg; struct compat_floppy_struct __user *uf = compat_ptr(arg); err = __put_user(f->size, &uf->size); err |= __put_user(f->sect, &uf->sect); err |= __put_user(f->head, &uf->head); err |= __put_user(f->track, &uf->track); err |= __put_user(f->stretch, &uf->stretch); err |= __put_user(f->gap, &uf->gap); err |= __put_user(f->rate, &uf->rate); err |= __put_user(f->spec1, &uf->spec1); err |= __put_user(f->fmt_gap, &uf->fmt_gap); err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); break; } case FDGETDRVPRM32: { struct compat_floppy_drive_params __user *uf; struct floppy_drive_params *f = karg; uf = compat_ptr(arg); err = __put_user(f->cmos, &uf->cmos); err |= __put_user(f->max_dtr, &uf->max_dtr); err |= __put_user(f->hlt, &uf->hlt); err |= __put_user(f->hut, &uf->hut); err |= __put_user(f->srt, &uf->srt); err |= __put_user(f->spinup, &uf->spinup); err |= __put_user(f->spindown, &uf->spindown); err |= __put_user(f->spindown_offset, &uf->spindown_offset); err |= __put_user(f->select_delay, &uf->select_delay); err |= __put_user(f->rps, &uf->rps); err |= __put_user(f->tracks, &uf->tracks); err |= __put_user(f->timeout, &uf->timeout); err |= __put_user(f->interleave_sect, &uf->interleave_sect); err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); err |= __put_user(f->flags, &uf->flags); err |= __put_user(f->read_track, &uf->read_track); err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); err |= __put_user(f->checkfreq, &uf->checkfreq); err |= __put_user(f->native_format, &uf->native_format); break; } case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: { struct compat_floppy_drive_struct __user *uf; struct floppy_drive_struct *f = karg; uf = compat_ptr(arg); err = __put_user(f->flags, &uf->flags); err |= __put_user(f->spinup_date, &uf->spinup_date); err |= __put_user(f->select_date, &uf->select_date); err |= __put_user(f->first_read_date, &uf->first_read_date); err |= __put_user(f->probed_format, &uf->probed_format); err |= __put_user(f->track, &uf->track); err |= __put_user(f->maxblock, &uf->maxblock); err |= __put_user(f->maxtrack, &uf->maxtrack); err |= __put_user(f->generation, &uf->generation); err |= __put_user(f->keep_data, &uf->keep_data); err |= __put_user(f->fd_ref, &uf->fd_ref); err |= __put_user(f->fd_device, &uf->fd_device); err |= __put_user(f->last_checked, &uf->last_checked); err |= __put_user((u64)f->dmabuf, &uf->dmabuf); err |= __put_user((u64)f->bufblocks, &uf->bufblocks); break; } case FDGETFDCSTAT32: { struct compat_floppy_fdc_state __user *uf; struct floppy_fdc_state *f = karg; uf = compat_ptr(arg); err = __put_user(f->spec1, &uf->spec1); err |= __put_user(f->spec2, &uf->spec2); err |= __put_user(f->dtr, &uf->dtr); err |= __put_user(f->version, &uf->version); err |= __put_user(f->dor, &uf->dor); err |= __put_user(f->address, &uf->address); err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), (char *)&f->address + sizeof(f->address), sizeof(int)); err |= __put_user(f->driver_version, &uf->driver_version); err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); break; } case FDWERRORGET32: { struct compat_floppy_write_errors __user *uf; struct floppy_write_errors *f = karg; uf = compat_ptr(arg); err = __put_user(f->write_errors, &uf->write_errors); err |= __put_user(f->first_error_sector, &uf->first_error_sector); err |= __put_user(f->first_error_generation, &uf->first_error_generation); err |= __put_user(f->last_error_sector, &uf->last_error_sector); err |= __put_user(f->last_error_generation, &uf->last_error_generation); err |= __put_user(f->badness, &uf->badness); break; } default: break; } if (err) err = -EFAULT; out: kfree(karg); return err; } static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { Loading @@ -537,16 +224,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(bdev, mode, cmd, arg); case FDSETPRM32: case FDDEFPRM32: case FDGETPRM32: case FDSETDRVPRM32: case FDGETDRVPRM32: case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: case FDGETFDCSTAT32: case FDWERRORGET32: return compat_fd_ioctl(bdev, mode, cmd, arg); case CDROMREADAUDIO: return compat_cdrom_read_audio(bdev, mode, cmd, arg); case CDROM_SEND_PACKET: Loading @@ -566,23 +243,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_DRIVE_CMD: /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ case 0x330: /* 0x02 -- Floppy ioctls */ case FDMSGON: case FDMSGOFF: case FDSETEMSGTRESH: case FDFLUSH: case FDWERRORCLR: case FDSETMAXERRS: case FDGETMAXERRS: case FDGETDRVTYP: case FDEJECT: case FDCLRPRM: case FDFMTBEG: case FDFMTEND: case FDRESET: case FDTWADDLE: case FDFMTTRK: case FDRAWCMD: /* CDROM stuff */ case CDROMPAUSE: case CDROMRESUME: Loading drivers/block/floppy.c +328 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static int print_unex = 1; #include <linux/io.h> #include <linux/uaccess.h> #include <linux/async.h> #include <linux/compat.h> /* * PS/2 floppies have much slower step rates than regular floppies. Loading Loading @@ -3568,6 +3569,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, return ret; } #ifdef CONFIG_COMPAT struct compat_floppy_drive_params { char cmos; compat_ulong_t max_dtr; compat_ulong_t hlt; compat_ulong_t hut; compat_ulong_t srt; compat_ulong_t spinup; compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; compat_int_t checkfreq; compat_int_t native_format; }; struct compat_floppy_drive_struct { signed char flags; compat_ulong_t spinup_date; compat_ulong_t select_date; compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; compat_int_t generation; compat_int_t keep_data; compat_int_t fd_ref; compat_int_t fd_device; compat_int_t last_checked; compat_caddr_t dmabuf; compat_int_t bufblocks; }; struct compat_floppy_fdc_state { compat_int_t spec1; compat_int_t spec2; compat_int_t dtr; unsigned char version; unsigned char dor; compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; unsigned int perp_mode:2; unsigned int has_fifo:1; unsigned int driver_version; unsigned char track[4]; }; struct compat_floppy_write_errors { unsigned int write_errors; compat_ulong_t first_error_sector; compat_int_t first_error_generation; compat_ulong_t last_error_sector; compat_int_t last_error_generation; compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd, struct compat_floppy_struct __user *arg) { struct floppy_struct v; int drive, type; int err; BUILD_BUG_ON(offsetof(struct floppy_struct, name) != offsetof(struct compat_floppy_struct, name)); if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) return -EPERM; memset(&v, 0, sizeof(struct floppy_struct)); if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name))) return -EFAULT; mutex_lock(&floppy_mutex); drive = (long)bdev->bd_disk->private_data; type = ITYPE(UDRS->fd_device); err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM, &v, drive, type, bdev); mutex_unlock(&floppy_mutex); return err; } static int compat_get_prm(int drive, struct compat_floppy_struct __user *arg) { struct compat_floppy_struct v; struct floppy_struct *p; int err; memset(&v, 0, sizeof(v)); mutex_lock(&floppy_mutex); err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p); if (err) { mutex_unlock(&floppy_mutex); return err; } memcpy(&v, p, offsetof(struct floppy_struct, name)); mutex_unlock(&floppy_mutex); if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct))) return -EFAULT; return 0; } static int compat_setdrvprm(int drive, struct compat_floppy_drive_params __user *arg) { struct compat_floppy_drive_params v; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params))) return -EFAULT; mutex_lock(&floppy_mutex); UDP->cmos = v.cmos; UDP->max_dtr = v.max_dtr; UDP->hlt = v.hlt; UDP->hut = v.hut; UDP->srt = v.srt; UDP->spinup = v.spinup; UDP->spindown = v.spindown; UDP->spindown_offset = v.spindown_offset; UDP->select_delay = v.select_delay; UDP->rps = v.rps; UDP->tracks = v.tracks; UDP->timeout = v.timeout; UDP->interleave_sect = v.interleave_sect; UDP->max_errors = v.max_errors; UDP->flags = v.flags; UDP->read_track = v.read_track; memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect)); UDP->checkfreq = v.checkfreq; UDP->native_format = v.native_format; mutex_unlock(&floppy_mutex); return 0; } static int compat_getdrvprm(int drive, struct compat_floppy_drive_params __user *arg) { struct compat_floppy_drive_params v; memset(&v, 0, sizeof(struct compat_floppy_drive_params)); mutex_lock(&floppy_mutex); v.cmos = UDP->cmos; v.max_dtr = UDP->max_dtr; v.hlt = UDP->hlt; v.hut = UDP->hut; v.srt = UDP->srt; v.spinup = UDP->spinup; v.spindown = UDP->spindown; v.spindown_offset = UDP->spindown_offset; v.select_delay = UDP->select_delay; v.rps = UDP->rps; v.tracks = UDP->tracks; v.timeout = UDP->timeout; v.interleave_sect = UDP->interleave_sect; v.max_errors = UDP->max_errors; v.flags = UDP->flags; v.read_track = UDP->read_track; memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect)); v.checkfreq = UDP->checkfreq; v.native_format = UDP->native_format; mutex_unlock(&floppy_mutex); if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) return -EFAULT; return 0; } static int compat_getdrvstat(int drive, bool poll, struct compat_floppy_drive_struct __user *arg) { struct compat_floppy_drive_struct v; memset(&v, 0, sizeof(struct compat_floppy_drive_struct)); mutex_lock(&floppy_mutex); if (poll) { if (lock_fdc(drive)) goto Eintr; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) goto Eintr; process_fd_request(); } v.spinup_date = UDRS->spinup_date; v.select_date = UDRS->select_date; v.first_read_date = UDRS->first_read_date; v.probed_format = UDRS->probed_format; v.track = UDRS->track; v.maxblock = UDRS->maxblock; v.maxtrack = UDRS->maxtrack; v.generation = UDRS->generation; v.keep_data = UDRS->keep_data; v.fd_ref = UDRS->fd_ref; v.fd_device = UDRS->fd_device; v.last_checked = UDRS->last_checked; v.dmabuf = (uintptr_t)UDRS->dmabuf; v.bufblocks = UDRS->bufblocks; mutex_unlock(&floppy_mutex); if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) return -EFAULT; return 0; Eintr: mutex_unlock(&floppy_mutex); return -EINTR; } static int compat_getfdcstat(int drive, struct compat_floppy_fdc_state __user *arg) { struct compat_floppy_fdc_state v32; struct floppy_fdc_state v; mutex_lock(&floppy_mutex); v = *UFDCS; mutex_unlock(&floppy_mutex); memset(&v32, 0, sizeof(struct compat_floppy_fdc_state)); v32.spec1 = v.spec1; v32.spec2 = v.spec2; v32.dtr = v.dtr; v32.version = v.version; v32.dor = v.dor; v32.address = v.address; v32.rawcmd = v.rawcmd; v32.reset = v.reset; v32.need_configure = v.need_configure; v32.perp_mode = v.perp_mode; v32.has_fifo = v.has_fifo; v32.driver_version = v.driver_version; memcpy(v32.track, v.track, 4); if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state))) return -EFAULT; return 0; } static int compat_werrorget(int drive, struct compat_floppy_write_errors __user *arg) { struct compat_floppy_write_errors v32; struct floppy_write_errors v; memset(&v32, 0, sizeof(struct compat_floppy_write_errors)); mutex_lock(&floppy_mutex); v = *UDRWE; mutex_unlock(&floppy_mutex); v32.write_errors = v.write_errors; v32.first_error_sector = v.first_error_sector; v32.first_error_generation = v.first_error_generation; v32.last_error_sector = v.last_error_sector; v32.last_error_generation = v.last_error_generation; v32.badness = v.badness; if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors))) return -EFAULT; return 0; } static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; switch (cmd) { case FDMSGON: case FDMSGOFF: case FDSETEMSGTRESH: case FDFLUSH: case FDWERRORCLR: case FDEJECT: case FDCLRPRM: case FDFMTBEG: case FDRESET: case FDTWADDLE: return fd_ioctl(bdev, mode, cmd, param); case FDSETMAXERRS: case FDGETMAXERRS: case FDGETDRVTYP: case FDFMTEND: case FDFMTTRK: case FDRAWCMD: return fd_ioctl(bdev, mode, cmd, (unsigned long)compat_ptr(param)); case FDSETPRM32: case FDDEFPRM32: return compat_set_geometry(bdev, mode, cmd, compat_ptr(param)); case FDGETPRM32: return compat_get_prm(drive, compat_ptr(param)); case FDSETDRVPRM32: return compat_setdrvprm(drive, compat_ptr(param)); case FDGETDRVPRM32: return compat_getdrvprm(drive, compat_ptr(param)); case FDPOLLDRVSTAT32: return compat_getdrvstat(drive, true, compat_ptr(param)); case FDGETDRVSTAT32: return compat_getdrvstat(drive, false, compat_ptr(param)); case FDGETFDCSTAT32: return compat_getfdcstat(drive, compat_ptr(param)); case FDWERRORGET32: return compat_werrorget(drive, compat_ptr(param)); } return -EINVAL; } #endif static void __init config_types(void) { bool has_drive = false; Loading Loading @@ -3885,6 +4210,9 @@ static const struct block_device_operations floppy_fops = { .getgeo = fd_getgeo, .check_events = floppy_check_events, .revalidate_disk = floppy_revalidate, #ifdef CONFIG_COMPAT .compat_ioctl = fd_compat_ioctl, #endif }; /* Loading Loading
block/compat_ioctl.c +0 −340 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ #include <linux/cdrom.h> #include <linux/compat.h> #include <linux/elevator.h> #include <linux/fd.h> #include <linux/hdreg.h> #include <linux/slab.h> #include <linux/syscalls.h> Loading Loading @@ -209,318 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, #define BLKBSZSET_32 _IOW(0x12, 113, int) #define BLKGETSIZE64_32 _IOR(0x12, 114, int) struct compat_floppy_drive_params { char cmos; compat_ulong_t max_dtr; compat_ulong_t hlt; compat_ulong_t hut; compat_ulong_t srt; compat_ulong_t spinup; compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; compat_int_t checkfreq; compat_int_t native_format; }; struct compat_floppy_drive_struct { signed char flags; compat_ulong_t spinup_date; compat_ulong_t select_date; compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; compat_int_t generation; compat_int_t keep_data; compat_int_t fd_ref; compat_int_t fd_device; compat_int_t last_checked; compat_caddr_t dmabuf; compat_int_t bufblocks; }; struct compat_floppy_fdc_state { compat_int_t spec1; compat_int_t spec2; compat_int_t dtr; unsigned char version; unsigned char dor; compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; unsigned int perp_mode:2; unsigned int has_fifo:1; unsigned int driver_version; unsigned char track[4]; }; struct compat_floppy_write_errors { unsigned int write_errors; compat_ulong_t first_error_sector; compat_int_t first_error_generation; compat_ulong_t last_error_sector; compat_int_t last_error_generation; compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) static struct { unsigned int cmd32; unsigned int cmd; } fd_ioctl_trans_table[] = { { FDSETPRM32, FDSETPRM }, { FDDEFPRM32, FDDEFPRM }, { FDGETPRM32, FDGETPRM }, { FDSETDRVPRM32, FDSETDRVPRM }, { FDGETDRVPRM32, FDGETDRVPRM }, { FDGETDRVSTAT32, FDGETDRVSTAT }, { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, { FDGETFDCSTAT32, FDGETFDCSTAT }, { FDWERRORGET32, FDWERRORGET } }; #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); void *karg = NULL; unsigned int kcmd = 0; int i, err; for (i = 0; i < NR_FD_IOCTL_TRANS; i++) if (cmd == fd_ioctl_trans_table[i].cmd32) { kcmd = fd_ioctl_trans_table[i].cmd; break; } if (!kcmd) return -EINVAL; switch (cmd) { case FDSETPRM32: case FDDEFPRM32: case FDGETPRM32: { compat_uptr_t name; struct compat_floppy_struct __user *uf; struct floppy_struct *f; uf = compat_ptr(arg); f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); if (!karg) return -ENOMEM; if (cmd == FDGETPRM32) break; err = __get_user(f->size, &uf->size); err |= __get_user(f->sect, &uf->sect); err |= __get_user(f->head, &uf->head); err |= __get_user(f->track, &uf->track); err |= __get_user(f->stretch, &uf->stretch); err |= __get_user(f->gap, &uf->gap); err |= __get_user(f->rate, &uf->rate); err |= __get_user(f->spec1, &uf->spec1); err |= __get_user(f->fmt_gap, &uf->fmt_gap); err |= __get_user(name, &uf->name); f->name = compat_ptr(name); if (err) { err = -EFAULT; goto out; } break; } case FDSETDRVPRM32: case FDGETDRVPRM32: { struct compat_floppy_drive_params __user *uf; struct floppy_drive_params *f; uf = compat_ptr(arg); f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); if (!karg) return -ENOMEM; if (cmd == FDGETDRVPRM32) break; err = __get_user(f->cmos, &uf->cmos); err |= __get_user(f->max_dtr, &uf->max_dtr); err |= __get_user(f->hlt, &uf->hlt); err |= __get_user(f->hut, &uf->hut); err |= __get_user(f->srt, &uf->srt); err |= __get_user(f->spinup, &uf->spinup); err |= __get_user(f->spindown, &uf->spindown); err |= __get_user(f->spindown_offset, &uf->spindown_offset); err |= __get_user(f->select_delay, &uf->select_delay); err |= __get_user(f->rps, &uf->rps); err |= __get_user(f->tracks, &uf->tracks); err |= __get_user(f->timeout, &uf->timeout); err |= __get_user(f->interleave_sect, &uf->interleave_sect); err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); err |= __get_user(f->flags, &uf->flags); err |= __get_user(f->read_track, &uf->read_track); err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); err |= __get_user(f->checkfreq, &uf->checkfreq); err |= __get_user(f->native_format, &uf->native_format); if (err) { err = -EFAULT; goto out; } break; } case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); if (!karg) return -ENOMEM; break; case FDGETFDCSTAT32: karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); if (!karg) return -ENOMEM; break; case FDWERRORGET32: karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); if (!karg) return -ENOMEM; break; default: return -EINVAL; } set_fs(KERNEL_DS); err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); set_fs(old_fs); if (err) goto out; switch (cmd) { case FDGETPRM32: { struct floppy_struct *f = karg; struct compat_floppy_struct __user *uf = compat_ptr(arg); err = __put_user(f->size, &uf->size); err |= __put_user(f->sect, &uf->sect); err |= __put_user(f->head, &uf->head); err |= __put_user(f->track, &uf->track); err |= __put_user(f->stretch, &uf->stretch); err |= __put_user(f->gap, &uf->gap); err |= __put_user(f->rate, &uf->rate); err |= __put_user(f->spec1, &uf->spec1); err |= __put_user(f->fmt_gap, &uf->fmt_gap); err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); break; } case FDGETDRVPRM32: { struct compat_floppy_drive_params __user *uf; struct floppy_drive_params *f = karg; uf = compat_ptr(arg); err = __put_user(f->cmos, &uf->cmos); err |= __put_user(f->max_dtr, &uf->max_dtr); err |= __put_user(f->hlt, &uf->hlt); err |= __put_user(f->hut, &uf->hut); err |= __put_user(f->srt, &uf->srt); err |= __put_user(f->spinup, &uf->spinup); err |= __put_user(f->spindown, &uf->spindown); err |= __put_user(f->spindown_offset, &uf->spindown_offset); err |= __put_user(f->select_delay, &uf->select_delay); err |= __put_user(f->rps, &uf->rps); err |= __put_user(f->tracks, &uf->tracks); err |= __put_user(f->timeout, &uf->timeout); err |= __put_user(f->interleave_sect, &uf->interleave_sect); err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); err |= __put_user(f->flags, &uf->flags); err |= __put_user(f->read_track, &uf->read_track); err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); err |= __put_user(f->checkfreq, &uf->checkfreq); err |= __put_user(f->native_format, &uf->native_format); break; } case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: { struct compat_floppy_drive_struct __user *uf; struct floppy_drive_struct *f = karg; uf = compat_ptr(arg); err = __put_user(f->flags, &uf->flags); err |= __put_user(f->spinup_date, &uf->spinup_date); err |= __put_user(f->select_date, &uf->select_date); err |= __put_user(f->first_read_date, &uf->first_read_date); err |= __put_user(f->probed_format, &uf->probed_format); err |= __put_user(f->track, &uf->track); err |= __put_user(f->maxblock, &uf->maxblock); err |= __put_user(f->maxtrack, &uf->maxtrack); err |= __put_user(f->generation, &uf->generation); err |= __put_user(f->keep_data, &uf->keep_data); err |= __put_user(f->fd_ref, &uf->fd_ref); err |= __put_user(f->fd_device, &uf->fd_device); err |= __put_user(f->last_checked, &uf->last_checked); err |= __put_user((u64)f->dmabuf, &uf->dmabuf); err |= __put_user((u64)f->bufblocks, &uf->bufblocks); break; } case FDGETFDCSTAT32: { struct compat_floppy_fdc_state __user *uf; struct floppy_fdc_state *f = karg; uf = compat_ptr(arg); err = __put_user(f->spec1, &uf->spec1); err |= __put_user(f->spec2, &uf->spec2); err |= __put_user(f->dtr, &uf->dtr); err |= __put_user(f->version, &uf->version); err |= __put_user(f->dor, &uf->dor); err |= __put_user(f->address, &uf->address); err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), (char *)&f->address + sizeof(f->address), sizeof(int)); err |= __put_user(f->driver_version, &uf->driver_version); err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); break; } case FDWERRORGET32: { struct compat_floppy_write_errors __user *uf; struct floppy_write_errors *f = karg; uf = compat_ptr(arg); err = __put_user(f->write_errors, &uf->write_errors); err |= __put_user(f->first_error_sector, &uf->first_error_sector); err |= __put_user(f->first_error_generation, &uf->first_error_generation); err |= __put_user(f->last_error_sector, &uf->last_error_sector); err |= __put_user(f->last_error_generation, &uf->last_error_generation); err |= __put_user(f->badness, &uf->badness); break; } default: break; } if (err) err = -EFAULT; out: kfree(karg); return err; } static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long arg) { Loading @@ -537,16 +224,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_GET_ADDRESS: case HDIO_GET_BUSSTATE: return compat_hdio_ioctl(bdev, mode, cmd, arg); case FDSETPRM32: case FDDEFPRM32: case FDGETPRM32: case FDSETDRVPRM32: case FDGETDRVPRM32: case FDGETDRVSTAT32: case FDPOLLDRVSTAT32: case FDGETFDCSTAT32: case FDWERRORGET32: return compat_fd_ioctl(bdev, mode, cmd, arg); case CDROMREADAUDIO: return compat_cdrom_read_audio(bdev, mode, cmd, arg); case CDROM_SEND_PACKET: Loading @@ -566,23 +243,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, case HDIO_DRIVE_CMD: /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ case 0x330: /* 0x02 -- Floppy ioctls */ case FDMSGON: case FDMSGOFF: case FDSETEMSGTRESH: case FDFLUSH: case FDWERRORCLR: case FDSETMAXERRS: case FDGETMAXERRS: case FDGETDRVTYP: case FDEJECT: case FDCLRPRM: case FDFMTBEG: case FDFMTEND: case FDRESET: case FDTWADDLE: case FDFMTTRK: case FDRAWCMD: /* CDROM stuff */ case CDROMPAUSE: case CDROMRESUME: Loading
drivers/block/floppy.c +328 −0 Original line number Diff line number Diff line Loading @@ -192,6 +192,7 @@ static int print_unex = 1; #include <linux/io.h> #include <linux/uaccess.h> #include <linux/async.h> #include <linux/compat.h> /* * PS/2 floppies have much slower step rates than regular floppies. Loading Loading @@ -3568,6 +3569,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, return ret; } #ifdef CONFIG_COMPAT struct compat_floppy_drive_params { char cmos; compat_ulong_t max_dtr; compat_ulong_t hlt; compat_ulong_t hut; compat_ulong_t srt; compat_ulong_t spinup; compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; compat_int_t checkfreq; compat_int_t native_format; }; struct compat_floppy_drive_struct { signed char flags; compat_ulong_t spinup_date; compat_ulong_t select_date; compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; compat_int_t generation; compat_int_t keep_data; compat_int_t fd_ref; compat_int_t fd_device; compat_int_t last_checked; compat_caddr_t dmabuf; compat_int_t bufblocks; }; struct compat_floppy_fdc_state { compat_int_t spec1; compat_int_t spec2; compat_int_t dtr; unsigned char version; unsigned char dor; compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; unsigned int perp_mode:2; unsigned int has_fifo:1; unsigned int driver_version; unsigned char track[4]; }; struct compat_floppy_write_errors { unsigned int write_errors; compat_ulong_t first_error_sector; compat_int_t first_error_generation; compat_ulong_t last_error_sector; compat_int_t last_error_generation; compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd, struct compat_floppy_struct __user *arg) { struct floppy_struct v; int drive, type; int err; BUILD_BUG_ON(offsetof(struct floppy_struct, name) != offsetof(struct compat_floppy_struct, name)); if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) return -EPERM; memset(&v, 0, sizeof(struct floppy_struct)); if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name))) return -EFAULT; mutex_lock(&floppy_mutex); drive = (long)bdev->bd_disk->private_data; type = ITYPE(UDRS->fd_device); err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM, &v, drive, type, bdev); mutex_unlock(&floppy_mutex); return err; } static int compat_get_prm(int drive, struct compat_floppy_struct __user *arg) { struct compat_floppy_struct v; struct floppy_struct *p; int err; memset(&v, 0, sizeof(v)); mutex_lock(&floppy_mutex); err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p); if (err) { mutex_unlock(&floppy_mutex); return err; } memcpy(&v, p, offsetof(struct floppy_struct, name)); mutex_unlock(&floppy_mutex); if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct))) return -EFAULT; return 0; } static int compat_setdrvprm(int drive, struct compat_floppy_drive_params __user *arg) { struct compat_floppy_drive_params v; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params))) return -EFAULT; mutex_lock(&floppy_mutex); UDP->cmos = v.cmos; UDP->max_dtr = v.max_dtr; UDP->hlt = v.hlt; UDP->hut = v.hut; UDP->srt = v.srt; UDP->spinup = v.spinup; UDP->spindown = v.spindown; UDP->spindown_offset = v.spindown_offset; UDP->select_delay = v.select_delay; UDP->rps = v.rps; UDP->tracks = v.tracks; UDP->timeout = v.timeout; UDP->interleave_sect = v.interleave_sect; UDP->max_errors = v.max_errors; UDP->flags = v.flags; UDP->read_track = v.read_track; memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect)); UDP->checkfreq = v.checkfreq; UDP->native_format = v.native_format; mutex_unlock(&floppy_mutex); return 0; } static int compat_getdrvprm(int drive, struct compat_floppy_drive_params __user *arg) { struct compat_floppy_drive_params v; memset(&v, 0, sizeof(struct compat_floppy_drive_params)); mutex_lock(&floppy_mutex); v.cmos = UDP->cmos; v.max_dtr = UDP->max_dtr; v.hlt = UDP->hlt; v.hut = UDP->hut; v.srt = UDP->srt; v.spinup = UDP->spinup; v.spindown = UDP->spindown; v.spindown_offset = UDP->spindown_offset; v.select_delay = UDP->select_delay; v.rps = UDP->rps; v.tracks = UDP->tracks; v.timeout = UDP->timeout; v.interleave_sect = UDP->interleave_sect; v.max_errors = UDP->max_errors; v.flags = UDP->flags; v.read_track = UDP->read_track; memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect)); v.checkfreq = UDP->checkfreq; v.native_format = UDP->native_format; mutex_unlock(&floppy_mutex); if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) return -EFAULT; return 0; } static int compat_getdrvstat(int drive, bool poll, struct compat_floppy_drive_struct __user *arg) { struct compat_floppy_drive_struct v; memset(&v, 0, sizeof(struct compat_floppy_drive_struct)); mutex_lock(&floppy_mutex); if (poll) { if (lock_fdc(drive)) goto Eintr; if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) goto Eintr; process_fd_request(); } v.spinup_date = UDRS->spinup_date; v.select_date = UDRS->select_date; v.first_read_date = UDRS->first_read_date; v.probed_format = UDRS->probed_format; v.track = UDRS->track; v.maxblock = UDRS->maxblock; v.maxtrack = UDRS->maxtrack; v.generation = UDRS->generation; v.keep_data = UDRS->keep_data; v.fd_ref = UDRS->fd_ref; v.fd_device = UDRS->fd_device; v.last_checked = UDRS->last_checked; v.dmabuf = (uintptr_t)UDRS->dmabuf; v.bufblocks = UDRS->bufblocks; mutex_unlock(&floppy_mutex); if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) return -EFAULT; return 0; Eintr: mutex_unlock(&floppy_mutex); return -EINTR; } static int compat_getfdcstat(int drive, struct compat_floppy_fdc_state __user *arg) { struct compat_floppy_fdc_state v32; struct floppy_fdc_state v; mutex_lock(&floppy_mutex); v = *UFDCS; mutex_unlock(&floppy_mutex); memset(&v32, 0, sizeof(struct compat_floppy_fdc_state)); v32.spec1 = v.spec1; v32.spec2 = v.spec2; v32.dtr = v.dtr; v32.version = v.version; v32.dor = v.dor; v32.address = v.address; v32.rawcmd = v.rawcmd; v32.reset = v.reset; v32.need_configure = v.need_configure; v32.perp_mode = v.perp_mode; v32.has_fifo = v.has_fifo; v32.driver_version = v.driver_version; memcpy(v32.track, v.track, 4); if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state))) return -EFAULT; return 0; } static int compat_werrorget(int drive, struct compat_floppy_write_errors __user *arg) { struct compat_floppy_write_errors v32; struct floppy_write_errors v; memset(&v32, 0, sizeof(struct compat_floppy_write_errors)); mutex_lock(&floppy_mutex); v = *UDRWE; mutex_unlock(&floppy_mutex); v32.write_errors = v.write_errors; v32.first_error_sector = v.first_error_sector; v32.first_error_generation = v.first_error_generation; v32.last_error_sector = v.last_error_sector; v32.last_error_generation = v.last_error_generation; v32.badness = v.badness; if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors))) return -EFAULT; return 0; } static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { int drive = (long)bdev->bd_disk->private_data; switch (cmd) { case FDMSGON: case FDMSGOFF: case FDSETEMSGTRESH: case FDFLUSH: case FDWERRORCLR: case FDEJECT: case FDCLRPRM: case FDFMTBEG: case FDRESET: case FDTWADDLE: return fd_ioctl(bdev, mode, cmd, param); case FDSETMAXERRS: case FDGETMAXERRS: case FDGETDRVTYP: case FDFMTEND: case FDFMTTRK: case FDRAWCMD: return fd_ioctl(bdev, mode, cmd, (unsigned long)compat_ptr(param)); case FDSETPRM32: case FDDEFPRM32: return compat_set_geometry(bdev, mode, cmd, compat_ptr(param)); case FDGETPRM32: return compat_get_prm(drive, compat_ptr(param)); case FDSETDRVPRM32: return compat_setdrvprm(drive, compat_ptr(param)); case FDGETDRVPRM32: return compat_getdrvprm(drive, compat_ptr(param)); case FDPOLLDRVSTAT32: return compat_getdrvstat(drive, true, compat_ptr(param)); case FDGETDRVSTAT32: return compat_getdrvstat(drive, false, compat_ptr(param)); case FDGETFDCSTAT32: return compat_getfdcstat(drive, compat_ptr(param)); case FDWERRORGET32: return compat_werrorget(drive, compat_ptr(param)); } return -EINVAL; } #endif static void __init config_types(void) { bool has_drive = false; Loading Loading @@ -3885,6 +4210,9 @@ static const struct block_device_operations floppy_fops = { .getgeo = fd_getgeo, .check_events = floppy_check_events, .revalidate_disk = floppy_revalidate, #ifdef CONFIG_COMPAT .compat_ioctl = fd_compat_ioctl, #endif }; /* Loading