Ways to toggle execstack for assembly files

There are a couple of utilities to toggle whether or not the stack is executable, and ways to set this flag at various stages while compiling assembly files into ELF binaries. Below is an investigation of these options, inspired by the following kernel bug:

commit 07c3ae18cac4dc96bb87ddc7bf9ad93999890146
Author: Jiri Olsa 
Date:   Mon Feb 6 18:54:06 2012 -0200

   perf tools: Fix perf stack to non executable on x86_64

   BugLink: http://bugs.launchpad.net/bugs/937915

   commit 7a0153ee15575a4d07b5da8c96b79e0b0fd41a12 upstream.

   By adding following objects:
     bench/mem-memcpy-x86-64-asm.o
   the x86_64 perf binary ended up with executable stack.

   The reason was that above object are assembler sourced and is missing the
   GNU-stack note section. In such case the linker assumes that the final binary
   should not be restricted at all and mark the stack as RWX.

   Adding section ".note.GNU-stack" definition to mentioned object, with all
   flags disabled, thus omiting this object from linker stack flags decision.

1. Toggle noexecstack with the linker

Here’s a bare-bones assembly file:

jesstess$ cat test.S
	.text
.global _start

_start:
	mov	$0x1,%eax
	int	$0x80

Assemble it into an ELF executable by hand, and check if the stack is executable:

jesstess$ as -o test.o test.S
jesstess$ ld -s -o test test.o
jesstess$ execstack test
? test

execstack isn’t sure, because it checks for a GNU_STACK section, which our program doesn’t have:

jesstess$ readelf -Sl test
There are 3 section headers, starting at offset 0x90:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000400078  00000078
       0000000000000007  0000000000000000  AX       0     0     4
  [ 2] .shstrtab         STRTAB           0000000000000000  0000007f
       0000000000000011  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0x400078
There are 1 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000007f 0x000000000000007f  R E    200000

 Section to Segment mapping:
  Segment Sections...
   00     .text

We can ask the linker to add a GNU_STACK section:

jesstess$ ld -z execstack -s -o test_exec test.o
jesstess$ ld -z noexecstack -s -o test_noexec test.o
jesstess$ readelf -Wl test_noexec | grep GNU_STACK
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x8
jesstess$ readelf -Wl test_exec | grep GNU_STACK
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x8
jesstess$ diff <(hexdump test_noexec) <(hexdump test_exec)
8c8
< 0000070 0000 0020 0000 0000 e551 6474 0006 0000
---
> 0000070 0000 0020 0000 0000 e551 6474 0007 0000
jesstess$ execstack test_noexec test_exec
- test_noexec
X test_exec

A single SHF_EXECINSTR bit dictates if the stack is executable.

2. Toggle noexecstack in the assembly

We can toggle noexecstack directly in the assembly by adding a .note.GNU-stack section manually:

jesstess$ cat >> test.S
.section .note.GNU-stack,"",%progbits
jesstess$ as -o test_note.o test.S
jesstess$ readelf -S test_note.o
There are 8 section headers, starting at offset 0x88:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000007  0000000000000000  AX       0     0     4
  [ 2] .data             PROGBITS         0000000000000000  00000048
       0000000000000000  0000000000000000  WA       0     0     4
  [ 3] .bss              NOBITS           0000000000000000  00000048
       0000000000000000  0000000000000000  WA       0     0     4
  [ 4] .note.GNU-stack   PROGBITS         0000000000000000  00000048
       0000000000000000  0000000000000000           0     0     1
  [ 5] .shstrtab         STRTAB           0000000000000000  00000048
       000000000000003c  0000000000000000           0     0     1
  [ 6] .symtab           SYMTAB           0000000000000000  00000288
       0000000000000090  0000000000000018           7     5     8
  [ 7] .strtab           STRTAB           0000000000000000  00000318
       0000000000000008  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
jesstess$ ld -s -o test_note test.o
jesstess$ execstack test_note
- test_note

To specify an executable stack manually, add an "x" in the .section description: .section .note.GNU-stack, "x".

3. Toggle noexecstack from the compiler

To get around passing complicated linker options for this toy example, pass -nostdlib:

jesstess$ gcc -o test_gcc test.s -nostdlib
jesstess$ readelf -Sl test_gcc
There are 6 section headers, starting at offset 0x110:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.gnu.build-i NOTE             00000000004000b0  000000b0
       0000000000000024  0000000000000000   A       0     0     4
  [ 2] .text             PROGBITS         00000000004000d4  000000d4
       0000000000000007  0000000000000000  AX       0     0     4
  [ 3] .shstrtab         STRTAB           0000000000000000  000000db
       0000000000000034  0000000000000000           0     0     1
  [ 4] .symtab           SYMTAB           0000000000000000  00000290
       00000000000000a8  0000000000000018           5     3     8
  [ 5] .strtab           STRTAB           0000000000000000  00000338
       0000000000000020  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0x4000d4
There are 2 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000000db 0x00000000000000db  R E    200000
  NOTE           0x00000000000000b0 0x00000000004000b0 0x00000000004000b0
                 0x0000000000000024 0x0000000000000024  R      4

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.build-id .text 
   01     .note.gnu.build-id

As we can see above, gcc doesn’t try to set a non-executable stack by default for assembly files, but we can pass a flag to tell gcc what to do:

jesstess$ execstack -q test_gcc
? test_gcc
jesstess$ gcc -z execstack -o test_gcc_exec test.s -nostdlib
jesstess$ gcc -z noexecstack -o test_gcc_noexec test.s -nostdlib
jesstess$ execstack -q test_gcc_exec test_gcc_noexec 
X test_gcc_exec
- test_gcc_noexec

The situation with C source code is a bit different: gcc tacks a .note.GNU-stack section onto the end of C files by default.

We can verify this by stopping gcc‘s compilation of a bare-bones C file before running the assembler:

jesstess$ cat test.c
int main()
{
  return 0;
}
jesstess$ gcc -o test.i -S test.c
jesstess$ cat test.i
	.file	"test.c"
	.text
.globl main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	movq	%rsp, %rbp
	.cfi_offset 6, -16
	.cfi_def_cfa_register 6
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
	.section	.note.GNU-stack,"",@progbits

4. Toggle noexecstack on an executable

We can use execstack to toggle the behavior of an already-compiled executable:

jesstess$ gcc -o ctest test.c
jesstess$ execstack -q ctest
- ctest
jesstess$ execstack -s ctest; execstack -q ctest
X ctest
jesstess$ execstack -c ctest; execstack -q ctest
- ctest

5. When trampolines make an executable stack necessary

A gcc extension allows nested functions, which require an executable stack under certain conditions. To quote this blog post: “if you pass a local function (a) as a parameter to another function (b) from an outer calling function (c), then gcc makes that local function a trampoline that’s resolved at runtime, because AFAICS the function is on the stack.”

We can verify this with a short example:

jesstess$ cat trampoline.c 
int main() {
    int a = 1;
  
    int nested() {
        return a;
    }
    int (*fptr)() = nested;
  
    return fptr();
}
jesstess$ gcc -o trampoline trampoline.c
jesstess$ execstack -q trampoline
X trampoline
jesstess$ ./trampoline 
jesstess$ execstack -c trampoline
jesstess$ ./trampoline 
Segmentation fault

6. Finding binaries with an executable stack

scanelf, part of the pax-utils package, makes short work of identifying binaries that want an exectuable stack:

jesstess$ scanelf -lpeq
RWX --- ---  /usr/lib32/libSDL-1.2.so.0.11.3
RWX --- ---  /lib/klibc-EBLO2mlo7LXngcucphVUH-0CbT0.so
RWX --- ---  /usr/bin/grub-editenv
RWX --- ---  /usr/bin/grub-mkpasswd-pbkdf2
RWX --- ---  /usr/bin/grub-mklayout
RWX --- ---  /usr/bin/grub-menulst2cfg
RWX --- ---  /usr/bin/grub-mount
RWX --- ---  /usr/bin/grub-fstest
RWX --- ---  /usr/bin/grub-mkfont
RWX --- ---  /usr/bin/grub-mkrelpath
RWX --- ---  /usr/bin/grub-mkimage
RWX --- ---  /usr/bin/grub-script-check
RWX --- ---  /usr/sbin/grub-probe
RWX --- ---  /usr/sbin/grub-mkdevicemap
RWX --- ---  /usr/sbin/grub

The flags to scanelf say to:

  • -l: scan all directories listed in /etc/ld.so.conf
  • -p: scan all directories in your $PATH
  • -e: print GNU_STACK information
  • -q: only print data for binaries with ‘bad’ attributes
  • Let’s pick one reported binary to confirm:

    jesstess$ execstack /usr/sbin/grub
    X /usr/sbin/grub
    jesstess$ readelf -l /usr/sbin/grub | grep GNU_STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

PyCon 2012 poster: getting and retaining new contributors to open source projects

My poster at the PyCon 2012 poster session was on getting and retaining contributors to open source projects.

A short video of me summarizing the poster is at http://pyvideo.org/video/692/2-twisted-matrix-high-scores.

The full-sized 4′x6′ poster pdf is here.

The poster strives to start a dialog in 3 areas of open source community management:

  1. Providing a welcoming environment with clear contribution guidelines and opportunities for new contributors.
  2. Identifying where in the ticket lifecycle a project bottlenecks and loses potential contributors, and how to incentivize community members to work on those bottlenecks.
  3. Resources for beginning open source contributors.

I use the Twisted Matrix High scores list as an example of one strategy to incentivize community members to work on ticket bottlenecks.

I happily got a lot of traffic in the poster hall, with a lot of people sharing their community stories and checking out OpenHatch and Twisted as a result (one Twisted sprinter even said he came to our sprint because of the poster!)

I was was right next to Brian Curtin, who had posters on the PSF Sprints and Outreach and Education committees. He funneled people to me to talk about the Boston Python Workshop grant.

For more on the poster session, see the call for posterslist of posters, and the full PyCon 2012 video list.

PyCon 2012: 5K

I ran my first 5K at PyCon 2012. All proceeds from the event went to the the charities Autism Speaks, the American Cancer Society, and the Epilepsy Foundation.

An impressive 148 participants completed the 7am run. Jacob Kaplan-Moss and the other 5K organizers did a great job of keeping the event upbeat and encouraging newcomers. I hope to see more programming communities supporting and encouraging fitness through events like this.

Read more at the event page and see more photos on Flickr (thanks and credit to volunteer photographer Michael McHugh).

PyCon 2012 talk: Diversity in Practice

I gave a talk with Asheesh Laroia at PyCon 2012 called Diversity in practice: How the Boston Python user group grew to 1700 people and over 15% women.

The video can be viewed online at http://pyvideo.org/video/719/diversity-in-practice-how-the-boston-python-user. Thank you to the PyCon organizers for orchestrating the lightning-fast turnaround time on subtitling and publishing the talk videos.

The slides are available here.

The talk was very well-received, with a great Q&A and many follow-up contacts from folks interested in running outreach events in their communities. Praise from Glyph, a long-time supporter who is leaving Boston soon for San Francisco, was particularly touching. We benefited tremendously from our practice run with the Boston Python user group.

PyCon 2012 talk

Abstract:

How do you bring more women into programming communities with long-term, measurable results? In this talk we’ll analyze our successful effort, the Boston Python Workshop, which brought over 200 women into Boston’s Python community this year. We’ll talk about lessons learned running the workshop, the dramatic effect it has had on the local user group, and how to run a workshop in your city.