From: Kurt Garloff <garloff@suse.de>
To: Linux kernel list <linux-kernel@vger.kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Subject: Non-Exec stack patches
Date: Wed, 24 Mar 2004 00:12:56 +0100 [thread overview]
Message-ID: <20040323231256.GP4677@tpkurt.garloff.de> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 867 bytes --]
Hi,
find attached a patch to parse the elf binaries for a PT_GNU_STACK
section to set the stack non-executable if possible.
Most parts have been shamelessly stolen from Ingo Molnar's more
ambitious stackshield
http://people.redhat.com/mingo/exec-shield/exec-shield-2.6.4-C9
The toolchain has meainwhile support for marking the binaries with a
PT_GNU_STACK section with ot without x bit as needed.
If no such section is found, we leave the stack to whatever the
arch defaults to. If there is one, we explicitly disabled the VM_EXEC
bit if no x bit is found, otherwise explicitly enable.
I believe this part should be merged into official mainstream kernels.
Ingo, what do you think?
Regards,
--
Kurt Garloff <garloff@suse.de> Cologne, DE
SUSE LINUX AG, Nuernberg, DE SUSE Labs (Head)
[-- Attachment #1.2: noexec_stack4 --]
[-- Type: text/plain, Size: 13247 bytes --]
diff -uNrp linux-2.6.4.EXSTACK/arch/ia64/ia32/binfmt_elf32.c linux-2.6.4.noexec/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.6.4.EXSTACK/arch/ia64/ia32/binfmt_elf32.c 2004-03-23 21:18:35.000000000 +0100
+++ linux-2.6.4.noexec/arch/ia64/ia32/binfmt_elf32.c 2004-03-23 22:48:31.000000000 +0100
@@ -35,7 +35,7 @@ extern void ia64_elf32_init (struct pt_r
static void elf32_set_personality (void);
-#define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
+#define setup_arg_pages(bprm,exec) ia32_setup_arg_pages(bprm,exec)
#define elf_map elf32_map
#undef SET_PERSONALITY
@@ -152,7 +152,7 @@ ia64_elf32_init (struct pt_regs *regs)
}
int
-ia32_setup_arg_pages (struct linux_binprm *bprm)
+ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
@@ -181,8 +181,14 @@ ia32_setup_arg_pages (struct linux_binpr
mpnt->vm_mm = current->mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = IA32_STACK_TOP;
- mpnt->vm_page_prot = PAGE_COPY;
- mpnt->vm_flags = VM_STACK_FLAGS;
+ if (executable_stack > 0)
+ mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC;
+ else if (executable_stack < 0)
+ mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC;
+ else
+ mpnt->vm_flags = VM_STACK_FLAGS;
+ mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)?
+ PAGE_COPY_EXEC: PAGE_COPY;
mpnt->vm_ops = NULL;
mpnt->vm_pgoff = mpnt->vm_start >> PAGE_SHIFT;
mpnt->vm_file = NULL;
@@ -197,7 +203,7 @@ ia32_setup_arg_pages (struct linux_binpr
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
- put_dirty_page(current, page, stack_base, PAGE_COPY, mpnt);
+ put_dirty_page(current, page, stack_base, mpnt->vm_page_prot, mpnt);
}
stack_base += PAGE_SIZE;
}
diff -uNrp linux-2.6.4.EXSTACK/arch/ia64/ia32/ia32priv.h linux-2.6.4.noexec/arch/ia64/ia32/ia32priv.h
--- linux-2.6.4.EXSTACK/arch/ia64/ia32/ia32priv.h 2004-03-11 03:55:51.000000000 +0100
+++ linux-2.6.4.noexec/arch/ia64/ia32/ia32priv.h 2004-03-23 22:56:20.000000000 +0100
@@ -494,7 +494,7 @@ struct ia32_user_desc {
struct linux_binprm;
extern void ia32_init_addr_space (struct pt_regs *regs);
-extern int ia32_setup_arg_pages (struct linux_binprm *bprm);
+extern int ia32_setup_arg_pages (struct linux_binprm *bprm, int exec_stack);
extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t);
extern void ia32_load_segment_descriptors (struct task_struct *task);
diff -uNrp linux-2.6.4.EXSTACK/arch/mips/kernel/irixelf.c linux-2.6.4.noexec/arch/mips/kernel/irixelf.c
--- linux-2.6.4.EXSTACK/arch/mips/kernel/irixelf.c 2004-03-11 03:56:03.000000000 +0100
+++ linux-2.6.4.noexec/arch/mips/kernel/irixelf.c 2004-03-23 22:56:42.000000000 +0100
@@ -688,7 +688,7 @@ static int load_irix_binary(struct linux
* change some of these later.
*/
current->mm->rss = 0;
- setup_arg_pages(bprm);
+ setup_arg_pages(bprm, 0);
current->mm->start_stack = bprm->p;
/* At this point, we assume that the image should be loaded at
diff -uNrp linux-2.6.4.EXSTACK/arch/s390/kernel/binfmt_elf32.c linux-2.6.4.noexec/arch/s390/kernel/binfmt_elf32.c
--- linux-2.6.4.EXSTACK/arch/s390/kernel/binfmt_elf32.c 2004-03-11 03:55:44.000000000 +0100
+++ linux-2.6.4.noexec/arch/s390/kernel/binfmt_elf32.c 2004-03-23 22:51:25.000000000 +0100
@@ -114,7 +114,7 @@ typedef s390_regs32 elf_gregset_t;
#include <linux/binfmts.h>
#include <linux/compat.h>
-int setup_arg_pages32(struct linux_binprm *bprm);
+int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack);
#define elf_prstatus elf_prstatus32
struct elf_prstatus32
@@ -165,7 +165,7 @@ struct elf_prpsinfo32
#undef start_thread
#define start_thread start_thread31
-#define setup_arg_pages(bprm) setup_arg_pages32(bprm)
+#define setup_arg_pages(bprm, exec) setup_arg_pages32(bprm, exec)
#define elf_map elf_map32
MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
diff -uNrp linux-2.6.4.EXSTACK/arch/s390/kernel/compat_exec.c linux-2.6.4.noexec/arch/s390/kernel/compat_exec.c
--- linux-2.6.4.EXSTACK/arch/s390/kernel/compat_exec.c 2004-03-23 21:18:35.000000000 +0100
+++ linux-2.6.4.noexec/arch/s390/kernel/compat_exec.c 2004-03-23 22:58:15.000000000 +0100
@@ -37,7 +37,7 @@
#undef STACK_TOP
#define STACK_TOP TASK31_SIZE
-int setup_arg_pages32(struct linux_binprm *bprm)
+int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
@@ -66,6 +66,7 @@ int setup_arg_pages32(struct linux_binpr
mpnt->vm_mm = mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = STACK_TOP;
+ /* executable stack setting would be applied here */
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
diff -uNrp linux-2.6.4.EXSTACK/arch/sparc64/kernel/binfmt_aout32.c linux-2.6.4.noexec/arch/sparc64/kernel/binfmt_aout32.c
--- linux-2.6.4.EXSTACK/arch/sparc64/kernel/binfmt_aout32.c 2004-03-11 03:55:27.000000000 +0100
+++ linux-2.6.4.noexec/arch/sparc64/kernel/binfmt_aout32.c 2004-03-23 22:49:50.000000000 +0100
@@ -310,7 +310,7 @@ beyond_if:
orig_thr_flags = current_thread_info()->flags;
current_thread_info()->flags |= _TIF_32BIT;
- retval = setup_arg_pages(bprm);
+ retval = setup_arg_pages(bprm, 0);
if (retval < 0) {
current_thread_info()->flags = orig_thr_flags;
diff -uNrp linux-2.6.4.EXSTACK/arch/x86_64/ia32/ia32_aout.c linux-2.6.4.noexec/arch/x86_64/ia32/ia32_aout.c
--- linux-2.6.4.EXSTACK/arch/x86_64/ia32/ia32_aout.c 2004-03-11 03:55:54.000000000 +0100
+++ linux-2.6.4.noexec/arch/x86_64/ia32/ia32_aout.c 2004-03-23 22:59:47.000000000 +0100
@@ -35,7 +35,7 @@
#undef WARN_OLD
#undef CORE_DUMP /* probably broken */
-extern int ia32_setup_arg_pages(struct linux_binprm *bprm);
+extern int ia32_setup_arg_pages(struct linux_binprm *bprm, int exec_stack);
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(struct file*);
@@ -395,7 +395,7 @@ beyond_if:
set_brk(current->mm->start_brk, current->mm->brk);
- retval = ia32_setup_arg_pages(bprm);
+ retval = ia32_setup_arg_pages(bprm, 0);
if (retval < 0) {
/* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0);
diff -uNrp linux-2.6.4.EXSTACK/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.4.noexec/arch/x86_64/ia32/ia32_binfmt.c
--- linux-2.6.4.EXSTACK/arch/x86_64/ia32/ia32_binfmt.c 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/arch/x86_64/ia32/ia32_binfmt.c 2004-03-23 21:18:35.000000000 +0100
@@ -272,8 +272,8 @@ do { \
#define load_elf_binary load_elf32_binary
#define ELF_PLAT_INIT(r, load_addr) elf32_init(r)
-#define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
-int ia32_setup_arg_pages(struct linux_binprm *bprm);
+#define setup_arg_pages(bprm, exec_stack) ia32_setup_arg_pages(bprm, exec_stack)
+int ia32_setup_arg_pages(struct linux_binprm *bprm, int executable_stack);
#undef start_thread
#define start_thread(regs,new_rip,new_rsp) do { \
@@ -325,7 +325,7 @@ static void elf32_init(struct pt_regs *r
me->thread.es = __USER_DS;
}
-int setup_arg_pages(struct linux_binprm *bprm)
+int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
@@ -354,7 +354,12 @@ int setup_arg_pages(struct linux_binprm
mpnt->vm_mm = mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = IA32_STACK_TOP;
- mpnt->vm_flags = vm_stack_flags32;
+ if (executable_stack > 0)
+ mpnt->vm_flags = vm_stack_flags32 | VM_EXEC;
+ else if (executable_stack < 0)
+ mpnt->vm_flags = vm_stack_flags32 & ~VM_EXEC;
+ else
+ mpnt->vm_flags = vm_stack_flags32;
mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ?
PAGE_COPY_EXEC : PAGE_COPY;
mpnt->vm_ops = NULL;
@@ -373,7 +378,7 @@ int setup_arg_pages(struct linux_binprm
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
- put_dirty_page(current,page,stack_base,PAGE_COPY_EXEC, mpnt);
+ put_dirty_page(current,page,stack_base,mpnt->vm_page_prot,mpnt);
}
stack_base += PAGE_SIZE;
}
diff -uNrp linux-2.6.4.EXSTACK/fs/binfmt_aout.c linux-2.6.4.noexec/fs/binfmt_aout.c
--- linux-2.6.4.EXSTACK/fs/binfmt_aout.c 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/fs/binfmt_aout.c 2004-03-23 21:18:35.000000000 +0100
@@ -413,7 +413,7 @@ beyond_if:
set_brk(current->mm->start_brk, current->mm->brk);
- retval = setup_arg_pages(bprm);
+ retval = setup_arg_pages(bprm, 0);
if (retval < 0) {
/* Someone check-me: is this error path enough? */
send_sig(SIGKILL, current, 0);
diff -uNrp linux-2.6.4.EXSTACK/fs/binfmt_elf.c linux-2.6.4.noexec/fs/binfmt_elf.c
--- linux-2.6.4.EXSTACK/fs/binfmt_elf.c 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/fs/binfmt_elf.c 2004-03-23 21:18:35.000000000 +0100
@@ -476,6 +476,7 @@ static int load_elf_binary(struct linux_
struct exec interp_ex;
char passed_fileno[6];
struct files_struct *files;
+ int executable_stack = 0; /* Don't touch */
/* Get the exec-header */
elf_ex = *((struct elfhdr *) bprm->buf);
@@ -599,6 +600,15 @@ static int load_elf_binary(struct linux_
elf_ppnt++;
}
+ elf_ppnt = elf_phdata;
+ for (i = 0; i < elf_ex.e_phnum; i++, elf_ppnt++)
+ if (elf_ppnt->p_type == PT_GNU_STACK) {
+ if (elf_ppnt->p_flags & PF_X)
+ executable_stack = 1;
+ else
+ executable_stack = -1;
+ }
+
/* Some simple consistency checks for the interpreter */
if (elf_interpreter) {
interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
@@ -674,7 +684,7 @@ static int load_elf_binary(struct linux_
change some of these later */
current->mm->rss = 0;
current->mm->free_area_cache = TASK_UNMAPPED_BASE;
- retval = setup_arg_pages(bprm);
+ retval = setup_arg_pages(bprm, executable_stack);
if (retval < 0) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
diff -uNrp linux-2.6.4.EXSTACK/fs/binfmt_som.c linux-2.6.4.noexec/fs/binfmt_som.c
--- linux-2.6.4.EXSTACK/fs/binfmt_som.c 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/fs/binfmt_som.c 2004-03-23 21:18:35.000000000 +0100
@@ -254,7 +254,7 @@ load_som_binary(struct linux_binprm * bp
set_binfmt(&som_format);
compute_creds(bprm);
- setup_arg_pages(bprm);
+ setup_arg_pages(bprm, 0);
create_som_tables(bprm);
diff -uNrp linux-2.6.4.EXSTACK/fs/exec.c linux-2.6.4.noexec/fs/exec.c
--- linux-2.6.4.EXSTACK/fs/exec.c 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/fs/exec.c 2004-03-23 21:18:35.000000000 +0100
@@ -342,7 +342,7 @@ out_sig:
return;
}
-int setup_arg_pages(struct linux_binprm *bprm)
+int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
@@ -425,8 +425,13 @@ int setup_arg_pages(struct linux_binprm
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = STACK_TOP;
#endif
- mpnt->vm_page_prot = protection_map[VM_STACK_FLAGS & 0x7];
- mpnt->vm_flags = VM_STACK_FLAGS;
+ if (executable_stack > 0)
+ mpnt->vm_flags = VM_STACK_FLAGS | VM_EXEC;
+ else if (executable_stack < 0)
+ mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC;
+ else
+ mpnt->vm_flags = VM_STACK_FLAGS;
+ mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
mpnt->vm_ops = NULL;
mpnt->vm_pgoff = mpnt->vm_start >> PAGE_SHIFT;
mpnt->vm_file = NULL;
diff -uNrp linux-2.6.4.EXSTACK/include/linux/binfmts.h linux-2.6.4.noexec/include/linux/binfmts.h
--- linux-2.6.4.EXSTACK/include/linux/binfmts.h 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/include/linux/binfmts.h 2004-03-23 21:18:35.000000000 +0100
@@ -58,7 +58,7 @@ extern int prepare_binprm(struct linux_b
extern void remove_arg_zero(struct linux_binprm *);
extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
extern int flush_old_exec(struct linux_binprm * bprm);
-extern int setup_arg_pages(struct linux_binprm * bprm);
+extern int setup_arg_pages(struct linux_binprm * bprm, int executable_stack);
extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm);
extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
extern void compute_creds(struct linux_binprm *binprm);
diff -uNrp linux-2.6.4.EXSTACK/include/linux/elf.h linux-2.6.4.noexec/include/linux/elf.h
--- linux-2.6.4.EXSTACK/include/linux/elf.h 2004-03-23 22:42:31.000000000 +0100
+++ linux-2.6.4.noexec/include/linux/elf.h 2004-03-23 21:18:35.000000000 +0100
@@ -35,6 +35,8 @@ typedef __s64 Elf64_Sxword;
#define PT_HIPROC 0x7fffffff
#define PT_GNU_EH_FRAME 0x6474e550
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+
/* These constants define the different elf file types */
#define ET_NONE 0
#define ET_REL 1
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
next reply other threads:[~2004-03-23 23:13 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-03-23 23:12 Kurt Garloff [this message]
2004-03-23 23:22 ` Non-Exec stack patches Ingo Molnar
2004-03-23 23:49 ` Andrew Morton
2004-03-24 0:21 ` Kurt Garloff
2004-03-24 0:38 ` David Mosberger
2004-03-24 1:20 ` Ulrich Drepper
2004-03-24 1:41 ` David Mosberger
2004-03-24 2:01 ` Ulrich Drepper
2004-03-24 7:09 ` David Mosberger
2004-03-24 7:00 ` Jakub Jelinek
2004-03-24 7:16 ` David Mosberger
2004-03-24 7:28 ` Jakub Jelinek
2004-03-24 7:45 ` David Mosberger
2004-03-24 16:29 ` John Reiser
2004-03-24 17:12 ` David Mosberger
2004-03-24 17:24 ` Jakub Jelinek
2004-03-24 18:01 ` David Mosberger
2004-03-24 19:02 ` John Reiser
2004-03-24 19:18 ` David Mosberger
2004-03-24 0:41 ` Andrew Morton
2004-03-24 0:41 ` Ingo Molnar
2004-03-24 10:53 ` Kurt Garloff
[not found] <1D3lO-3dh-13@gated-at.bofh.it>
[not found] ` <1D3YZ-3Gl-1@gated-at.bofh.it>
2004-03-24 6:01 ` Andi Kleen
2004-03-24 10:23 ` Stefan Smietanowski
2004-03-24 11:27 ` Andi Kleen
2004-03-24 22:03 ` Kurt Garloff
[not found] <20040324002149.GT4677@tpkurt.garloff.de.suse.lists.linux.kernel>
[not found] ` <16480.55450.730214.175997@napali.hpl.hp.com.suse.lists.linux.kernel>
[not found] ` <4060E24C.9000507@redhat.com.suse.lists.linux.kernel>
[not found] ` <16480.59229.808025.231875@napali.hpl.hp.com.suse.lists.linux.kernel>
[not found] ` <20040324070020.GI31589@devserv.devel.redhat.com.suse.lists.linux.kernel>
[not found] ` <16481.13780.673796.20976@napali.hpl.hp.com.suse.lists.linux.kernel>
[not found] ` <20040324072840.GK31589@devserv.devel.redhat.com.suse.lists.linux.kernel>
[not found] ` <16481.15493.591464.867776@napali.hpl.hp.com.suse.lists.linux.kernel>
[not found] ` <4061B764.5070008@BitWagon.com.suse.lists.linux.kernel>
[not found] ` <16481.49534.124281.434663@napali.hpl.hp.com.suse.lists.linux.kernel>
[not found] ` <20040324172454.GP31589@devserv.devel.redhat.com.suse.lists.linux.kernel>
2004-03-24 17:49 ` Andi Kleen
2004-03-24 17:54 ` Jakub Jelinek
-- strict thread matches above, loose matches on Subject: below --
2004-04-14 7:28 Siddha, Suresh B
2004-04-14 8:23 ` Jamie Lokier
2004-04-14 9:47 ` Jamie Lokier
2004-04-14 18:30 ` Kurt Garloff
2004-04-14 20:54 ` Jeff Dike
2004-04-14 8:45 Siddha, Suresh B
2004-04-14 9:38 ` Jamie Lokier
2004-04-14 19:14 Siddha, Suresh B
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040323231256.GP4677@tpkurt.garloff.de \
--to=garloff@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox