Re: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

2016-06-12 Thread Yury Norov
Hi Bamvor,

Sorry, I missed this patch.

On Sat, Jun 04, 2016 at 07:34:32PM +0800, Zhangjian (Bamvor) wrote:
> Hi,
> 
> I found an issue of unwind with the following code. The correct backtrace
> should be:
> (gdb) where
> #0 0x004004d0 in my_sig (sig=11) at test_force3.c:16
> #1 
> #2 func2 (num=0) at test_force3.c:22
> #3 0x00400540 in func1 (num=1) at test_force3.c:28
> #4 0x00400574 in main (argc=1, argv=0xffd7bc04) at test_force3.c:33
> 
> Without my patch, the backtrace is:
> (gdb) where
> #0 0x00400490 in my_sig (sig=11) at test_force3.c:16
> #1 
> #2 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33
> 
> With my patch which fix the wrong frame pointer(setup_return calculate the 
> offset
> of fp through ilp32_sigframe instead of sigfreame), the backtrace is:
> (gdb) where
> #0 0x00400490 in my_sig (sig=11) at test_force3.c:16
> #1 
> #2 func1 () at test_force3.c:28
> #3 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33
> 
> I am not sure there is still some issue in kernel. But it seem that the gdb 
> of ilp32
> does not work correctly when unwind without framepointer.
> 
> The test code is:
> 
> From 7e364a765097f57aed2d73f94c1688c2e7343e79 Mon Sep 17 00:00:00 2001
> From: Bamvor Jian Zhang 
> Date: Sat, 4 Jun 2016 14:30:05 +0800
> Subject: [PATCH] arm64: ilp32: fix for wrong fp offset when calculate the
>  new fp
> 
> ILP32 define its own sigframe(ilp32_sigframe) because of the
> difference uc_context. setup_return do not use ilp32 specific
> sigframe to calculate the new offset of fp which lead to wrong
> fp in signal handler. At this circumstance, gdb backtrace will miss
> one item:
> (gdb) where
> 
> It should be:
> (gdb) where
> 
> The test code is as follows:
> 
> void my_sig(int sig)
> {
> printf("sig=%d\n", sig);
> *(int *)0 = 0x0;
> }
> 
> void func2(int num)
> {
> printf("%s: %d\n", __FUNCTION__, num);
> *(int *)0 = 0x0;
> func2(num-1);
> }
> 
> void func1(int num)
> {
> printf("%s\n", __FUNCTION__);
> func2(num - 1);
> }
> 
> int main(int argc, char **argv)
> {
> signal(11, my_sig);
> func1(argc);
> return 0;
> }
> 
> This patch fix this by passing the correct offset of fp to
> setup_return.
> Test pass on both ILP32 and LP64 in aarch64 EE.
> 
> Signed-off-by: Bamvor Jian Zhang 
> ---
>  arch/arm64/include/asm/signal_common.h | 3 ++-
>  arch/arm64/kernel/signal.c | 9 +
>  arch/arm64/kernel/signal_ilp32.c   | 4 ++--
>  3 files changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/signal_common.h 
> b/arch/arm64/include/asm/signal_common.h
> index de93c71..a5d7b63 100644
> --- a/arch/arm64/include/asm/signal_common.h
> +++ b/arch/arm64/include/asm/signal_common.h
> @@ -29,6 +29,7 @@ int setup_sigcontex(struct sigcontext __user *uc_mcontext,
>   struct pt_regs *regs);
>  int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf);
>  void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
> - void __user *frame, off_t sigframe_off, int usig);
> + void __user *frame, off_t sigframe_off, off_t fp_off,
> + int usig); 
> 
>  #endif /* __ASM_SIGNAL_COMMON_H */
> diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> index 038bebe..e66a6e9 100644
> --- a/arch/arm64/kernel/signal.c
> +++ b/arch/arm64/kernel/signal.c
> @@ -256,14 +256,14 @@ static struct rt_sigframe __user *get_sigframe(struct 
> ksignal *ksig,
>  }
> 
>  void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
> -  void __user *frame, off_t sigframe_off, int usig)
> +  void __user *frame, off_t sigframe_off, off_t fp_off,
> +  int usig)
>  {
>   __sigrestore_t sigtramp;
> 
>   regs->regs[0] = usig;
>   regs->sp = (unsigned long)frame;
> - regs->regs[29] = regs->sp + sigframe_off +
> - offsetof(struct sigframe, fp);
> + regs->regs[29] = regs->sp + sigframe_off + fp_off;

I think you are right here. The only nitpick is what for we send 2
offsets just to add one to another inside setup_return()?
We can do like this:

void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 void __user *frame, off_t fp_off, int usig)
{
__sigrestore_t sigtramp;

regs->regs[0] = usig;
regs->sp = (unsigned long)frame;
regs->regs[29] = regs->sp + fp_off;
[...]
}

Where fp_off calculation is done by caller. 

setup_return(regs, >ka, frame,
offsetof(struct rt_sigframe, sig) + offsetof(struct sigframe, 
fp),
usig);

For me it's more clear to understand what happens with this approach.
I don't think struct rt_sigframe will grow, but we can 

Re: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

2016-06-12 Thread Zhangjian (Bamvor)

Hi, Yury


Here is another print issue in this patch:

On 2016/5/24 8:04, Yury Norov wrote:

From: Andrew Pinski 

ILP32 uses AARCH32 compat structures and syscall handlers for signals.
But ILP32 struct rt_sigframe  and ucontext differs from both LP64 and
AARCH32. So some specific mechanism is needed to take care of it.


[...]

diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 000..841e8f8
--- /dev/null
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -0,0 +1,192 @@
+/*

[...]

+asmlinkage long ilp32_sys_rt_sigreturn(struct pt_regs *regs)
+{
+   struct ilp32_rt_sigframe __user *frame;
+
+   /* Always make any pending restarted system calls return -EINTR */
+   current->restart_block.fn = do_no_restart_syscall;
+
+   /*
+* Since we stacked the signal on a 128-bit boundary,
+* then 'sp' should be word aligned here.  If it's
+* not, then the user is trying to mess with us.
+*/
+   if (regs->sp & 15)
+   goto badframe;
+
+   frame = (struct ilp32_rt_sigframe __user *)regs->sp;
+
+   if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+   goto badframe;
+
+   if (restore_ilp32_sigframe(regs, >sig))
+   goto badframe;
+
+   if (compat_restore_altstack(>sig.uc.uc_stack))
+   goto badframe;
+
+   return regs->regs[0];
+
+badframe:
+   if (show_unhandled_signals)
+   pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx 
sp=%08llx\n",
+   current->comm, task_pid_nr(current), 
__func__,
+   regs->pc, regs->compat_sp);

It should be sp instead of compat_sp. The latter one is used by aarch32 EE.

Regards

Bamvor

+   force_sig(SIGSEGV, current);
+   return 0;
+}
+


--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

2016-06-12 Thread Zhangjian (Bamvor)

ping

On 2016/6/4 19:34, Zhangjian (Bamvor) wrote:

Hi,

I found an issue of unwind with the following code. The correct backtrace
should be:
(gdb) where
#0 0x004004d0 in my_sig (sig=11) at test_force3.c:16
#1 
#2 func2 (num=0) at test_force3.c:22
#3 0x00400540 in func1 (num=1) at test_force3.c:28
#4 0x00400574 in main (argc=1, argv=0xffd7bc04) at test_force3.c:33

Without my patch, the backtrace is:
(gdb) where
#0 0x00400490 in my_sig (sig=11) at test_force3.c:16
#1 
#2 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33

With my patch which fix the wrong frame pointer(setup_return calculate the 
offset
of fp through ilp32_sigframe instead of sigfreame), the backtrace is:
(gdb) where
#0 0x00400490 in my_sig (sig=11) at test_force3.c:16
#1 
#2 func1 () at test_force3.c:28
#3 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33

I am not sure there is still some issue in kernel. But it seem that the gdb of 
ilp32
does not work correctly when unwind without framepointer.

The test code is:

#include 
#include 
#include 
#include 

void my_sig(int sig)
{
 printf("sig=%d\n", sig);
 *(int *)0 = 0x0;
}


void func2()
{
 *(int *)0 = 0x0;
}

void func1()
{
 func2();
}

int main(int argc, char **argv)
{
 signal(11, my_sig);
 func1();
 return 0;
}


The full patch is as follows:

 From 7e364a765097f57aed2d73f94c1688c2e7343e79 Mon Sep 17 00:00:00 2001
From: Bamvor Jian Zhang 
Date: Sat, 4 Jun 2016 14:30:05 +0800
Subject: [PATCH] arm64: ilp32: fix for wrong fp offset when calculate the
  new fp

ILP32 define its own sigframe(ilp32_sigframe) because of the
difference uc_context. setup_return do not use ilp32 specific
sigframe to calculate the new offset of fp which lead to wrong
fp in signal handler. At this circumstance, gdb backtrace will miss
one item:
(gdb) where

It should be:
(gdb) where

The test code is as follows:

void my_sig(int sig)
{
 printf("sig=%d\n", sig);
 *(int *)0 = 0x0;
}

void func2(int num)
{
 printf("%s: %d\n", __FUNCTION__, num);
 *(int *)0 = 0x0;
 func2(num-1);
}

void func1(int num)
{
 printf("%s\n", __FUNCTION__);
 func2(num - 1);
}

int main(int argc, char **argv)
{
 signal(11, my_sig);
 func1(argc);
 return 0;
}

This patch fix this by passing the correct offset of fp to
setup_return.
Test pass on both ILP32 and LP64 in aarch64 EE.

Signed-off-by: Bamvor Jian Zhang 
---
  arch/arm64/include/asm/signal_common.h | 3 ++-
  arch/arm64/kernel/signal.c | 9 +
  arch/arm64/kernel/signal_ilp32.c   | 4 ++--
  3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/signal_common.h 
b/arch/arm64/include/asm/signal_common.h
index de93c71..a5d7b63 100644
--- a/arch/arm64/include/asm/signal_common.h
+++ b/arch/arm64/include/asm/signal_common.h
@@ -29,6 +29,7 @@ int setup_sigcontex(struct sigcontext __user *uc_mcontext,
  struct pt_regs *regs);
  int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf);
  void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-void __user *frame, off_t sigframe_off, int usig);
+void __user *frame, off_t sigframe_off, off_t fp_off,
+int usig);

  #endif /* __ASM_SIGNAL_COMMON_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 038bebe..e66a6e9 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -256,14 +256,14 @@ static struct rt_sigframe __user *get_sigframe(struct 
ksignal *ksig,
  }

  void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
- void __user *frame, off_t sigframe_off, int usig)
+ void __user *frame, off_t sigframe_off, off_t fp_off,
+ int usig)
  {
  __sigrestore_t sigtramp;

  regs->regs[0] = usig;
  regs->sp = (unsigned long)frame;
-regs->regs[29] = regs->sp + sigframe_off +
-offsetof(struct sigframe, fp);
+regs->regs[29] = regs->sp + sigframe_off + fp_off;
  regs->pc = (unsigned long)ka->sa.sa_handler;

  if (ka->sa.sa_flags & SA_RESTORER)
@@ -294,7 +294,8 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, 
sigset_t *set,
  err |= setup_sigframe(>sig, regs, set);
  if (err == 0) {
  setup_return(regs, >ka, frame,
-offsetof(struct rt_sigframe, sig), usig);
+offsetof(struct rt_sigframe, sig),
+offsetof(struct sigframe, fp), usig);
  if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
  err |= copy_siginfo_to_user(>info, >info);
  regs->regs[1] = (unsigned long)>info;
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
index a8ea73e..9030f14 100644
--- a/arch/arm64/kernel/signal_ilp32.c
+++ b/arch/arm64/kernel/signal_ilp32.c
@@ -147,7 +147,6 @@ static struct ilp32_rt_sigframe __user 

Re: [PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

2016-06-04 Thread Zhangjian (Bamvor)

Hi,

I found an issue of unwind with the following code. The correct backtrace
should be:
(gdb) where
#0 0x004004d0 in my_sig (sig=11) at test_force3.c:16
#1 
#2 func2 (num=0) at test_force3.c:22
#3 0x00400540 in func1 (num=1) at test_force3.c:28
#4 0x00400574 in main (argc=1, argv=0xffd7bc04) at test_force3.c:33

Without my patch, the backtrace is:
(gdb) where
#0 0x00400490 in my_sig (sig=11) at test_force3.c:16
#1 
#2 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33

With my patch which fix the wrong frame pointer(setup_return calculate the 
offset
of fp through ilp32_sigframe instead of sigfreame), the backtrace is:
(gdb) where
#0 0x00400490 in my_sig (sig=11) at test_force3.c:16
#1 
#2 func1 () at test_force3.c:28
#3 0x004004e4 in main (argc=1, argv=0xffe6f8f4) at test_force3.c:33

I am not sure there is still some issue in kernel. But it seem that the gdb of 
ilp32
does not work correctly when unwind without framepointer.

The test code is:

#include 
#include 
#include 
#include 

void my_sig(int sig)
{
printf("sig=%d\n", sig);
*(int *)0 = 0x0;
}


void func2()
{
*(int *)0 = 0x0;
}

void func1()
{
func2();
}

int main(int argc, char **argv)
{
signal(11, my_sig);
func1();
return 0;
}


The full patch is as follows:

From 7e364a765097f57aed2d73f94c1688c2e7343e79 Mon Sep 17 00:00:00 2001
From: Bamvor Jian Zhang 
Date: Sat, 4 Jun 2016 14:30:05 +0800
Subject: [PATCH] arm64: ilp32: fix for wrong fp offset when calculate the
 new fp

ILP32 define its own sigframe(ilp32_sigframe) because of the
difference uc_context. setup_return do not use ilp32 specific
sigframe to calculate the new offset of fp which lead to wrong
fp in signal handler. At this circumstance, gdb backtrace will miss
one item:
(gdb) where

It should be:
(gdb) where

The test code is as follows:

void my_sig(int sig)
{
printf("sig=%d\n", sig);
*(int *)0 = 0x0;
}

void func2(int num)
{
printf("%s: %d\n", __FUNCTION__, num);
*(int *)0 = 0x0;
func2(num-1);
}

void func1(int num)
{
printf("%s\n", __FUNCTION__);
func2(num - 1);
}

int main(int argc, char **argv)
{
signal(11, my_sig);
func1(argc);
return 0;
}

This patch fix this by passing the correct offset of fp to
setup_return.
Test pass on both ILP32 and LP64 in aarch64 EE.

Signed-off-by: Bamvor Jian Zhang 
---
 arch/arm64/include/asm/signal_common.h | 3 ++-
 arch/arm64/kernel/signal.c | 9 +
 arch/arm64/kernel/signal_ilp32.c   | 4 ++--
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/signal_common.h 
b/arch/arm64/include/asm/signal_common.h
index de93c71..a5d7b63 100644
--- a/arch/arm64/include/asm/signal_common.h
+++ b/arch/arm64/include/asm/signal_common.h
@@ -29,6 +29,7 @@ int setup_sigcontex(struct sigcontext __user *uc_mcontext,
struct pt_regs *regs);
 int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sf);
 void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-   void __user *frame, off_t sigframe_off, int usig);
+   void __user *frame, off_t sigframe_off, off_t fp_off,
+   int usig);

 #endif /* __ASM_SIGNAL_COMMON_H */
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 038bebe..e66a6e9 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -256,14 +256,14 @@ static struct rt_sigframe __user *get_sigframe(struct 
ksignal *ksig,
 }

 void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
-void __user *frame, off_t sigframe_off, int usig)
+void __user *frame, off_t sigframe_off, off_t fp_off,
+int usig)
 {
__sigrestore_t sigtramp;

regs->regs[0] = usig;
regs->sp = (unsigned long)frame;
-   regs->regs[29] = regs->sp + sigframe_off +
-   offsetof(struct sigframe, fp);
+   regs->regs[29] = regs->sp + sigframe_off + fp_off;
regs->pc = (unsigned long)ka->sa.sa_handler;

if (ka->sa.sa_flags & SA_RESTORER)
@@ -294,7 +294,8 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, 
sigset_t *set,
err |= setup_sigframe(>sig, regs, set);
if (err == 0) {
setup_return(regs, >ka, frame,
-   offsetof(struct rt_sigframe, sig), usig);
+   offsetof(struct rt_sigframe, sig),
+   offsetof(struct sigframe, fp), usig);
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(>info, >info);
regs->regs[1] = (unsigned long)>info;
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
index a8ea73e..9030f14 100644
--- a/arch/arm64/kernel/signal_ilp32.c
+++ 

[PATCH 21/23] arm64: ilp32: introduce ilp32-specific handlers for sigframe and ucontext

2016-05-23 Thread Yury Norov
From: Andrew Pinski 

ILP32 uses AARCH32 compat structures and syscall handlers for signals.
But ILP32 struct rt_sigframe  and ucontext differs from both LP64 and
AARCH32. So some specific mechanism is needed to take care of it.

Signed-off-by: Andrew Pinski 
Signed-off-by: Yury Norov 
---
 arch/arm64/include/asm/signal_ilp32.h |  34 ++
 arch/arm64/kernel/Makefile|   3 +-
 arch/arm64/kernel/entry_ilp32.S   |  23 
 arch/arm64/kernel/signal.c|   3 +
 arch/arm64/kernel/signal_ilp32.c  | 192 ++
 arch/arm64/kernel/sys_ilp32.c |   3 +
 6 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/signal_ilp32.h
 create mode 100644 arch/arm64/kernel/entry_ilp32.S
 create mode 100644 arch/arm64/kernel/signal_ilp32.c

diff --git a/arch/arm64/include/asm/signal_ilp32.h 
b/arch/arm64/include/asm/signal_ilp32.h
new file mode 100644
index 000..30eff23
--- /dev/null
+++ b/arch/arm64/include/asm/signal_ilp32.h
@@ -0,0 +1,34 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+#ifndef __ASM_SIGNAL_ILP32_H
+#define __ASM_SIGNAL_ILP32_H
+
+#ifdef CONFIG_ARM64_ILP32
+
+#include 
+
+int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
+ struct pt_regs *regs);
+
+#else
+
+static inline int ilp32_setup_rt_frame(int usig, struct ksignal *ksig, 
sigset_t *set,
+ struct pt_regs *regs)
+{
+   return -ENOSYS;
+}
+
+#endif /* CONFIG_ARM64_ILP32 */
+
+#endif /* __ASM_SIGNAL_ILP32_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 3ed55eb..09e4373 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -28,7 +28,8 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
 arm64-obj-$(CONFIG_AARCH32_EL0)+= sys32.o kuser32.o signal32.o 
\
   sys_compat.o entry32.o   
\
   ../../arm/kernel/opcodes.o 
binfmt_elf32.o
-arm64-obj-$(CONFIG_ARM64_ILP32)+= binfmt_ilp32.o sys_ilp32.o
+arm64-obj-$(CONFIG_ARM64_ILP32)+= binfmt_ilp32.o sys_ilp32.o   
\
+  signal_ilp32.o entry_ilp32.o
 arm64-obj-$(CONFIG_COMPAT) += signal32_common.o
 arm64-obj-$(CONFIG_FUNCTION_TRACER)+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)+= arm64ksyms.o module.o
diff --git a/arch/arm64/kernel/entry_ilp32.S b/arch/arm64/kernel/entry_ilp32.S
new file mode 100644
index 000..5063172
--- /dev/null
+++ b/arch/arm64/kernel/entry_ilp32.S
@@ -0,0 +1,23 @@
+/*
+ * ILP32 system call wrappers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#include 
+
+ENTRY(ilp32_sys_rt_sigreturn_wrapper)
+   mov x0, sp
+   b   ilp32_sys_rt_sigreturn
+ENDPROC(ilp32_sys_rt_sigreturn_wrapper)
+
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index f9fbf8a..45bcd96 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct sigframe {
struct ucontext uc;
@@ -323,6 +324,8 @@ static void handle_signal(struct ksignal *ksig, struct 
pt_regs *regs)
ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
else
ret = compat_setup_frame(usig, ksig, oldset, regs);
+   } else if (is_ilp32_compat_task()) {
+   ret = ilp32_setup_rt_frame(usig, ksig, oldset, regs);
} else {
ret = setup_rt_frame(usig, ksig, oldset, regs);
}
diff --git a/arch/arm64/kernel/signal_ilp32.c b/arch/arm64/kernel/signal_ilp32.c
new file mode 100644
index 000..841e8f8
--- /dev/null
+++