Messages in this thread | | | Date | Wed, 10 Feb 2016 15:03:56 -0500 | Subject | compat_ioctl question/problem | From | Soohoon pho <> |
| |
Hi,
following is the code in question.
+static int compat_hdio_ioctl(struct inode *inode, struct file *file, + struct gendisk *disk, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + unsigned long kval; + unsigned int __user *uvp; + int error; + + set_fs(KERNEL_DS); + error = blkdev_driver_ioctl(inode, file, disk, + cmd, (unsigned long)(&kval)); + set_fs(old_fs); + + if (error == 0) { + uvp = compat_ptr(arg); + if (put_user(kval, uvp)) + error = -EFAULT; + } + return error; +}
kval is local so it has random value. But one of syscall like HDIO_GET_32BIT/ATA_IOC_GET_IO32 only updates one byte so if kval has 0xaaaaaaaa and ioctl() updates one byte then it becomes 0xaaaaaa01. And put_user() writes 4bytes.
Because of that I’m having problem with 32bit hdparm.
void process_dev (char *devname) { static long parm, multcount; <-- parm is static so it’s zero ….. if (do_defaults || get_io32bit) { if (0 == ioctl(fd, HDIO_GET_32BIT, &parm)) {
so parm becomes 0xaaaaaa01 and reports wrong mode.
If hdparm is 64bit then 64bit syscall will update 1byte of parm so it becomes 0x1.
What would be a good fix if I can't use 64bit hdparm? - Modify hdparm to look at only 1byte - Initialize kval to zero - Copy parm to kval before blkdev_driver_ioctl() to be more accurately close to 64bit syscall.
Thanks, Soohoon.
| |