Files
BPI-CM9-Linux/build/patch/kernel/archive/sm8550-6.18/9999-allow-aarch64-to-perform-32bit-syscalls.patch

122 lines
4.2 KiB
Diff

From 897560fd00e1add63a9973c31fc437b006855680 Mon Sep 17 00:00:00 2001
From: Sergio Lopez <[email protected]>
Date: Tue, 8 Oct 2024 11:24:25 +0200
Subject: [PATCH] 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 <[email protected]>
---
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 2ccd3eedbd6733..abb8cfb99d6cf9 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 3b7bb12b023bc6..e78c0492ce0d36 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 77f01ac385f7a5..01125573065ecd 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1535,6 +1535,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 961216093f11ab..86fca7d168cc66 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -311,4 +311,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 2db751ce25a260..1be74620b0b659 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2768,6 +2768,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;