This is still RFC because we have no glibc yet, that correspnds new ABI
introduced here. And so we cannot run tests. LP64 and AARCH32 tests show
no regression though.
v3: https://lkml.org/lkml/2014/9/3/704
v4: https://lkml.org/lkml/2015/4/13/691
v5: https://lkml.org/lkml/2015/9/29/911
v6:
- time_t, __kenel_off_t and other types turned to be 32-bit
for compatibility reasons (after v5 discussion);
- related changes applied to ILP32 syscall table and handlers;
- ILP32 VDSO code excluded. It's not mandatory, and caused questions
during review process. We definitely make sure we will follow up
with a VDSO later on because it is needed for performance reasons;
- fixed build issues with different combinations of AARCH32 / ILP32
enabling in config;
- ILP32 TLS bug fixed;
- entry32-common.S introduced to hold wrappers needed for both ILP32
and AARCH32_EL0;
- documentation updated according to latest changes;
- rebased to the current head;
- coding style re-checked;
- ILP32 syscall table turned around.
rfc3:
- all structures and system calls are just like AARCH32 ones now. with 2
exceptions: syscalls that take 64-bit parameter in 2 32-bit regosters
are replaced with LP64 version; struct rt_sigframe is constructed both
from LP64 and AARCH32 fields to be consistent with AARCH64 register set;
- documentation rewritten accordingly;
- common code for all 3 ABIs is moved to separated files for easy use,
new headers and objects are introduced, incl: is_compat.h, thread_bits.h,
signal_common.h, signal32_common.h.
- ILP32 VDSO code restored, Nathans comments are addressed;
- patch "arm64: ilp32: force IPC_64 in msgctl, shmctl, semctl" removed, as
Arnd suggested general solution for IPC_64 problem.
rfc4:
- sys_ilp32.c syscall list is fixed according to comments;
- binfmt_elf32.c and binfmt_ilp32.c are introduced to host the code handling
corresponding formats;
- statfs64, fstsatfs64 and mmap wrappers are removed;
- rebased on v4.4-rc8 + http://www.spinics.net/lists/kernel/msg2151759.html
Andrew Pinski (7):
arm64: ensure the kernel is compiled for LP64
arm64: rename COMPAT to AARCH32_EL0 in Kconfig
arm64: change some CONFIG_COMPAT over to use CONFIG_AARCH32_EL0
instead
arm64:uapi: set __BITS_PER_LONG correctly for ILP32 and LP64
arm64:ilp32: share HWCAP between LP64 and ILP32
arm64:ilp32: add sys_ilp32.c and a separate table (in entry.S) to use
it
arm64:ilp32: add ARM64_ILP32 to Kconfig
Bamvor Jian Zhang (1):
arm64: compat: fix wrong dependency
Philipp Tomsich (2):
arm64:ilp32: add vdso-ilp32 and use for signal return
arm64:ilp32: change COMPAT_ELF_PLATFORM to report a a subplatform for
ILP32
Yury Norov (11):
arm64: ilp32: add documentation on the ILP32 ABI for ARM64
thread: move thread bits accessors to separated file
arm64: introduce is_a32_task and is_a32_thread (for AArch32 compat)
arm64: ilp32: add is_ilp32_compat_{task,thread} and TIF_32BIT_AARCH64
arm64: introduce binfmt_elf32
arm64: ilp32: introduce binfmt_ilp32.c
arm64: ptrace: handle ptrace_request differently for aarch32 and ilp32
arm64: signal: wrap struct ucontext, fp and lr with struct sigframe
arm64: signal: share lp64 signal routines to ilp32
arm64: signal32: move ilp32 and aarch32 common code to separated file
arm64: ilp32: introduce ilp32-specific handlers for sigframe
Documentation/arm64/ilp32.txt | 13 +++
arch/arm64/Kconfig | 16 +++-
arch/arm64/Makefile | 5 +
arch/arm64/include/asm/compat.h | 19 +---
arch/arm64/include/asm/elf.h | 30 ++----
arch/arm64/include/asm/fpsimd.h | 2 +-
arch/arm64/include/asm/hwcap.h | 12 ++-
arch/arm64/include/asm/is_compat.h | 82 +++++++++++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 11 ++-
arch/arm64/include/asm/ptrace.h | 2 +-
arch/arm64/include/asm/signal32.h | 6 +-
arch/arm64/include/asm/signal32_common.h | 28 ++++++
arch/arm64/include/asm/signal_common.h | 39 ++++++++
arch/arm64/include/asm/signal_ilp32.h | 36 ++++++++
arch/arm64/include/asm/thread_info.h | 3 +-
arch/arm64/include/asm/unistd.h | 11 ++-
arch/arm64/include/asm/vdso.h | 6 ++
arch/arm64/include/uapi/asm/bitsperlong.h | 9 +-
arch/arm64/kernel/Makefile | 12 ++-
arch/arm64/kernel/asm-offsets.c | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 25 +++++
arch/arm64/kernel/binfmt_ilp32.c | 21 +++++
arch/arm64/kernel/entry.S | 18 +++-
arch/arm64/kernel/entry_ilp32.S | 23 +++++
arch/arm64/kernel/head.S | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +-
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 +-
arch/arm64/kernel/ptrace.c | 31 +++++--
arch/arm64/kernel/signal.c | 47 +++++-----
arch/arm64/kernel/signal32.c | 85 -----------------
arch/arm64/kernel/signal32_common.c | 115 +++++++++++++++++++++++
arch/arm64/kernel/signal_ilp32.c | 128 ++++++++++++++++++++++++++
arch/arm64/kernel/sys_ilp32.c | 69 ++++++++++++++
arch/arm64/kernel/traps.c | 5 +-
arch/arm64/kernel/vdso-ilp32/.gitignore | 2 +
arch/arm64/kernel/vdso-ilp32/Makefile | 72 +++++++++++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S | 33 +++++++
arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S | 95 +++++++++++++++++++
arch/arm64/kernel/vdso.c | 65 ++++++++++---
include/linux/thread_bits.h | 55 +++++++++++
include/linux/thread_info.h | 44 +--------
43 files changed, 1054 insertions(+), 245 deletions(-)
create mode 100644 Documentation/arm64/ilp32.txt
create mode 100644 arch/arm64/include/asm/is_compat.h
create mode 100644 arch/arm64/include/asm/signal32_common.h
create mode 100644 arch/arm64/include/asm/signal_common.h
create mode 100644 arch/arm64/include/asm/signal_ilp32.h
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
create mode 100644 arch/arm64/kernel/binfmt_ilp32.c
create mode 100644 arch/arm64/kernel/entry_ilp32.S
create mode 100644 arch/arm64/kernel/signal32_common.c
create mode 100644 arch/arm64/kernel/signal_ilp32.c
create mode 100644 arch/arm64/kernel/sys_ilp32.c
create mode 100644 arch/arm64/kernel/vdso-ilp32/.gitignore
create mode 100644 arch/arm64/kernel/vdso-ilp32/Makefile
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.S
create mode 100644 arch/arm64/kernel/vdso-ilp32/vdso-ilp32.lds.S
create mode 100644 include/linux/thread_bits.h
--
2.5.0
@@ -0,0 +1,13 @@+ILP32 AARCH64 SYSCALL ABI+=========================++This document describes the ILP32 syscall ABI and where it differs+from the generic compat linux syscall interface.++Syscalls which normally would pass 64bit values as two arguments;+now pass the 64bit value as one argument.++struct rt_sigframe is redefined and contains struct compat_siginfo,+as compat syscalls expects, and struct sigframe, taken from lp64 to+handle AARCH64 register set.+
From: Andrew Pinski <redacted>
The kernel needs to be compiled as a LP64 binary for ARM64, even when
using a compiler that defaults to code-generation for the ILP32 ABI.
Consequently, we need to explicitly pass '-mabi=lp64' (supported on
gcc-4.9 and newer).
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/Makefile | 5 +++++
1 file changed, 5 insertions(+)
From: Andrew Pinski <redacted>
In this patchset ILP32 ABI support is added. Additionally to AARCH32,
which is binary-compatible with ARM, ILP32 is (mostly) ABI-compatible.
From now, AARCH32_EL0 (former COMPAT) config option means the support of
AARCH32 userspace, ARM64_ILP32 - support of ILP32 ABI (see next patches),
and COMPAT indicates that one of them, or both, is enabled.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/Kconfig | 4 ++++
1 file changed, 4 insertions(+)
@@ -762,6 +762,10 @@ menu "Userspace binary formats"source"fs/Kconfig.binfmt"configCOMPAT+def_booly+depends onAARCH32_EL0++configAARCH32_EL0bool"Kernel support for 32-bit EL0"depends onARM64_4K_PAGES||EXPERTselectCOMPAT_BINFMT_ELF
From: Bamvor Jian Zhang <redacted>
With the patches of ILP32, COMPAT is not equivalent to AARCH32 in EL0.
This patch fix this by updating the dependency from COMPAT to
AARCH32_EL0 for ARMV8_DEPRECATED and ARM64_ERRATUM_845719.
Signed-off-by: Bamvor Jian Zhang <redacted>
Signed-off-by: Yury Norov <redacted>
---
arch/arm64/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Andrew Pinski <redacted>
Define __BITS_PER_LONG depending on the ABI used (i.e. check whether
__ILP32__ or __LP64__ is defined). This is necessary for glibc to
determine the appropriate type definitions for the system call interface.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/include/uapi/asm/bitsperlong.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
@@ -16,7 +16,14 @@#ifndef __ASM_BITSPERLONG_H#define __ASM_BITSPERLONG_H-#define __BITS_PER_LONG 64+#if defined(__LP64__)+/* Assuming __LP64__ will be defined for native ELF64's and not for ILP32. */+# define __BITS_PER_LONG 64+#elif defined(__ILP32__)+# define __BITS_PER_LONG 32+#else+# error "Neither LP64 nor ILP32: unsupported ABI in asm/bitsperlong.h"+#endif#include<asm-generic/bitsperlong.h>
They may be accessed from low-level code, so isolating is a measure to
avoid circular dependencies in header files.
The exact reason for circular dependency is WARN_ON() macro added in
patch edd63a27 (set_restore_sigmask() is never called without SIGPENDING
(and never should be)).
Signed-off-by: Yury Norov <redacted>
---
include/linux/thread_bits.h | 55 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/thread_info.h | 44 +-----------------------------------
2 files changed, 56 insertions(+), 43 deletions(-)
create mode 100644 include/linux/thread_bits.h
Based on patch of Andrew Pinski.
This patch introduces is_a32_compat_task and is_a32_thread so it is
easier to say this is a a32 specific thread or a generic compat thread/task.
Corresponding functions are located in <asm/is_compat.h> to avoid mess in
headers.
Some files include both <linux/compat.h> and <asm/compat.h>,
and this is wrong because <linux/compat.h> has <asm/compat.h> already
included. It was fixed too.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/include/asm/compat.h | 19 ++----------
arch/arm64/include/asm/elf.h | 7 ++---
arch/arm64/include/asm/is_compat.h | 58 ++++++++++++++++++++++++++++++++++++
arch/arm64/include/asm/memory.h | 3 +-
arch/arm64/include/asm/processor.h | 5 ++--
arch/arm64/include/asm/thread_info.h | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 10 +++----
arch/arm64/kernel/perf_regs.c | 2 +-
arch/arm64/kernel/process.c | 5 ++--
arch/arm64/kernel/ptrace.c | 9 +++---
arch/arm64/kernel/signal.c | 4 +--
arch/arm64/kernel/traps.c | 3 +-
12 files changed, 84 insertions(+), 43 deletions(-)
create mode 100644 arch/arm64/include/asm/is_compat.h
@@ -175,7 +175,7 @@ static int is_compat_bp(struct perf_event *bp)*deprecatedbehaviourifweuseunalignedwatchpointsin*AArch64state.*/-returntsk&&is_compat_thread(task_thread_info(tsk));+returntsk&&is_a32_compat_thread(task_thread_info(tsk));}/**
@@ -435,7 +435,7 @@ static int arch_build_bp_info(struct perf_event *bp)*Watchpointscanbeoflength1,2,4or8bytes.*/if(info->ctrl.type==ARM_BREAKPOINT_EXECUTE){-if(is_compat_bp(bp)){+if(is_a32_compat_bp(bp)){if(info->ctrl.len!=ARM_BREAKPOINT_LEN_2&&info->ctrl.len!=ARM_BREAKPOINT_LEN_4)return-EINVAL;
@@ -492,7 +492,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)*AArch32tasksexpectsomesimplealignmentfixups,soemulate*thathere.*/-if(is_compat_bp(bp)){+if(is_a32_compat_bp(bp)){if(info->ctrl.len==ARM_BREAKPOINT_LEN_8)alignment_mask=0x7;else
@@ -679,7 +679,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,info=counter_arch_bp(wp);/* AArch32 watchpoints are either 4 or 8 bytes aligned. */-if(is_compat_task()){+if(is_a32_compat_task()){if(info->ctrl.len==ARM_BREAKPOINT_LEN_8)alignment_mask=0x7;else
@@ -262,7 +261,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,asm("mrs %0, tpidr_el0":"=r"(*task_user_tls(p)));if(stack_start){-if(is_compat_thread(task_thread_info(p)))+if(is_a32_compat_thread(task_thread_info(p)))childregs->compat_sp=stack_start;/* 16-byte aligned stack mandatory on AArch64 */elseif(stack_start&15)
ILP32 tasks are needed to be distinguished from lp64 and aarch32.
This patch adds helper functions is_ilp32_compat_{task,thread} and
thread flag TIF_32BIT_AARCH64 to address it. This is a preparation
for following patches in ilp32 patchset.
For consistency, SET_PERSONALITY are changed here accordingly.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/include/asm/elf.h | 13 +++++++++++--
arch/arm64/include/asm/is_compat.h | 28 +++++++++++++++++++++++++++-
arch/arm64/include/asm/thread_info.h | 1 +
3 files changed, 39 insertions(+), 3 deletions(-)
As we support more than one compat formats, it looks more reasonable
to not use fs/compat_binfmt.c. Custom binfmt_elf32.c allows to move aarch32
specific definitions there and make code more maintainable and readable.
Signed-off-by: Yury Norov <redacted>
---
arch/arm64/Kconfig | 1 -
arch/arm64/include/asm/elf.h | 18 ------------------
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/binfmt_elf32.c | 25 +++++++++++++++++++++++++
4 files changed, 26 insertions(+), 20 deletions(-)
create mode 100644 arch/arm64/kernel/binfmt_elf32.c
From: Andrew Pinski <redacted>
Add a separate syscall-table for ILP32, which dispatches either to native
LP64 system call implementation or to compat-syscalls, as appropriate.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Yury Norov <redacted>
---
arch/arm64/include/asm/unistd.h | 11 ++++++-
arch/arm64/kernel/Makefile | 2 +-
arch/arm64/kernel/entry.S | 12 +++++++-
arch/arm64/kernel/sys_ilp32.c | 66 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 88 insertions(+), 3 deletions(-)
create mode 100644 arch/arm64/kernel/sys_ilp32.c
@@ -666,9 +666,13 @@ ENDPROC(ret_from_fork)*/.align6el0_svc:-adrpstbl,sys_call_table//loadsyscalltablepointeruxtwscno,w8//syscallnumberinw8movsc_nr,#__NR_syscalls+#ifdef CONFIG_ARM64_ILP32+ldrx16,[tsk,#TI_FLAGS]+tbnzx16,#TIF_32BIT_AARCH64, el0_ilp32_svc // We are using ILP32+#endif+adrpstbl,sys_call_table//loadsyscalltablepointerel0_svc_naked://compatentrypointstpx0,scno,[sp,#S_ORIG_X0] // save the original x0 and syscall numberenable_dbg_and_irq
@@ -688,6 +692,12 @@ ni_sys:bret_fast_syscallENDPROC(el0_svc)+#ifdef CONFIG_ARM64_ILP32+el0_ilp32_svc:+adrpstbl,sys_call_ilp32_table//loadsyscalltablepointer+bel0_svc_naked+#endif+/**Thisisthereallyslowpath.We're going to be doing context*switches,andwaitingforourparenttorespond.
It helps to move common code for lp64 and ilp32 to separated header.
Signed-off-by: Yury Norov <redacted>
---
arch/arm64/kernel/signal.c | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)
After that, it will be possible to reuse it in ilp32.
Signed-off-by: Yury Norov <redacted>
---
arch/arm64/include/asm/signal_common.h | 39 ++++++++++++++++++++++++++++++++++
arch/arm64/kernel/signal.c | 17 ++++++---------
2 files changed, 45 insertions(+), 11 deletions(-)
create mode 100644 arch/arm64/include/asm/signal_common.h
@@ -125,91 +125,6 @@ static inline int get_sigset_t(sigset_t *set,return0;}-intcopy_siginfo_to_user32(compat_siginfo_t__user*to,constsiginfo_t*from)-{-interr;--if(!access_ok(VERIFY_WRITE,to,sizeof(*to)))-return-EFAULT;--/* If you change siginfo_t structure, please be sure-*thiscodeisfixedaccordingly.-*Itshouldnevercopyanypadcontainedinthestructure-*toavoidsecurityleaks,butmustcopythegeneric-*3intsplustherelevantunionmember.-*Thisroutinemustconvertsiginfofrom64bitto32bitaswell-*atthesametime.-*/-err=__put_user(from->si_signo,&to->si_signo);-err|=__put_user(from->si_errno,&to->si_errno);-err|=__put_user((short)from->si_code,&to->si_code);-if(from->si_code<0)-err|=__copy_to_user(&to->_sifields._pad,&from->_sifields._pad,-SI_PAD_SIZE);-elseswitch(from->si_code&__SI_MASK){-case__SI_KILL:-err|=__put_user(from->si_pid,&to->si_pid);-err|=__put_user(from->si_uid,&to->si_uid);-break;-case__SI_TIMER:-err|=__put_user(from->si_tid,&to->si_tid);-err|=__put_user(from->si_overrun,&to->si_overrun);-err|=__put_user(from->si_int,&to->si_int);-break;-case__SI_POLL:-err|=__put_user(from->si_band,&to->si_band);-err|=__put_user(from->si_fd,&to->si_fd);-break;-case__SI_FAULT:-err|=__put_user((compat_uptr_t)(unsignedlong)from->si_addr,-&to->si_addr);-#ifdef BUS_MCEERR_AO-/*-*Othercallersmightnotinitializethesi_lsbfield,-*socheckexplicitelyfortherightcodeshere.-*/-if(from->si_signo==SIGBUS&&-(from->si_code==BUS_MCEERR_AR||from->si_code==BUS_MCEERR_AO))-err|=__put_user(from->si_addr_lsb,&to->si_addr_lsb);-#endif-break;-case__SI_CHLD:-err|=__put_user(from->si_pid,&to->si_pid);-err|=__put_user(from->si_uid,&to->si_uid);-err|=__put_user(from->si_status,&to->si_status);-err|=__put_user(from->si_utime,&to->si_utime);-err|=__put_user(from->si_stime,&to->si_stime);-break;-case__SI_RT:/* This is not generated by the kernel as of now. */-case__SI_MESGQ:/* But this is */-err|=__put_user(from->si_pid,&to->si_pid);-err|=__put_user(from->si_uid,&to->si_uid);-err|=__put_user(from->si_int,&to->si_int);-break;-case__SI_SYS:-err|=__put_user((compat_uptr_t)(unsignedlong)-from->si_call_addr,&to->si_call_addr);-err|=__put_user(from->si_syscall,&to->si_syscall);-err|=__put_user(from->si_arch,&to->si_arch);-break;-default:/* this is just in case for now ... */-err|=__put_user(from->si_pid,&to->si_pid);-err|=__put_user(from->si_uid,&to->si_uid);-break;-}-returnerr;-}--intcopy_siginfo_from_user32(siginfo_t*to,compat_siginfo_t__user*from)-{-if(copy_from_user(to,from,__ARCH_SI_PREAMBLE_SIZE)||-copy_from_user(to->_sifields._pad,-from->_sifields._pad,SI_PAD_SIZE))-return-EFAULT;--return0;-}-/**VFPsave/restorecode.*
@@ -0,0 +1,115 @@+/*+*Basedonarch/arm/kernel/signal.c+*+*Copyright(C)1995-2009RussellKing+*Copyright(C)2012ARMLtd.+*ModifiedbyWillDeacon<will.deacon@arm.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/compat.h>+#include<linux/signal.h>+#include<linux/ratelimit.h>++#include<asm/esr.h>+#include<asm/fpsimd.h>+#include<asm/signal32_common.h>+#include<asm/uaccess.h>+#include<asm/unistd.h>++intcopy_siginfo_to_user32(compat_siginfo_t__user*to,constsiginfo_t*from)+{+interr;++if(!access_ok(VERIFY_WRITE,to,sizeof(*to)))+return-EFAULT;++/* If you change siginfo_t structure, please be sure+*thiscodeisfixedaccordingly.+*Itshouldnevercopyanypadcontainedinthestructure+*toavoidsecurityleaks,butmustcopythegeneric+*3intsplustherelevantunionmember.+*Thisroutinemustconvertsiginfofrom64bitto32bitaswell+*atthesametime.+*/+err=__put_user(from->si_signo,&to->si_signo);+err|=__put_user(from->si_errno,&to->si_errno);+err|=__put_user((short)from->si_code,&to->si_code);+if(from->si_code<0)+err|=__copy_to_user(&to->_sifields._pad,&from->_sifields._pad,+SI_PAD_SIZE);+elseswitch(from->si_code&__SI_MASK){+case__SI_KILL:+err|=__put_user(from->si_pid,&to->si_pid);+err|=__put_user(from->si_uid,&to->si_uid);+break;+case__SI_TIMER:+err|=__put_user(from->si_tid,&to->si_tid);+err|=__put_user(from->si_overrun,&to->si_overrun);+err|=__put_user(from->si_int,&to->si_int);+break;+case__SI_POLL:+err|=__put_user(from->si_band,&to->si_band);+err|=__put_user(from->si_fd,&to->si_fd);+break;+case__SI_FAULT:+err|=__put_user((compat_uptr_t)(unsignedlong)from->si_addr,+&to->si_addr);+#ifdef BUS_MCEERR_AO+/*+*Othercallersmightnotinitializethesi_lsbfield,+*socheckexplicitelyfortherightcodeshere.+*/+if(from->si_signo==SIGBUS&&+(from->si_code==BUS_MCEERR_AR||from->si_code==BUS_MCEERR_AO))+err|=__put_user(from->si_addr_lsb,&to->si_addr_lsb);+#endif+break;+case__SI_CHLD:+err|=__put_user(from->si_pid,&to->si_pid);+err|=__put_user(from->si_uid,&to->si_uid);+err|=__put_user(from->si_status,&to->si_status);+err|=__put_user(from->si_utime,&to->si_utime);+err|=__put_user(from->si_stime,&to->si_stime);+break;+case__SI_RT:/* This is not generated by the kernel as of now. */+case__SI_MESGQ:/* But this is */+err|=__put_user(from->si_pid,&to->si_pid);+err|=__put_user(from->si_uid,&to->si_uid);+err|=__put_user(from->si_int,&to->si_int);+break;+case__SI_SYS:+err|=__put_user((compat_uptr_t)(unsignedlong)+from->si_call_addr,&to->si_call_addr);+err|=__put_user(from->si_syscall,&to->si_syscall);+err|=__put_user(from->si_arch,&to->si_arch);+break;+default:/* this is just in case for now ... */+err|=__put_user(from->si_pid,&to->si_pid);+err|=__put_user(from->si_uid,&to->si_uid);+break;+}+returnerr;+}++intcopy_siginfo_from_user32(siginfo_t*to,compat_siginfo_t__user*from)+{+if(copy_from_user(to,from,__ARCH_SI_PREAMBLE_SIZE)||+copy_from_user(to->_sifields._pad,+from->_sifields._pad,SI_PAD_SIZE))+return-EFAULT;++return0;+}+
@@ -0,0 +1,128 @@+/*+*Basedonarch/arm/kernel/signal.c+*+*Copyright(C)1995-2009RussellKing+*Copyright(C)2012ARMLtd.+*Copyright(C)2016CaviumNetworks.+*YuryNorov<ynorov@caviumnetworks.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*+*Thisprogramisdistributedinthehopethatitwillbeuseful,+*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof+*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*+*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense+*alongwiththisprogram.Ifnot,see<http://www.gnu.org/licenses/>.+*/++#include<linux/compat.h>+#include<linux/signal.h>+#include<linux/syscalls.h>+#include<linux/ratelimit.h>++#include<asm/esr.h>+#include<asm/fpsimd.h>+#include<asm/signal32_common.h>+#include<asm/signal_common.h>+#include<asm/uaccess.h>+#include<asm/unistd.h>+#include<asm/ucontext.h>++structilp32_rt_sigframe{+structcompat_siginfoinfo;+structsigframesig;+};++asmlinkageintilp32_sys_rt_sigreturn(structpt_regs*regs)+{+structilp32_rt_sigframe__user*frame;++/* Always make any pending restarted system calls return -EINTR */+current->restart_block.fn=do_no_restart_syscall;++/*+*Sincewestackedthesignalona128-bitboundary,+*then'sp'shouldbewordalignedhere.Ifit's+*not,thentheuseristryingtomesswithus.+*/+if(regs->sp&15)+gotobadframe;++frame=(structilp32_rt_sigframe__user*)regs->sp;++if(!access_ok(VERIFY_READ,frame,sizeof(*frame)))+gotobadframe;++if(restore_sigframe(regs,&frame->sig))+gotobadframe;++if(restore_altstack(&frame->sig.uc.uc_stack))+gotobadframe;++returnregs->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);+force_sig(SIGSEGV,current);+return0;+}++staticstructilp32_rt_sigframe__user*ilp32_get_sigframe(structksignal*ksig,+structpt_regs*regs)+{+unsignedlongsp,sp_top;+structilp32_rt_sigframe__user*frame;++sp=sp_top=sigsp(regs->sp,ksig);++sp=(sp-sizeof(structilp32_rt_sigframe))&~15;+frame=(structilp32_rt_sigframe__user*)sp;++/*+*Checkthatwecanactuallywritetothesignalframe.+*/+if(!access_ok(VERIFY_WRITE,frame,sp_top-sp))+frame=NULL;++returnframe;+}++/*+*ILP32signalhandlingroutinescalledfromsignal.c+*/+intilp32_setup_rt_frame(intusig,structksignal*ksig,+sigset_t*set,structpt_regs*regs)+{+structilp32_rt_sigframe__user*frame;+interr=0;++frame=ilp32_get_sigframe(ksig,regs);++if(!frame)+return1;++__put_user_error(0,&frame->sig.uc.uc_flags,err);+__put_user_error(NULL,&frame->sig.uc.uc_link,err);++err|=__save_altstack(&frame->sig.uc.uc_stack,regs->sp);+err|=setup_sigframe(&frame->sig,regs,set);+if(err==0){+setup_return(regs,&ksig->ka,frame,+offsetof(structilp32_rt_sigframe,sig),usig);+if(ksig->ka.sa.sa_flags&SA_SIGINFO){+err|=copy_siginfo_to_user32(&frame->info,&ksig->info);+regs->regs[1]=(unsignedlong)&frame->info;+regs->regs[2]=(unsignedlong)&frame->sig.uc;+}+}++returnerr;+}+
@@ -53,3 +54,7 @@ extra-y += $(head-y) vmlinux.lds# vDSO - this must be built first to generate the symbol offsets$(call objectify,$(arm64-obj-y)):$(obj)/vdso/vdso-offsets.h$(obj)/vdso/vdso-offsets.h:$(obj)/vdso++# vDSO - this must be built first to generate the symbol offsets+$(call objectify,$(arm64-obj-y)):$(obj)/vdso-ilp32/vdso-ilp32-offsets.h+$(obj)/vdso-ilp32/vdso-ilp32-offsets.h:$(obj)/vdso-ilp32
@@ -0,0 +1,72 @@+#+# Building a vDSO image for AArch64.+#+# Author: Will Deacon <will.deacon@arm.com>+# Heavily based on the vDSO Makefiles for other archs.+#++obj-ilp32-vdso:=gettimeofday-ilp32.onote-ilp32.osigreturn-ilp32.o++# Build rules+targets:=$(obj-ilp32-vdso)vdso-ilp32.sovdso-ilp32.so.dbg+obj-ilp32-vdso:=$(addprefix$(obj)/,$(obj-ilp32-vdso))++ccflags-y:=-shared-fno-common-fno-builtin+ccflags-y+=-nostdlib-Wl,-soname=linux-ilp32-vdso.so.1\+$(callcc-ldoption,-Wl$(comma)--hash-style=sysv)++obj-y+=vdso-ilp32.o+extra-y+=vdso-ilp32.ldsvdso-ilp32-offsets.h+CPPFLAGS_vdso-ilp32.lds+=-P-C-U$(ARCH)-mabi=ilp32++# Force dependency (incbin is bad)+$(obj)/vdso-ilp32.o :$(obj)/vdso-ilp32.so++# Link rule for the .so file, .lds has to be first+$(obj)/vdso-ilp32.so.dbg:$(src)/vdso-ilp32.lds$(obj-ilp32-vdso)+$(callif_changed,vdso-ilp32ld)++# Strip rule for the .so file+$(obj)/%.so:OBJCOPYFLAGS := -S+$(obj)/%.so:$(obj)/%.so.dbgFORCE+$(callif_changed,objcopy)++# Generate VDSO offsets using helper script+gen-vdsosym:=$(srctree)/$(src)/../vdso/gen_vdso_offsets.sh+quiet_cmd_vdsosym=VDSOSYM$@+define cmd_vdsosym+$(NM)$<|$(gen-vdsosym)|LC_ALL=Csort>$@&&\+cp$@include/generated/+endef++$(obj)/vdso-ilp32-offsets.h:$(obj)/vdso-ilp32.so.dbgFORCE+$(callif_changed,vdsosym)++# Assembly rules for the .S files+#$(obj-ilp32-vdso): %.o: $(src)/../vdso/$(subst -ilp32,,%.S)+# $(call if_changed_dep,vdso-ilp32as)++$(obj)/gettimeofday-ilp32.o:$(src)/../vdso/gettimeofday.S+$(callif_changed_dep,vdso-ilp32as)++$(obj)/note-ilp32.o:$(src)/../vdso/note.S+$(callif_changed_dep,vdso-ilp32as)++$(obj)/sigreturn-ilp32.o:$(src)/../vdso/sigreturn.S+$(callif_changed_dep,vdso-ilp32as)++# Actual build commands+quiet_cmd_vdso-ilp32ld=VDSOILP32L$@+cmd_vdso-ilp32ld=$(CC)$(c_flags)-mabi=ilp32-Wl,-n-Wl,-T$^-o$@+quiet_cmd_vdso-ilp32as=VDSOILP32A$@+cmd_vdso-ilp32as=$(CC)$(a_flags)-mabi=ilp32-c-o$@$<++# Install commands for the unstripped file+quiet_cmd_vdso_install=INSTALL$@+cmd_vdso_install=cp$(obj)/$@.dbg$(MODLIB)/vdso/$@++vdso-ilp32.so:$(obj)/vdso-ilp32.so.dbg+@mkdir-p$(MODLIB)/vdso+$(callcmd,vdso_install)++vdso_install:vdso-ilp32.so
@@ -109,24 +115,29 @@ int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)}#endif /* CONFIG_AARCH32_EL0 */-staticstructvm_special_mappingvdso_spec[2];--staticint__initvdso_init(void)+staticint__initvdso_init_common(char*vdso_start,char*vdso_end,+unsignedlong*vdso_pagesp,+structpage***vdso_pagelistp,+structvm_special_mapping*vdso_spec){inti;+unsignedlongvdso_pages;+structpage**vdso_pagelist;-if(memcmp(&vdso_start,"\177ELF",4)){+if(memcmp(vdso_start,"\177ELF",4)){pr_err("vDSO is not a valid ELF object!\n");return-EINVAL;}-vdso_pages=(&vdso_end-&vdso_start)>>PAGE_SHIFT;+vdso_pages=(vdso_end-vdso_start)>>PAGE_SHIFT;+*vdso_pagesp=vdso_pages;pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",-vdso_pages+1,vdso_pages,&vdso_start,1L,vdso_data);+vdso_pages+1,vdso_pages,vdso_start,1L,vdso_data);/* Allocate the vDSO pagelist, plus a page for the data. */vdso_pagelist=kcalloc(vdso_pages+1,sizeof(structpage*),GFP_KERNEL);+*vdso_pagelistp=vdso_pagelist;if(vdso_pagelist==NULL)return-ENOMEM;
@@ -135,7 +146,7 @@ static int __init vdso_init(void)/* Grab the vDSO code pages. */for(i=0;i<vdso_pages;i++)-vdso_pagelist[i+1]=virt_to_page(&vdso_start+i*PAGE_SIZE);+vdso_pagelist[i+1]=virt_to_page(vdso_start+i*PAGE_SIZE);/* Populate the special mapping structures */vdso_spec[0]=(structvm_special_mapping){
@@ -150,16 +161,46 @@ static int __init vdso_init(void)return0;}++staticstructvm_special_mappingvdso_spec[2];++staticint__initvdso_init(void)+{+returnvdso_init_common(&vdso_start,&vdso_end,+&vdso_pages,&vdso_pagelist,+vdso_spec);+}arch_initcall(vdso_init);+#ifdef CONFIG_ARM64_ILP32+staticstructvm_special_mappingvdso_ilp32_spec[2];++staticint__initvdso_ilp32_init(void)+{+returnvdso_init_common(&vdso_ilp32_start,&vdso_ilp32_end,+&vdso_ilp32_pages,&vdso_ilp32_pagelist,+vdso_ilp32_spec);+}+arch_initcall(vdso_ilp32_init);+#endif+intarch_setup_additional_pages(structlinux_binprm*bprm,intuses_interp){structmm_struct*mm=current->mm;unsignedlongvdso_base,vdso_text_len,vdso_mapping_len;void*ret;+unsignedlongpages=vdso_pages;+structvm_special_mapping*spec=vdso_spec;++#ifdef CONFIG_ARM64_ILP32+if(is_ilp32_compat_task()){+pages=vdso_ilp32_pages;+spec=vdso_ilp32_spec;+}+#endif-vdso_text_len=vdso_pages<<PAGE_SHIFT;+vdso_text_len=pages<<PAGE_SHIFT;/* Be sure to map the data page */vdso_mapping_len=vdso_text_len+PAGE_SIZE;
@@ -171,7 +212,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,}ret=_install_special_mapping(mm,vdso_base,PAGE_SIZE,VM_READ|VM_MAYREAD,-&vdso_spec[0]);+&spec[0]);if(IS_ERR(ret))gotoup_fail;
@@ -180,7 +221,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,ret=_install_special_mapping(mm,vdso_base,vdso_text_len,VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,-&vdso_spec[1]);+&spec[1]);if(IS_ERR(ret))gotoup_fail;
From: Philipp Tomsich <redacted>
To make life for tools (such as gdb) easier when dealing with ILP32 processes,
we report a proper subarchitecture for ILP32 in the ELF auxiliary vectors.
Signed-off-by: Andrew Pinski <redacted>
Signed-off-by: Philipp Tomsich <redacted>
Signed-off-by: Christoph Muellner <redacted>
Signed-off-by: Yury Norov <redacted>
Reviewed-by: David Daney <redacted>
---
arch/arm64/include/asm/elf.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -763,7 +763,7 @@ source "fs/Kconfig.binfmt"configCOMPATdef_booly-depends onAARCH32_EL0+depends onAARCH32_EL0||ARM64_ILP32configAARCH32_EL0bool"Kernel support for 32-bit EL0"
@@ -783,6 +783,13 @@ config AARCH32_EL0Ifyouwanttoexecute32-bituserspaceapplications,sayY.+configARM64_ILP32+bool"Kernel support for ILP32"+help+ThisoptionenablessupportforAArch64ILP32userspace.ILP32+isanABIwherelongandpointersare32bitsbutitusestheAARCH64+instructionset.+configSYSVIPC_COMPATdef_boolydepends onCOMPAT&&SYSVIPC
Not sure about this. Originally it was just:
#define compat_elf_check_arch(x) (((x)->e_machine == EM_AARCH64) \
But how than distinguish aarch64 and aarch64/ilp32 elfs?
On Friday 08 January 2016 02:34:23 Yury Norov wrote:
From: Bamvor Jian Zhang <redacted>
With the patches of ILP32, COMPAT is not equivalent to AARCH32 in EL0.
This patch fix this by updating the dependency from COMPAT to
AARCH32_EL0 for ARMV8_DEPRECATED and ARM64_ERRATUM_845719.
Signed-off-by: Bamvor Jian Zhang <redacted>
Signed-off-by: Yury Norov <redacted>
I'd change the title of this patch: at this point in the series, the
dependency is not wrong yet, it just needs to be changed before
ARM64_ILP32 gets introduced.
Arnd
This should no longer be needed after patch 11: just define the ELF_HWCAP
and ELF_HWCAP2 values for the right mode when including fs/binfmt_elf.c.
You know what it should be at build time, so don't bother doing a runtime
check.
Arnd
Looking at this again, I think we can avoid this runtime check
if we duplicate the compat_sys_ptrace function and make a special one
for a32 that is copied from the regular handler and but calls
compat_a32_ptrace directly. Or maybe make a separate handler for
arm64-ilp32 if that is smaller.
Arnd
On Friday 08 January 2016 02:34:32 Yury Norov wrote:
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t off);
+#define sys_mmap2 sys_mmap
Why do you need a separate declaration for sys_mmap here? There
is one in include/asm-generic/syscalls.h that should be visible
in this file.
Arnd
On Friday 08 January 2016 02:34:29 Yury Norov wrote:
+
+#include "../../../fs/compat_binfmt_elf.c"
This is the wrong file, you have to include fs/binfmt_elf.c, otherwise
you pick up the same definitions that you have for the other one.
Alternatively, you can also change binfmt_elf32.c to include fs/binfmt_elf.c
and use fs/compat_binfmt_elf.c here if that makes the code nicer, you
just can use the compat file for both or things get ugly because of
the extra indirections.
Arnd
On Friday 08 January 2016 02:34:32 Yury Norov wrote:
quoted hunk
@@ -688,6 +692,12 @@ ni_sys: b ret_fast_syscall ENDPROC(el0_svc)+#ifdef CONFIG_ARM64_ILP32+el0_ilp32_svc:+ adrp stbl, sys_call_ilp32_table // load syscall table pointer+ b el0_svc_naked+#endif
Don't we still need some code that clears the top halves of the 32-bit
arguments? That thread has taken so many turns now that I'm confused
about what we actually need, but I thought we had concluded that your
current approach has at some some problems.
On Fri, Jan 08, 2016 at 10:21:06AM +0100, Arnd Bergmann wrote:
On Friday 08 January 2016 02:34:32 Yury Norov wrote:
quoted
@@ -688,6 +692,12 @@ ni_sys: b ret_fast_syscall ENDPROC(el0_svc)+#ifdef CONFIG_ARM64_ILP32+el0_ilp32_svc:+ adrp stbl, sys_call_ilp32_table // load syscall table pointer+ b el0_svc_naked+#endif
Don't we still need some code that clears the top halves of the 32-bit
arguments? That thread has taken so many turns now that I'm confused
about what we actually need, but I thought we had concluded that your
current approach has at some some problems.
We are discussing how to do it better - make a generic solution from
s390 with individual syscall handling, or reproduce s390 solution for
ILP32, or zero top-half registers and not use top half of register at
all. As I understand, we stand on 1st option, and agreed to introduce
it separately.
On Friday 08 January 2016 14:13:18 Yury Norov wrote:
On Fri, Jan 08, 2016 at 10:21:06AM +0100, Arnd Bergmann wrote:
quoted
On Friday 08 January 2016 02:34:32 Yury Norov wrote:
quoted
@@ -688,6 +692,12 @@ ni_sys: b ret_fast_syscall ENDPROC(el0_svc)+#ifdef CONFIG_ARM64_ILP32+el0_ilp32_svc:+ adrp stbl, sys_call_ilp32_table // load syscall table pointer+ b el0_svc_naked+#endif
Don't we still need some code that clears the top halves of the 32-bit
arguments? That thread has taken so many turns now that I'm confused
about what we actually need, but I thought we had concluded that your
current approach has at some some problems.
We are discussing how to do it better - make a generic solution from
s390 with individual syscall handling, or reproduce s390 solution for
ILP32, or zero top-half registers and not use top half of register at
all. As I understand, we stand on 1st option, and agreed to introduce
it separately.
Ok. At some point I thought there was a security hole if we don't
do the explicit expansion, but now I can't remember what I was thinking
of or if that was actually real. Let me try to recall my understanding:
We know that the existing DEFINE_SYSCALL wrappers work fine for
32-bit (__u32, int, unsigned int, ...) or smaller (char, short, __u8,
__u16, ...) arguments as well as the explicitly 64-bit arguments (loff_t,
__u64, __s64). Entering a syscall with a 'long' (or size_t, pointer, ...)
argument means that user space expects the kernel to ignore the upper
half, but the kernel will treat it as part of the register. This means
anything we pass into the kernel will follow the ELF ABI for function
calls, and I don't see a security problem here either, just the question
of how the ABI should be defined.
(sorry for the excursion, I needed to write that down to get my own
thoughts sorted)
I still think that the first option from Catalin's email is best here,
and it would be good if you could implement that so we can see if
there are any complications we have not thought of yet.
Arnd
On Fri, Jan 08, 2016 at 10:08:44AM +0100, Arnd Bergmann wrote:
On Friday 08 January 2016 02:34:29 Yury Norov wrote:
quoted
+
+#include "../../../fs/compat_binfmt_elf.c"
This is the wrong file, you have to include fs/binfmt_elf.c, otherwise
you pick up the same definitions that you have for the other one.
I chose compat as it's how it wokrs now. It redefines some types like
user_long_t, and I think it's neccessary for ILP32, as for aarch32.
Alternatively, you can also change binfmt_elf32.c to include fs/binfmt_elf.c
and use fs/compat_binfmt_elf.c here if that makes the code nicer, you
just can use the compat file for both or things get ugly because of
the extra indirections.
Arnd
On Tuesday 12 January 2016 19:46:41 Yury Norov wrote:
On Fri, Jan 08, 2016 at 10:08:44AM +0100, Arnd Bergmann wrote:
quoted
On Friday 08 January 2016 02:34:29 Yury Norov wrote:
quoted
+
+#include "../../../fs/compat_binfmt_elf.c"
This is the wrong file, you have to include fs/binfmt_elf.c, otherwise
you pick up the same definitions that you have for the other one.
I chose compat as it's how it wokrs now. It redefines some types like
user_long_t, and I think it's neccessary for ILP32, as for aarch32.
I really think the double indirection adds way too much complexity
here, it makes it rather hard to understand what is going on, and
that leads to bugs.
fs/compat_binfmt_elf.c is not doing much at all, and most of it is not
actually needed if you just make a copy of that file and fill in the
data as needed. Some of the overrides (ELF_ARCH, ELF_PLATFORM, ELF_NREG,
ELF_HWCAP, ELF_HWCAP2) are identical between ilp32 and lp64 modes
for arm64, but are different for arm32 compat, so you don't even have
to override them at all.
Arnd
On Fri, Jan 08, 2016 at 10:21:06AM +0100, Arnd Bergmann wrote:
On Friday 08 January 2016 02:34:32 Yury Norov wrote:
quoted
@@ -688,6 +692,12 @@ ni_sys: b ret_fast_syscall ENDPROC(el0_svc)+#ifdef CONFIG_ARM64_ILP32+el0_ilp32_svc:+ adrp stbl, sys_call_ilp32_table // load syscall table pointer+ b el0_svc_naked+#endif
Don't we still need some code that clears the top halves of the 32-bit
arguments? That thread has taken so many turns now that I'm confused
about what we actually need, but I thought we had concluded that your
current approach has at some some problems.