* [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL
@ 2004-09-10 16:17 Arun Sharma
2004-09-21 21:56 ` Andreas Schwab
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Arun Sharma @ 2004-09-10 16:17 UTC (permalink / raw)
To: linux-ia64
[-- Attachment #1: Type: text/plain, Size: 366 bytes --]
When userland doesn't specify sigaction->sa_restorer, we try to put
the restorer code on the stack. But this breaks ia32 binaries with
non-executable stacks. We now put the restorer code on a gate page.
We still leave the sigreturn code on the stack due to backward
compatibility concerns with ia32 gdb.
This issue was primarily seen with debian glibc.
-Arun
[-- Attachment #2: ive-gate-page-3.patch --]
[-- Type: text/plain, Size: 9306 bytes --]
When userland doesn't specify sigaction->sa_restorer, we try to put
the restorer code on the stack. But this breaks ia32 binaries with
non-executable stacks. We now put the restorer code on a gate page.
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
arch/ia64/ia32/binfmt_elf32.c | 39 +++++++++++++++++++++++++++++++++++++++
arch/ia64/ia32/ia32_signal.c | 33 ++++++++++++++++++++++-----------
arch/ia64/ia32/ia32_support.c | 28 +++++++++++++++++++++++++---
arch/ia64/ia32/ia32priv.h | 11 ++++++++---
arch/ia64/mm/init.c | 2 +-
include/asm-ia64/ia32.h | 2 +-
6 files changed, 96 insertions(+), 19 deletions(-)
diff -purN -X dontdiff linux-2.6.8.ori/arch/ia64/ia32/binfmt_elf32.c linux-2.6.8/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.6.8.ori/arch/ia64/ia32/binfmt_elf32.c 2004-08-16 15:36:30.000000000 +0800
+++ linux-2.6.8/arch/ia64/ia32/binfmt_elf32.c 2004-09-09 18:31:47.000000000 +0800
@@ -48,6 +48,7 @@ static void elf32_set_personality (void)
extern struct page *ia32_shared_page[];
extern unsigned long *ia32_gdt;
+extern struct page *ia32_gate_page;
struct page *
ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type)
@@ -59,10 +60,25 @@ ia32_install_shared_page (struct vm_area
return pg;
}
+struct page *
+ia32_install_gate_page (struct vm_area_struct *vma, unsigned long address, int *type)
+{
+ struct page *pg = ia32_gate_page;
+ get_page(pg);
+ if (type)
+ *type = VM_FAULT_MINOR;
+ return pg;
+}
+
+
static struct vm_operations_struct ia32_shared_page_vm_ops = {
.nopage = ia32_install_shared_page
};
+static struct vm_operations_struct ia32_gate_page_vm_ops = {
+ .nopage = ia32_install_gate_page
+};
+
void
ia64_elf32_init (struct pt_regs *regs)
{
@@ -90,6 +106,29 @@ ia64_elf32_init (struct pt_regs *regs)
}
/*
+ * When user stack is not executable, push sigreturn code to stack makes
+ * segmentation fault raised when returning to kernel. So now sigreturn
+ * code is locked in specific gate page, which is pointed by pretcode
+ * when setup_frame_ia32
+ */
+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma) {
+ memset(vma, 0, sizeof(*vma));
+ vma->vm_mm = current->mm;
+ vma->vm_start = IA32_GATE_OFFSET;
+ vma->vm_end = vma->vm_start + PAGE_SIZE;
+ vma->vm_page_prot = PAGE_COPY_EXEC;
+ vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC
+ | VM_MAYEXEC | VM_RESERVED;
+ vma->vm_ops = &ia32_gate_page_vm_ops;
+ down_write(¤t->mm->mmap_sem);
+ {
+ insert_vm_struct(current->mm, vma);
+ }
+ up_write(¤t->mm->mmap_sem);
+ }
+
+ /*
* Install LDT as anonymous memory. This gives us all-zero segment descriptors
* until a task modifies them via modify_ldt().
*/
diff -purN -X dontdiff linux-2.6.8.ori/arch/ia64/ia32/ia32priv.h linux-2.6.8/arch/ia64/ia32/ia32priv.h
--- linux-2.6.8.ori/arch/ia64/ia32/ia32priv.h 2004-08-16 15:36:30.000000000 +0800
+++ linux-2.6.8/arch/ia64/ia32/ia32priv.h 2004-09-09 19:03:34.000000000 +0800
@@ -168,6 +168,9 @@ struct ia32_user_fxsr_struct {
#define IA32_SA_HANDLER(ka) ((unsigned long) (ka)->sa.sa_handler & 0xffffffff)
#define IA32_SA_RESTORER(ka) ((unsigned long) (ka)->sa.sa_handler >> 32)
+#define __IA32_NR_sigreturn 119
+#define __IA32_NR_rt_sigreturn 173
+
struct sigaction32 {
unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */
unsigned int sa_flags;
@@ -324,14 +327,16 @@ struct old_linux32_dirent {
#define IA32_PAGE_OFFSET 0xc0000000
#define IA32_STACK_TOP IA32_PAGE_OFFSET
+#define IA32_GATE_OFFSET IA32_PAGE_OFFSET
+#define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
/*
* The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
* access them.
*/
-#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET)
-#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
-#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_GDT_OFFSET (IA32_PAGE_OFFSET + PAGE_SIZE)
+#define IA32_TSS_OFFSET (IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_LDT_OFFSET (IA32_PAGE_OFFSET + 3*PAGE_SIZE)
#define ELF_EXEC_PAGESIZE IA32_PAGE_SIZE
diff -purN -X dontdiff linux-2.6.8.ori/arch/ia64/ia32/ia32_signal.c linux-2.6.8/arch/ia64/ia32/ia32_signal.c
--- linux-2.6.8.ori/arch/ia64/ia32/ia32_signal.c 2004-06-17 15:55:32.000000000 +0800
+++ linux-2.6.8/arch/ia64/ia32/ia32_signal.c 2004-09-09 18:31:47.000000000 +0800
@@ -853,14 +853,19 @@ setup_frame_ia32 (int sig, struct k_siga
unsigned int restorer = IA32_SA_RESTORER(ka);
err |= __put_user(restorer, &frame->pretcode);
} else {
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is popl %eax ; movl $,%eax ; int $0x80 */
- err |= __put_user(0xb858, (short *)(frame->retcode+0));
- err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
- err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
- err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+ /* Pointing to restorer in ia32 gate page */
+ err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode);
}
+ /* This is popl %eax ; movl $,%eax ; int $0x80
+ * and there for historical reasons only.
+ * See arch/i386/kernel/signal.c
+ */
+
+ err |= __put_user(0xb858, (short *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_sigreturn, (int *)(frame->retcode+2));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+
if (err)
goto give_sigsegv;
@@ -924,13 +929,19 @@ setup_rt_frame_ia32 (int sig, struct k_s
unsigned int restorer = IA32_SA_RESTORER(ka);
err |= __put_user(restorer, &frame->pretcode);
} else {
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is movl $,%eax ; int $0x80 */
- err |= __put_user(0xb8, (char *)(frame->retcode+0));
- err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
- err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+ /* Pointing to rt_restorer in ia32 gate page */
+ err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode);
}
+ /* This is movl $,%eax ; int $0x80
+ * and there for historical reasons only.
+ * See arch/i386/kernel/signal.c
+ */
+
+ err |= __put_user(0xb8, (char *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+
if (err)
goto give_sigsegv;
diff -purN -X dontdiff linux-2.6.8.ori/arch/ia64/ia32/ia32_support.c linux-2.6.8/arch/ia64/ia32/ia32_support.c
--- linux-2.6.8.ori/arch/ia64/ia32/ia32_support.c 2004-08-16 15:36:30.000000000 +0800
+++ linux-2.6.8/arch/ia64/ia32/ia32_support.c 2004-09-09 18:31:47.000000000 +0800
@@ -33,6 +33,7 @@ struct exec_domain ia32_exec_domain;
struct page *ia32_shared_page[NR_CPUS];
unsigned long *ia32_boot_gdt;
unsigned long *cpu_gdt_table[NR_CPUS];
+struct page *ia32_gate_page;
static unsigned long
load_desc (u16 selector)
@@ -155,7 +156,7 @@ ia32_gdt_init (void)
/*
* Setup IA32 GDT and TSS
*/
-void
+static void
ia32_boot_gdt_init (void)
{
unsigned long ldt_size;
@@ -166,12 +167,12 @@ ia32_boot_gdt_init (void)
/* CS descriptor in IA-32 (scrambled) format */
ia32_boot_gdt[__USER_CS >> 3]
- = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
0xb, 1, 3, 1, 1, 1, 1);
/* DS descriptor in IA-32 (scrambled) format */
ia32_boot_gdt[__USER_DS >> 3]
- = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ = IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
0x3, 1, 3, 1, 1, 1, 1);
ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
@@ -181,6 +182,27 @@ ia32_boot_gdt_init (void)
0x2, 0, 3, 1, 1, 1, 0);
}
+static void
+ia32_gate_page_init(void)
+{
+ unsigned long *sr;
+
+ ia32_gate_page = alloc_page(GFP_KERNEL);
+ sr = page_address(ia32_gate_page);
+ /* This is popl %eax ; movl $,%eax ; int $0x80 */
+ *sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48);
+
+ /* This is movl $,%eax ; int $0x80 */
+ *sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40);
+}
+
+void
+ia32_mem_init(void)
+{
+ ia32_boot_gdt_init();
+ ia32_gate_page_init();
+}
+
/*
* Handle bad IA32 interrupt via syscall
*/
diff -purN -X dontdiff linux-2.6.8.ori/arch/ia64/mm/init.c linux-2.6.8/arch/ia64/mm/init.c
--- linux-2.6.8.ori/arch/ia64/mm/init.c 2004-08-16 15:36:30.000000000 +0800
+++ linux-2.6.8/arch/ia64/mm/init.c 2004-09-09 18:31:47.000000000 +0800
@@ -585,6 +585,6 @@ mem_init (void)
setup_gate();
#ifdef CONFIG_IA32_SUPPORT
- ia32_boot_gdt_init();
+ ia32_mem_init();
#endif
}
diff -purN -X dontdiff linux-2.6.8.ori/include/asm-ia64/ia32.h linux-2.6.8/include/asm-ia64/ia32.h
--- linux-2.6.8.ori/include/asm-ia64/ia32.h 2004-08-16 15:36:43.000000000 +0800
+++ linux-2.6.8/include/asm-ia64/ia32.h 2004-09-09 18:31:47.000000000 +0800
@@ -14,7 +14,7 @@
# ifdef CONFIG_IA32_SUPPORT
extern void ia32_cpu_init (void);
-extern void ia32_boot_gdt_init (void);
+extern void ia32_mem_init (void);
extern void ia32_gdt_init (void);
extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL
2004-09-10 16:17 [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL Arun Sharma
@ 2004-09-21 21:56 ` Andreas Schwab
2004-09-22 1:44 ` Arun Sharma
2004-09-22 7:22 ` Andreas Schwab
2 siblings, 0 replies; 4+ messages in thread
From: Andreas Schwab @ 2004-09-21 21:56 UTC (permalink / raw)
To: linux-ia64
Arun Sharma <arun.sharma@intel.com> writes:
> When userland doesn't specify sigaction->sa_restorer, we try to put
> the restorer code on the stack. But this breaks ia32 binaries with
> non-executable stacks. We now put the restorer code on a gate page.
Does this work with nested signal handlers?
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL
2004-09-10 16:17 [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL Arun Sharma
2004-09-21 21:56 ` Andreas Schwab
@ 2004-09-22 1:44 ` Arun Sharma
2004-09-22 7:22 ` Andreas Schwab
2 siblings, 0 replies; 4+ messages in thread
From: Arun Sharma @ 2004-09-22 1:44 UTC (permalink / raw)
To: linux-ia64
On 9/21/2004 2:56 PM, Andreas Schwab wrote:
> Arun Sharma <arun.sharma@intel.com> writes:
>
>> When userland doesn't specify sigaction->sa_restorer, we try to put
>> the restorer code on the stack. But this breaks ia32 binaries with
>> non-executable stacks. We now put the restorer code on a gate page.
>
> Does this work with nested signal handlers?
I don't see why not. The gate page is read-only.
-Arun
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL
2004-09-10 16:17 [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL Arun Sharma
2004-09-21 21:56 ` Andreas Schwab
2004-09-22 1:44 ` Arun Sharma
@ 2004-09-22 7:22 ` Andreas Schwab
2 siblings, 0 replies; 4+ messages in thread
From: Andreas Schwab @ 2004-09-22 7:22 UTC (permalink / raw)
To: linux-ia64
Arun Sharma <arun.sharma@intel.com> writes:
> I don't see why not. The gate page is read-only.
Thanks, I understand it now.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-09-22 7:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-10 16:17 [PATCH] ia32 support for NX when sigaction->sa_restorer == NULL Arun Sharma
2004-09-21 21:56 ` Andreas Schwab
2004-09-22 1:44 ` Arun Sharma
2004-09-22 7:22 ` Andreas Schwab
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox