PATCH: Re: Problem with virtual memory rlimits

Marcus Meissner meissner at suse.de
Fri Mar 17 10:04:08 CST 2006


On Fri, Feb 24, 2006 at 02:12:46PM +0100, Marcus Meissner wrote:
> Hi,
> 
> I am having a problem with virtual ulimits/rlimits.
> 
> If you limit the virtual memory size using "ulimit -v 1400000" for
> instance, wine will only crash.
> 
> The problem is, that VIRTUAL_alloc_teb() tries to allocate a memory
> area within the acceptable userspace ... but it does so much mmap()s
> that it runs out of available mmap space before.
> 
> I was only able to reproduce this on AMD64 machines up to now, 
> which pass out memory starting from 0xf7fffffff somewhere.
> 
> Any clue how to solve this?

Got an idea...

It helps if the process is started with the ADDR_COMPAT_LAYOUT personality
flag set.

So if we are running without it, we can just set the personality and
execve ourselves.

Btw, this trick might even help execshield and avoid the need for the
preloader at all, but I do not have Fedora/Redhat here to test.

Ciao, Marcus

Changelog:
	Change to ADDR_COMPAT_LAYOUT personality to avoid problems
	with AMD64 memory layout and ulimits set.

Index: loader/preloader.c
===================================================================
RCS file: /home/wine/wine/loader/preloader.c,v
retrieving revision 1.20
diff -u -r1.20 preloader.c
--- loader/preloader.c	6 Feb 2006 13:35:58 -0000	1.20
+++ loader/preloader.c	17 Mar 2006 15:36:21 -0000
@@ -208,6 +208,14 @@
     return SYSCALL_RET(ret);
 }
 
+static inline int wld_personality( int perso )
+{
+    int ret;
+    __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
+                          : "=a" (ret) : "0" (SYS_personality), "r" (perso) );
+    return SYSCALL_RET(ret);
+}
+
 static inline ssize_t wld_read( int fd, void *buffer, size_t len )
 {
     int ret;
@@ -226,6 +234,14 @@
     return SYSCALL_RET(ret);
 }
 
+static inline int wld_execve( const char * path, char **argv, char ** envp )
+{
+    int ret;
+    __asm__ __volatile__( "pushl %%ebx; movl %2,%%ebx; int $0x80; popl %%ebx"
+                          : "=a" (ret) : "0" (SYS_execve), "r" (path), "c" (argv), "d" (envp) );
+    return SYSCALL_RET(ret);
+}
+
 static inline int wld_mprotect( const void *addr, size_t len, int prot )
 {
     int ret;
@@ -886,6 +902,7 @@
     ElfW(auxv_t) new_av[12], delete_av[3], *av;
     struct wld_link_map main_binary_map, ld_so_map;
     struct wine_preload_info **wine_main_preload_info;
+    unsigned int perso;
 
     pargc = *stack;
     argv = (char **)pargc + 1;
@@ -894,6 +911,14 @@
     /* skip over the parameters */
     p = argv + *pargc + 1;
 
+    perso = wld_personality(0xffffffff);
+    if (!(perso & 0x200000)) {
+	wld_personality(perso | 0x200000);
+    	wld_execve(argv[0],argv,p);
+	fatal_error( "Failed execve %s\n", argv[0] );
+	return NULL;
+    }
+
     /* skip over the environment */
     while (*p)
     {



More information about the wine-devel mailing list