Skip to content

Instantly share code, notes, and snippets.

@markmont
Last active August 2, 2017 15:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markmont/b5f1ee6b4c1c7a68b085bb3aae96e3b9 to your computer and use it in GitHub Desktop.
Save markmont/b5f1ee6b4c1c7a68b085bb3aae96e3b9 to your computer and use it in GitHub Desktop.
W^X test case using temporary file that is mmap()'d twice
#
# Run under Fedora 26 with SELinux enabled
#
# /tmp must not be mounted noexec for this to work.
#
[markmont@f26docker examples]$ sudo setsebool selinuxuser_execstack=off deny_execmem=on
[sudo] password for markmont:
[markmont@f26docker examples]$ gcc -o m2 m2.c
[markmont@f26docker examples]$ ./m2
(dynamic) code returned 42
[markmont@f26docker examples]$
/* W^X test case based on
* https://www.akkadia.org/drepper/selinux-mem.html
* and
* https://stackoverflow.com/questions/28015876/what-do-i-have-to-do-to-execute-code-in-data-areas-segment-protection
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h> /* mmap(), mprotect() */
static uint8_t code[] = {
0xB8,0x2A,0x00,0x00,0x00, /* mov eax,0x2a */
0xC3, /* ret */
};
int main(void)
{
const size_t len = sizeof(code);
char tmpfname[] = "/tmp/execmemXXXXXX";
int fd = mkstemp(tmpfname);
if (fd == -1) {
perror("can't create execmem file");
return 1;
}
if (unlink(tmpfname) == -1) {
perror("can't unlink execmem file");
return 1;
}
if (ftruncate (fd, 1000) == -1) {
perror("can't truncate execmem file");
return 1;
}
void *writep = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (writep==MAP_FAILED) {
fprintf(stderr, "mmap() writep failed\n");
return 2;
}
void *execp = mmap(NULL, 4096, PROT_READ|PROT_EXEC, MAP_SHARED, fd, 0);
if (execp==MAP_FAILED) {
fprintf(stderr, "mmap() execp failed\n");
return 2;
}
/* Copy it in (still not executable) */
memcpy(writep, code, len);
/* Go! */
int (*func)(void) = execp;
printf("(dynamic) code returned %d\n", func());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment