hpet: Support 32-bit userspace
commit 4e60131d0d36af65ab9c9144f4f163fe97ae36e8 upstream. hpet_compat_ioctl and read file operations failed to handle parameters from 32-bit userspace and thus samples/timers/hpet_example.c fails as below. root@intel-x86-64:~# ./hpet_example-32.out poll /dev/hpet 1 2 -hpet: executing poll hpet_poll: HPET_IRQFREQ failed This patch fixes cmd and arg handling in hpet_compat_ioctl and adds compat handling for 32-bit userspace in hpet_read. hpet_example now shows that it works for both 64-bit and 32-bit. root@intel-x86-64:~# ./hpet_example-32.out poll /dev/hpet 1 2 -hpet: executing poll hpet_poll: info.hi_flags 0x0 hpet_poll: expired time = 0xf4298 hpet_poll: revents = 0x1 hpet_poll: data 0x1 hpet_poll: expired time = 0xf4235 hpet_poll: revents = 0x1 hpet_poll: data 0x1 root@intel-x86-64:~# ./hpet_example-64.out poll /dev/hpet 1 2 -hpet: executing poll hpet_poll: info.hi_flags 0x0 hpet_poll: expired time = 0xf42a1 hpet_poll: revents = 0x1 hpet_poll: data 0x1 hpet_poll: expired time = 0xf4232 hpet_poll: revents = 0x1 hpet_poll: data 0x1 Cc: stable@vger.kernel.org Signed-off-by: He Zhe <zhe.he@windriver.com> Fixes: 54066a57c584 ("hpet: kill BKL, add compat_ioctl") Reviewed-by: Arnd Bergmann <arnd@arndb.de> Link: https://lore.kernel.org/r/20240606123908.738733-1-zhe.he@windriver.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
30cad84fc2
commit
e0edce12c0
1 changed files with 29 additions and 5 deletions
|
@ -304,8 +304,13 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||||
if (!devp->hd_ireqfreq)
|
if (!devp->hd_ireqfreq)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
if (in_compat_syscall()) {
|
||||||
|
if (count < sizeof(compat_ulong_t))
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
if (count < sizeof(unsigned long))
|
if (count < sizeof(unsigned long))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
add_wait_queue(&devp->hd_waitqueue, &wait);
|
add_wait_queue(&devp->hd_waitqueue, &wait);
|
||||||
|
|
||||||
|
@ -329,9 +334,16 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||||
schedule();
|
schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in_compat_syscall()) {
|
||||||
|
retval = put_user(data, (compat_ulong_t __user *)buf);
|
||||||
|
if (!retval)
|
||||||
|
retval = sizeof(compat_ulong_t);
|
||||||
|
} else {
|
||||||
retval = put_user(data, (unsigned long __user *)buf);
|
retval = put_user(data, (unsigned long __user *)buf);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
retval = sizeof(unsigned long);
|
retval = sizeof(unsigned long);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&devp->hd_waitqueue, &wait);
|
remove_wait_queue(&devp->hd_waitqueue, &wait);
|
||||||
|
@ -686,12 +698,24 @@ struct compat_hpet_info {
|
||||||
unsigned short hi_timer;
|
unsigned short hi_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 32-bit types would lead to different command codes which should be
|
||||||
|
* translated into 64-bit ones before passed to hpet_ioctl_common
|
||||||
|
*/
|
||||||
|
#define COMPAT_HPET_INFO _IOR('h', 0x03, struct compat_hpet_info)
|
||||||
|
#define COMPAT_HPET_IRQFREQ _IOW('h', 0x6, compat_ulong_t)
|
||||||
|
|
||||||
static long
|
static long
|
||||||
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct hpet_info info;
|
struct hpet_info info;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (cmd == COMPAT_HPET_INFO)
|
||||||
|
cmd = HPET_INFO;
|
||||||
|
|
||||||
|
if (cmd == COMPAT_HPET_IRQFREQ)
|
||||||
|
cmd = HPET_IRQFREQ;
|
||||||
|
|
||||||
mutex_lock(&hpet_mutex);
|
mutex_lock(&hpet_mutex);
|
||||||
err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
|
err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
|
||||||
mutex_unlock(&hpet_mutex);
|
mutex_unlock(&hpet_mutex);
|
||||||
|
|
Loading…
Add table
Reference in a new issue