Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2cb9446 authored by He Zhe's avatar He Zhe Committed by Greg Kroah-Hartman
Browse files

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: default avatarHe Zhe <zhe.he@windriver.com>
Fixes: 54066a57 ("hpet: kill BKL, add compat_ioctl")
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20240606123908.738733-1-zhe.he@windriver.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d8418fd0
Loading
Loading
Loading
Loading
+29 −5
Original line number Diff line number Diff line
@@ -307,8 +307,13 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
	if (!devp->hd_ireqfreq)
		return -EIO;

	if (in_compat_syscall()) {
		if (count < sizeof(compat_ulong_t))
			return -EINVAL;
	} else {
		if (count < sizeof(unsigned long))
			return -EINVAL;
	}

	add_wait_queue(&devp->hd_waitqueue, &wait);

@@ -332,9 +337,16 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
		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);
		if (!retval)
			retval = sizeof(unsigned long);
	}

out:
	__set_current_state(TASK_RUNNING);
	remove_wait_queue(&devp->hd_waitqueue, &wait);
@@ -689,12 +701,24 @@ struct compat_hpet_info {
	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
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct hpet_info info;
	int err;

	if (cmd == COMPAT_HPET_INFO)
		cmd = HPET_INFO;

	if (cmd == COMPAT_HPET_IRQFREQ)
		cmd = HPET_IRQFREQ;

	mutex_lock(&hpet_mutex);
	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
	mutex_unlock(&hpet_mutex);