tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Tests requiring MD hooks
Hi list,
(sorry to cross-post toolchain and userlevel, I don't know where
questions for ATF tests/ should go)
We already have some tests covering read/write permission under
lib/libc/sys/t_mprotect, so I started to write code for the --x counterpart.
That seems to be a bit tricky to write in a portable way: testing --x
right in memory pages requires to put/copy some payload in a page and
call it. I battled with GCC for a few hours trying to find a way to make
this in a MI way, and finally gave up and move to using "pure assembly"
code; neither volatile variables around C functions, nor mixing inline
assembly with C blocks makes it possible to "automagically" detect
beginning/end marker of a function code.
Attached is a proposal for the --x mprotect case; as I am on a route to
test other parts of memory too (like non-executable stack), I'd like to
have a trivial return_one() shellcode and expose it publicly. Although
the shellcode is not really libc-related, I added the i386/amd64 ones
under tests/lib/libc/arch/, with the associated header available under
tests/lib/common/exec_prot.h.
Only i386 and amd64 payloads are currently implemented. To make the test
a bit more helpful, all architectures are expected to inform the caller
(via exec_prot_support) whether they support --x rights or not.
Comments on the patch are welcomed, especially the placement of files.
tests/ are not big consumers of MD hooks currently, I'd like to have
clear directions regarding cases that do not really belong anywhere. For
example, non-executable stack tests are not really linked with either
libc or csu (perhaps crt?), yet I have to know where they should
eventually go.
Same goes for tests/lib/libc/arch vs tests/lib/arch/ for MD hooks. It's
hard to figure out a way to organize tests while remaining consistent
with current src/ layout.
Thanks!
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
Index: tests/lib/libc/sys/Makefile
===================================================================
RCS file: /cvsroot/src/tests/lib/libc/sys/Makefile,v
retrieving revision 1.6
diff -u -p -u -p -r1.6 Makefile
--- tests/lib/libc/sys/Makefile 7 Jul 2011 19:29:58 -0000 1.6
+++ tests/lib/libc/sys/Makefile 11 Jul 2011 01:08:21 -0000
@@ -4,6 +4,15 @@ MKMAN= no
.include <bsd.own.mk>
+.if exists(${.CURDIR}/../arch/${MACHINE_CPU})
+ARCHDIR= ${.CURDIR}/../arch/${MACHINE_CPU}
+.PATH: ${ARCHDIR}
+.else
+.BEGIN:
+ @echo no ARCHDIR for ${MACHINE_CPU}
+ @false
+.endif
+
TESTSDIR= ${TESTSBASE}/lib/libc/sys
TESTS_C+= t_access
@@ -41,6 +50,8 @@ TESTS_C+= t_truncate
TESTS_C+= t_umask
TESTS_C+= t_unlink
+SRCS.t_mprotect= t_mprotect.c misc.c return_one.S
+
LDADD.t_getpid+= -lpthread
LDADD.t_timer_create+= -lpthread
Index: tests/lib/libc/sys/t_mprotect.c
===================================================================
RCS file: /cvsroot/src/tests/lib/libc/sys/t_mprotect.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 t_mprotect.c
--- tests/lib/libc/sys/t_mprotect.c 7 Jul 2011 06:57:54 -0000 1.1
+++ tests/lib/libc/sys/t_mprotect.c 11 Jul 2011 01:08:21 -0000
@@ -44,6 +44,8 @@ __RCSID("$NetBSD: t_mprotect.c,v 1.1 201
#include <atf-c.h>
+#include "../../common/exec_prot.h"
+
static long page = 0;
static int pax_global = -1;
static int pax_enabled = -1;
@@ -158,10 +160,91 @@ ATF_TC_BODY(mprotect_err, tc)
ATF_REQUIRE(errno == EINVAL);
}
+ATF_TC(mprotect_exec);
+ATF_TC_HEAD(mprotect_exec, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test mprotect(2) executable space protections");
+}
+
+/*
+ * Trivial function -- should fit into a page
+ */
+ATF_TC_BODY(mprotect_exec, tc)
+{
+ pid_t pid;
+ void *map;
+ int sta, xp_support;
+
+ xp_support = exec_prot_support();
+
+ switch (xp_support) {
+ case NOTIMPL:
+ atf_tc_skip(
+ "Execute protection callback check not implemented");
+ break;
+ case NO_XP:
+ atf_tc_skip(
+ "Host does not support executable space protection");
+ break;
+ case PARTIAL_XP: case PERPAGE_XP: default:
+ break;
+ }
+
+ /*
+ * Map a page read/write and copy a trivial assembly function inside.
+ * We will then change the mapping rights:
+ * - first by setting the execution right, and check that we can
+ * call the code found in the allocated page.
+ * - second by removing the execution right. This should generate
+ * a SIGSEGV on architectures that can enforce --x permissions.
+ */
+
+ map = mmap(NULL, page, PROT_WRITE|PROT_READ, MAP_ANON, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ memcpy(map, (void *)return_one,
+ (uintptr_t)return_one_end - (uintptr_t)return_one);
+
+ /* give r-x rights then call code in page */
+ ATF_REQUIRE(mprotect(map, page, PROT_EXEC|PROT_READ) == 0);
+ ATF_REQUIRE(((int (*)(void))map)() == 1);
+
+ /* remove --x right */
+ ATF_REQUIRE(mprotect(map, page, PROT_READ) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ ATF_REQUIRE(signal(SIGSEGV, sighandler) != SIG_ERR);
+ ATF_CHECK(((int (*)(void))map)() == 1);
+ _exit(0);
+ }
+
+ (void)wait(&sta);
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+
+ switch (xp_support) {
+ case PARTIAL_XP:
+ /* Partial protection might fail: indicate it */
+ ATF_CHECK_MSG(WEXITSTATUS(sta) == SIGSEGV,
+ "Host only supports partial executable space protection");
+ break;
+ case PERPAGE_XP: default:
+ /* Per-page --x protection should not fail */
+ ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
+ break;
+ }
+
+ ATF_REQUIRE(munmap(map, page) == 0);
+}
+
ATF_TC(mprotect_pax);
ATF_TC_HEAD(mprotect_pax, tc)
{
- atf_tc_set_md_var(tc, "descr", "PaX restrictions and mprotect(2),");
+ atf_tc_set_md_var(tc, "descr", "PaX restrictions and mprotect(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
@@ -224,7 +307,7 @@ out:
ATF_TC(mprotect_write);
ATF_TC_HEAD(mprotect_write, tc)
{
- atf_tc_set_md_var(tc, "descr", "Test mprotect(2) protections");
+ atf_tc_set_md_var(tc, "descr", "Test mprotect(2) write protections");
}
ATF_TC_BODY(mprotect_write, tc)
@@ -266,6 +349,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, mprotect_access);
ATF_TP_ADD_TC(tp, mprotect_err);
+ ATF_TP_ADD_TC(tp, mprotect_exec);
ATF_TP_ADD_TC(tp, mprotect_pax);
ATF_TP_ADD_TC(tp, mprotect_write);
--- /dev/null 2011-07-11 02:58:19.000000000 +0200
+++ tests/lib/common/exec_prot.h 2011-07-10 20:39:07.000000000 +0200
@@ -0,0 +1,61 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jean-Yves Migeon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TESTS_H_FUNC_H_
+#define _TESTS_H_FUNC_H_
+
+/*
+ * Prototype definitions of external helper functions for executable
+ * mapping tests.
+ */
+
+/*
+ * Trivial MD shellcode that justs returns 1.
+ */
+int return_one(void); /* begin marker -- shellcode entry */
+int return_one_end(void); /* end marker */
+
+/*
+ * MD callback to verify whether host offers executable space protection.
+ * Returns execute protection level.
+ */
+int exec_prot_support(void);
+
+/* execute protection level */
+enum {
+ NOTIMPL = -1, /* callback not implemented */
+ NO_XP, /* no execute protection */
+ PERPAGE_XP, /* per-page execute protection */
+ PARTIAL_XP /* partial execute protection. Depending on where the
+ page is located in virtual memory, executable space
+ protection may be enforced or not. */
+};
+#endif
--- /dev/null 2011-07-11 02:58:19.000000000 +0200
+++ tests/lib/libc/arch/i386/misc.c 2011-07-11 02:54:06.000000000 +0200
@@ -0,0 +1,65 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jean-Yves Migeon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <stdlib.h>
+#include <sys/sysctl.h>
+
+#include "../../../common/exec_prot.h"
+
+/*
+ * Support for executable space protection has always been erratic under i386.
+ * Originally IA-32 can't do per-page execute permission, so it is
+ * implemented using different executable segments for %cs (code segment).
+ * This only allows coarse grained protection, especially when memory starts
+ * being fragmented.
+ * Later, PAE was introduced together with a NX/XD bit in the page table
+ * entry to offer per-page permission.
+ */
+int
+exec_prot_support(void)
+{
+ int pae;
+ size_t pae_len = sizeof(pae);
+
+ if (sysctlbyname("machdep.pae", &pae, &pae_len, NULL, 0) == -1)
+ return PARTIAL_XP;
+
+ if (pae == 1) {
+ if (system("cpuctl identify 0 | grep -q NOX") == 0 ||
+ system("cpuctl identify 0 | grep -q XD") == 0)
+ return PERPAGE_XP;
+ }
+
+ return PARTIAL_XP;
+}
--- /dev/null 2011-07-11 02:58:19.000000000 +0200
+++ tests/lib/libc/arch/i386/return_one.S 2011-07-11 02:45:38.000000000
+0200
@@ -0,0 +1,38 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jean-Yves Migeon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+RCSID("$NetBSD$");
+
+_ENTRY(return_one)
+ movl $0x1,%eax
+ ret
+LABEL(return_one_end)
--- /dev/null 2011-07-11 02:58:19.000000000 +0200
+++ tests/lib/libc/arch/x86_64/misc.c 2011-07-10 21:25:24.000000000 +0200
@@ -0,0 +1,50 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jean-Yves Migeon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include <stdlib.h>
+
+#include "../../../common/exec_prot.h"
+
+/*
+ * When the NX/XD flag is present, the protection should be enabled.
+ */
+int
+exec_prot_support(void)
+{
+ if (system("cpuctl identify 0 | grep -q NOX") == 0 ||
+ system("cpuctl identify 0 | grep -q XD") == 0)
+ return PERPAGE_XP;
+
+ return NO_XP;
+}
--- /dev/null 2011-07-11 02:58:19.000000000 +0200
+++ tests/lib/libc/arch/x86_64/return_one.S 2011-07-11 02:45:45.000000000
+0200
@@ -0,0 +1,38 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jean-Yves Migeon.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+RCSID("$NetBSD$");
+
+_ENTRY(return_one)
+ movq $0x1, %rax
+ retq
+LABEL(return_one_end)
Home |
Main Index |
Thread Index |
Old Index