Author: mturk Date: Fri Jun 19 06:48:37 2009 New Revision: 786391 URL: http://svn.apache.org/viewvc?rev=786391&view=rev Log: Check for SELinux and create double page mapped file if it is
Added: commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c (with props) Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecutableMemory.java commons/sandbox/runtime/trunk/src/main/native/Makefile.in commons/sandbox/runtime/trunk/src/main/native/configure commons/sandbox/runtime/trunk/src/main/native/os/unix/execmem.c commons/sandbox/runtime/trunk/src/main/native/os/win32/execmem.c commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestMemory.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecutableMemory.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecutableMemory.java?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecutableMemory.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/ExecutableMemory.java Fri Jun 19 06:48:37 2009 @@ -33,6 +33,8 @@ } + public static native Pointer malloc0(long size) + throws OutOfMemoryError; /** * Allocates {...@code size} bytes and returns a {...@link Pointer} * to the allocated memory. The memory has executable permissions. @@ -43,7 +45,32 @@ * @throws OutOfMemoryError if memory cannot be allocated. * @throws IllegalArgumentException if the size is less then {...@code 1}. */ - public static native Pointer malloc(long size) - throws OutOfMemoryError, IllegalArgumentException; + public static Pointer malloc(long size) + throws OutOfMemoryError, IllegalArgumentException + { + if (size < 1L) + throw new IllegalArgumentException(); + + return malloc0(size); + } + + public static native Pointer exec0(Pointer src); + /** + * Returns the executable {...@code page} bytes of previously allocated + * executable memory and returns a {...@link Pointer}, + * + * @return new {...@link Pointer} containing executable memory area. + * + * @throws NullPointerException if {...@code src} is {...@code null}. + */ + public static Pointer getExecutablePage(Pointer src) + throws NullPointerException + { + if (src == null || src.IsNull()) + throw new NullPointerException(); + synchronized (ExecutableMemory.class) { + return exec0(src); + } + } } Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Fri Jun 19 06:48:37 2009 @@ -91,7 +91,6 @@ $(SRCDIR)/modules/network/ssl/openssl.$(OBJ) LINUX_OBJS= \ - $(SRCDIR)/os/unix/execmem.$(OBJ) \ $(SRCDIR)/os/unix/file.$(OBJ) \ $(SRCDIR)/os/unix/main.$(OBJ) \ $(SRCDIR)/os/unix/group.$(OBJ) \ @@ -99,6 +98,7 @@ $(SRCDIR)/os/unix/syslog.$(OBJ) \ $(SRCDIR)/os/unix/uuid.$(OBJ) \ $(SRCDIR)/os/unix/uutils.$(OBJ) \ + $(SRCDIR)/os/linux/execmem.$(OBJ) \ $(SRCDIR)/os/linux/platform.$(OBJ) \ $(SRCDIR)/os/linux/pgroup.$(OBJ) \ $(SRCDIR)/os/linux/puser.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/configure URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/configure?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/configure (original) +++ commons/sandbox/runtime/trunk/src/main/native/configure Fri Jun 19 06:48:37 2009 @@ -677,6 +677,20 @@ varadds ldflags "-laio" fi +if [ ".$host" = ".linux" ]; then + have_selinux=`have_include selinux/selinux` + if [ ".$have_selinux" = ".1" ]; then + ok=`have_library selinux` + if [ ".$ok" = ".1" ]; then + varadds ldflags "-lselinux" + else + have_selinux=0 + fi + fi +else + have_selinux=0 +fi + # Generate configuration header file # cat > $topdir/include/ccconfig.h << EOF @@ -697,6 +711,7 @@ #define HAVE_LIBAIO_H $have_libaio #define HAVE_UUID_UUID_H $have_uuid_uuid #define HAVE_OPENSSL $have_openssl +#define HAVE_SELINUX_H $have_selinux #define HAS_BIG_ENDIAN $bige #define HAVE_UNISTD_H `have_include unistd` @@ -806,9 +821,9 @@ -e "s;=...@rcflags@;=$rcflags;g" \ -e "s;=...@includes@;=$includes;g" \ -e "s;=...@name@;=$name;g" \ - -e "s;=...@vmajor@;$vmajor;g" \ - -e "s;=...@vminor@;$vminor;g" \ - -e "s;=...@vpatch@;$vpatch;g" \ + -e "s;=...@vmajor@;=$vmajor;g" \ + -e "s;=...@vminor@;=$vminor;g" \ + -e "s;=...@vpatch@;=$vpatch;g" \ -e "s;@platform@;$platform;g" \ -e "s;@testobjs@;$testobjs;g" \ -e "s;@modules@;$modules;g" \ Added: commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c?rev=786391&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c Fri Jun 19 06:48:37 2009 @@ -0,0 +1,177 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "acr.h" +#include "acr_private.h" +#include "acr_arch.h" +#include "acr_memory.h" +#include "acr_pointer.h" +#include "acr_error.h" + +#include <sys/mman.h> +#if HAVE_SELINUX_H +#include <selinux/selinux.h> +#else +#define is_selinux_enabled() 0 +#endif + +extern acr_size_t acr_page_size; +static int acr_exec_file = -1; +#define EXEC_PAGE_OFF(M, L) *((ptrdiff_t *)((char *)(M) + (L) - sizeof(ptrdiff_t))) +/** + * Linux executable memory functions + * + */ +static int execmem_pointer_cleanup(void *mem, size_t len) +{ + if (mem && len) { + ptrdiff_t p = EXEC_PAGE_OFF(mem, len); + munmap(mem, len); + if (p) { + munmap((void *)p, len); + } + return 0; + } + else { + return ACR_EISNULL; + } +} + +static const char *tmp_envs[] = { + "TMP", + "TEMP", + "TMPDIR", + "HOME", + NULL +}; + +static const char *tmp_path[] = { + "/tmp", + "/var/tmp", + NULL +}; + +static int exec_tempfile() +{ + char path[PATH_MAX]; + int i = 0; + int fd; + while (tmp_path[i]) { + strcpy(path, tmp_path[i++]); + strcat(path, "/acXXXXXX"); + if ((fd = mkstemp(path)) != -1) { + unlink(path); + return fd; + } + } + i = 0; + while (tmp_envs[i]) { + char *es = getenv(tmp_envs[i++]); + if (es) { + strcpy(path, es); + strcat(path, "/mmXXXXXX"); + if ((fd = mkstemp(path)) != -1) { + unlink(path); + return fd; + } + } + } + return -1; +} + + +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, malloc0)(ACR_JNISTDARGS, + jlong siz) +{ + jobject ptr = NULL; + void *mmw = NULL; + void *mmx = NULL; + acr_size_t ass = (acr_size_t)ACR_ALIGN(siz + sizeof(ptrdiff_t), acr_page_size); + + UNREFERENCED_O; +#if HAVE_SELINUX_H + if (acr_exec_file == -1 && !is_selinux_enabled()) { + mmw = mmap(0, ass, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + else { + if (acr_exec_file == -1) { + acr_exec_file = exec_tempfile(); + if (acr_exec_file == -1) { + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, + ACR_GET_OS_ERROR()); + return NULL; + } + } + ftruncate(acr_exec_file, ass); + mmw = mmap(NULL, ass, PROT_READ | PROT_WRITE, + MAP_SHARED, acr_exec_file, 0); + if (mmw == NULL) { + int se = ACR_GET_OS_ERROR(); + close(acr_exec_file); + acr_exec_file = -1; + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, se); + return NULL; + } + mmx = mmap(NULL, ass, PROT_READ | PROT_EXEC, + MAP_SHARED, acr_exec_file, 0); + if (mmx == NULL) { + int se = ACR_GET_OS_ERROR(); + munmap(mmw, ass); + close(acr_exec_file); + acr_exec_file = -1; + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, se); + return NULL; + } + } +#else + mmw = mmap(0, ass, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#endif + if (mmw) { + EXEC_PAGE_OFF(mmw, ass) = (ptrdiff_t)mmx; + /* Create the Pointer class with default cleanup. + */ + ptr = ACR_PointerCreate(_E, mmw, ass, execmem_pointer_cleanup); + if (!ptr) { + munmap(mmw, ass); + if (mmx) + munmap(mmx, ass); + } + } + else + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, ACR_GET_OS_ERROR()); + + return ptr; +} + +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, exec0)(ACR_JNISTDARGS, + jobject src) +{ + jobject po; + size_t sl; + void *dp; + char *sp = (char *)ACR_PointerGet(_E, src, &sl); + + UNREFERENCED_O; + + dp = (void *)(EXEC_PAGE_OFF(sp, sl)); + if (dp) + po = ACR_PointerCreate(_E, dp, sl, NULL); + else + po = ACR_PointerCreate(_E, sp, sl, NULL); + return po; +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/linux/execmem.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/execmem.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/execmem.c?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/execmem.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/execmem.c Fri Jun 19 06:48:37 2009 @@ -53,21 +53,19 @@ } } -ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, malloc)(ACR_JNISTDARGS, - jlong siz) +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, malloc0)(ACR_JNISTDARGS, + jlong siz) { jobject ptr = NULL; void *mem; acr_size_t ass = (acr_size_t)ACR_ALIGN(siz, acr_page_size); UNREFERENCED_O; - if (siz < 1L) { - ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINVAL, 0); - return NULL; - } #ifdef ACR_USE_MMAP mem = mmap(0, ass, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem == NULL) + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, ACR_GET_OS_ERROR()); #else mem = ACR_Malloc(_E, THROW_NMARK, ass); #endif @@ -85,3 +83,13 @@ } return ptr; } + +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, exec0)(ACR_JNISTDARGS, + jobject src) +{ + size_t sl; + void *sp = ACR_PointerGet(_E, src, &sl); + + UNREFERENCED_O; + return ACR_PointerCreate(_E, sp, sl, NULL); +} Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/execmem.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/execmem.c?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/execmem.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/execmem.c Fri Jun 19 06:48:37 2009 @@ -37,18 +37,14 @@ } } -ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, malloc)(ACR_JNISTDARGS, - jlong siz) +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, malloc0)(ACR_JNISTDARGS, + jlong siz) { jobject ptr = NULL; void *mem; acr_size_t ass = (acr_size_t)ACR_ALIGN(siz, acr_page_size); UNREFERENCED_O; - if (siz < 1L) { - ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINVAL, 0); - return NULL; - } mem = VirtualAlloc(NULL, ass, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); @@ -60,5 +56,17 @@ VirtualFree(mem, 0, MEM_RELEASE); } } + else + ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ENOMEM, ACR_GET_OS_ERROR()); return ptr; } + +ACR_JNI_EXPORT_DECLARE(jobject, ExecutableMemory, exec0)(ACR_JNISTDARGS, + jobject src) +{ + size_t sl; + void *sp = ACR_PointerGet(_E, src, &sl); + + UNREFERENCED_O; + return ACR_PointerCreate(_E, sp, sl, NULL); +} Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestMemory.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestMemory.java?rev=786391&r1=786390&r2=786391&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestMemory.java (original) +++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestMemory.java Fri Jun 19 06:48:37 2009 @@ -110,6 +110,18 @@ p.free(); } + public void testExecutableExec() + throws Throwable + { + Pointer w = ExecutableMemory.malloc(1000); + assertNotNull("ExecutableWritePointer", w); + w.poke(999, 23); + Pointer x = ExecutableMemory.getExecutablePage(w); + assertNotNull("ExecutableExecPointer", x); + assertEquals("Value", 23, x.peek(999)); + w.free(); + } + public void testSlice() throws Throwable { @@ -191,9 +203,12 @@ assertNotNull("Array", b); try { char[] c = Memory.toCharArray(p, 0, 501); - fail("Missing IndexOutOfBoundsException"); + fail("Exception not thrown"); } catch (IndexOutOfBoundsException ix) { // Succedded. + } catch (Exception ex) { + // Succedded. + fail("Missing IndexOutOfBoundsException"); } p.free(); }