libkrunfw/patches/0017-Enable-64-bit-processe...

125 lines
4.2 KiB
Diff

From cc1a30862f3cf046bf75f750e07e0601e5796238 Mon Sep 17 00:00:00 2001
From: Sergio Lopez <slp@redhat.com>
Date: Tue, 8 Oct 2024 11:24:25 +0200
Subject: [PATCH 17/21] Enable 64 bit processes to use compat input syscalls
The compat variant of input syscalls is only enabled for 32 bit
tasks, but in some cases, such as userspace emulation, it's useful to
enable that variant for 64 bit processes.
Here we introduce the PR_[GET|SET]_COMPAT_INPUT prctl to allow 64 bit
tasks to opt-in for compat input syscalls.
Signed-off-by: Sergio Lopez <slp@redhat.com>
---
drivers/input/input-compat.c | 6 +++---
drivers/input/input-compat.h | 2 +-
include/linux/sched.h | 5 +++++
include/uapi/linux/prctl.h | 5 +++++
kernel/sys.c | 15 +++++++++++++++
5 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/input/input-compat.c b/drivers/input/input-compat.c
index 2ccd3eedbd67..abb8cfb99d6c 100644
--- a/drivers/input/input-compat.c
+++ b/drivers/input/input-compat.c
@@ -14,7 +14,7 @@
int input_event_from_user(const char __user *buffer,
struct input_event *event)
{
- if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
+ if (current->compat_input || (in_compat_syscall() && !COMPAT_USE_64BIT_TIME)) {
struct input_event_compat compat_event;
if (copy_from_user(&compat_event, buffer,
@@ -38,7 +38,7 @@ int input_event_from_user(const char __user *buffer,
int input_event_to_user(char __user *buffer,
const struct input_event *event)
{
- if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
+ if (current->compat_input || (in_compat_syscall() && !COMPAT_USE_64BIT_TIME)) {
struct input_event_compat compat_event;
compat_event.sec = event->input_event_sec;
@@ -62,7 +62,7 @@ int input_event_to_user(char __user *buffer,
int input_ff_effect_from_user(const char __user *buffer, size_t size,
struct ff_effect *effect)
{
- if (in_compat_syscall()) {
+ if (current->compat_input || (in_compat_syscall() && !COMPAT_USE_64BIT_TIME)) {
struct ff_effect_compat *compat_effect;
if (size != sizeof(struct ff_effect_compat))
diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h
index 3b7bb12b023b..e78c0492ce0d 100644
--- a/drivers/input/input-compat.h
+++ b/drivers/input/input-compat.h
@@ -53,7 +53,7 @@ struct ff_effect_compat {
static inline size_t input_event_size(void)
{
- return (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) ?
+ return (current->compat_input || (in_compat_syscall() && !COMPAT_USE_64BIT_TIME)) ?
sizeof(struct input_event_compat) : sizeof(struct input_event);
}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0d1d70aded38..eb86e4778b27 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1599,6 +1599,11 @@ struct task_struct {
#ifdef CONFIG_USER_EVENTS
struct user_event_mm *user_event_mm;
#endif
+ /*
+ * Whether the task wants to use compat input syscalls even if it's
+ * a 64-bit process.
+ */
+ bool compat_input;
/*
* New fields for task_struct should be added above here, so that
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 36c278683cd6..c2027aa99409 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -333,4 +333,9 @@ struct prctl_mm_map {
# define PR_SET_MEM_MODEL_DEFAULT 0
# define PR_SET_MEM_MODEL_TSO 1
+#define PR_GET_COMPAT_INPUT 0x63494e50
+#define PR_SET_COMPAT_INPUT 0x43494e50
+# define PR_SET_COMPAT_INPUT_DISABLE 0
+# define PR_SET_COMPAT_INPUT_ENABLE 1
+
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 83da58930513..24dd021a1592 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2805,6 +2805,21 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
return -EINVAL;
error = arch_prctl_mem_model_set(me, arg2);
break;
+ case PR_GET_COMPAT_INPUT:
+ if (arg2 || arg3 || arg4 || arg5)
+ return -EINVAL;
+ error = current->compat_input;
+ break;
+ case PR_SET_COMPAT_INPUT:
+ if (arg3 || arg4 || arg5)
+ return -EINVAL;
+ if (arg2 == PR_SET_COMPAT_INPUT_DISABLE)
+ current->compat_input = false;
+ else if (arg2 == PR_SET_COMPAT_INPUT_ENABLE)
+ current->compat_input = true;
+ else
+ return -EINVAL;
+ break;
default:
error = -EINVAL;
break;
--
2.47.1