125 lines
4.2 KiB
Diff
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
|
|
|