.wine dir on noexec part fails even if exes/dlls are links

Questions about Wine on Linux
Locked
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

.wine dir on noexec part fails even if exes/dlls are links

Post by opensense »

Hello,
I'm finding that some programs will not run if the .wine config directory is on a partition which is mounted noexec, even if nothing under .wine actually needs to be executed. I have tried moving drive_c (which holds all the actual executables) onto an exec partition and linking it in, but certain programs still wont run and I get these errors:
err:virtual:map_file_into_view failed to set 00000007 protection on file map, noexec filesystem?

Is there any way to store the .wine config dir on a noexec partition? I dug into the source and see the relevant sections in dlls/ntdll/virtual.c and found some old discussions and patches about noexec filesystems but can't find a way to force it to run. I dabble a little in c but don't understand enough to know what all the exec/noexec protections are about. I have found past statements such as ".wine needs to be on an exec partition, that's the way it has always been" - but is there a legitimate reason for that? Is there no workaround?

More background:
I manage software installations for public libraries and some of them want some windows apps that run under wine. To ensure that we have control over what users can run on the computers, we don't want the users to be able to write to any location that can execute code. So /home, /tmp, etc. are mounted noexec. Instead of .wine being noexec, it would instead be OK if .wine was read-only with user-writable files underneath, but that doesn't work as several files under there deleted and recreated by wine. The specific app I'm having trouble with at the moment is pipelight - I know that is using a patched version of wine but as far as I can tell no one has ever successfully stored .wine on a noexec partition with any version of wine.
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

in ./dlls/ntdll/virtual.c
I disabled the mmap that gives the error (changed 2nd/3rd line below), and then the program runs. Does anyone know what the practical consequence of that is?

/* only try mmap if media is not removable (or if we require write access) */
/* mpp if ( !removable || shared_write) */
if ( 0 )
{
int flags = MAP_FIXED | (shared_write ? MAP_SHARED : MAP_PRIVATE);

if (mmap( (char *)view->base + start, size, prot, flags, fd, offset ) != (void *)-1)
goto done;

if ((errno == EPERM) && (prot & PROT_EXEC))
ERR( "failed to set %08x protection on file map, noexec filesystem?\n", prot );
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

sorry, I guess this should have been in the Linux sub-forum - if an admin could move it that would be great.
oiaohm
Level 8
Level 8
Posts: 1020
Joined: Fri Feb 29, 2008 2:54 am

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by oiaohm »

opensense wine is not simple. There will be a performance hit removing mapping.

opensense you do really need to find out why PROT_EXEC 0x4 /* page can be executed */ is being set on that mmap.

static BOOL force_exec_prot; /* whether to force PROT_EXEC on all PROT_READ mmaps */ State of this could be interesting as you say it only some applications.

Now in future do include the function you are messing with. Sometimes they are duplications inside a c file.

Code: Select all

 /***********************************************************************
  *           map_file_into_view
  *
  * Wrapper for mmap() to map a file into a view, falling back to read if mmap fails.
  * The csVirtual section must be held by caller.
  */
 static NTSTATUS map_file_into_view( struct file_view *view, int fd, size_t start, size_t size,
                                     off_t offset, unsigned int vprot, BOOL removable )
Notice the vprot This is the bit that could be containing VPROT_EXEC that ends up resulting in PROT_EXEC set after VIRTUAL_GetUnixProt converts it.

Also there is a there is a nice second path to cause it to set.

Code: Select all

     if (force_exec_prot && !(vprot & VPROT_NOEXEC) && (vprot & VPROT_READ))
     {
         TRACE( "forcing exec permission on mapping %p-%p\n",
                (char *)view->base + start, (char *)view->base + start + size - 1 );
         prot |= PROT_EXEC;
     } 
WINEDEBUG=+ntdll would be a really good idea.

opensense I would say the patch you have done is not a really great idea. But I would also suspect wine is also doing something really badly wrong from a security point of view.

force_exec_prot/ VIRTUAL_SetForceExec is very hacky.

Without a log of what is going wrong I cannot really recommend much. opensense if it a case that force_exec_prot is being turned on and it really not required on. This would be a very much better fix than removing mmapping. In fact force_exec_prot flag really should not effect particular files like the .reg files but currently it does.

Wine is basically forbidding creating executable memory space in ram from non executable disc storage. This is a perfectly correct thing todo. The problem I have is wine setting stuff executable that it should not be so causing your failures.

Yes due to force_exec_prot being super hacky it most likely doing the wrong things. I now need logs to confirm if its force_exec_prot being defective in this case.

Problem is I am not an advanced developer. Fixing force_exec_prot would involve creating some logic checks. Like don't work on .reg files in wineprefix directory.

opensense where wine stops is only part of the story. You need to know why it got there in the first place to fix it.

WINEDEBUG=+ntdll would be a really good idea and possible other channels will be required to work out exactly what is going wrong.

opensense no PROT_EXEC set no error. So that is what we have to solve. Is why PROT_EXEC is set and if it really required to be set.(I highly suspect the answer is it set incorrectly) If it set incorrectly its a security bug in wine.
oiaohm
Level 8
Level 8
Posts: 1020
Joined: Fri Feb 29, 2008 2:54 am

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by oiaohm »

opensense if its force_exec_prot doing the wrong thing VPROT_NOEXEC will need to be added in a few places to prevent force_exec_prot from doing the wrong thing.

This is the problem the error will have happened a decent way back before it stops.
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

thanks a lot oiaohm, I am now going to try to digging into things further and try setting VPROT_NOEXEC. Yes the source code change I made is probably bad, it was just a test. Even a 50% performance hit might be OK, but security cannot be compromised.

I reran using stock wine 1.7.8 compiled from source (as opposed to with pipelight patches) and get the same issue, here are some WINEDEBUG=+ntdll logs with /home mounted exec vs. noexec
http://s2.groovix.net/tmp/wine-stock-17 ... noexec.log
http://s2.groovix.net/tmp/wine-stock-17 ... g-exec.log
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

I'm making some progress digging through the code but I'm in way over my head. I found some key debug info by also debugging with +virtual and even more will +all:
http://s2.groovix.net/tmp/wine-stock-17 ... noexec.log
http://s2.groovix.net/tmp/wine-stock-17 ... g-exec.log
http://s2.groovix.net/tmp/wine-stock-17 ... xec.log.gz
http://s2.groovix.net/tmp/wine-stock-17 ... xec.log.gz

I'm wondering if these lines from the full log are relevant:
928.646:0009:warn:module:alloc_module disabling no-exec because of L"pluginloader.exe"
929.894:0009:warn:module:alloc_module disabling no-exec because of L"WININET.dll"

Is there something about those specific executables (not NX compatible?) that requires them to use executable memory? Even if that is so, those are stored on an executable partition so I'm not sure what the problem is.

in dlls/ntdll/loader.c the warning is generated here:

Code: Select all

    if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
    {
        ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
        WARN( "disabling no-exec because of %s\n", debugstr_w(wm->ldr.BaseDllName.Buffer) );
        NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
    }

and in dlls/ntdll/virtual.c:
force_exec_prot
is set by:
VIRTUAL_SetForceExec ( BOOL enable )
which is called in dlls/ntdll/process.c and the value of enable is determined here:

Code: Select all

switch (*(ULONG *)ProcessInformation & (MEM_EXECUTE_OPTION_ENABLE|MEM_EXECUTE_OPTION_DISABLE))
            {
            case MEM_EXECUTE_OPTION_ENABLE:
                enable = TRUE;
                break;
            case MEM_EXECUTE_OPTION_DISABLE:
                enable = FALSE;
                break;
            default:
                return STATUS_INVALID_PARAMETER;
            }
            execute_flags = *(ULONG *)ProcessInformation;
            VIRTUAL_SetForceExec( enable );

I'm going to try overriding some values and see what happens...
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

Things seem to work ok if I comment out this section in dlls/ntdll/loader.c :

Code: Select all

/*
    if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
    {
        ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
        WARN( "disabling no-exec because of %s\n", debugstr_w(wm->ldr.BaseDllName.Buffer) );
        NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
    }
*/
Doing it this way should still allow memory mapping unlike my previous hack. Is there any practical downside to commenting that section out?

I found this:
http://www.winehq.org/pipermail/wine-de ... 77576.html
but I'm still confused. The way I read things, if the dll is not nx compatible, nx support is disabled and execute permission on data pages should be forced. Then why is wine refusing to execute in this circumstance? For most programs, wine happily executes files on a noexec partition. It seems to be doing the opposite of what it should.

So in short, wine does not allow some programs to run if .wine is on a noexec partition, even if the programs are on an exec partition. And on the flip side, wine lets most programs run even if they are on a noexec partition. I think these are two separate issues that have never been addressed since very few people use noexec. Should bugs be filed or will the response be: "that's just the way it is" and "no one uses noexec anyways" ?

I'm also considering just letting /home be mounted exec, because now I've realized that wine allows most programs to be executed from a noexec partition. I guess that's not too surprising since its kind of an interpreter like bash, perl, etc. But it would still be better if it prevented running executables from noexec partitions. I know noexec isn't perfect, but some protections are better than none. I guess those who want the benefits of wine might have to accept the additional security risk.
oiaohm
Level 8
Level 8
Posts: 1020
Joined: Fri Feb 29, 2008 2:54 am

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by oiaohm »

opensense really what you have found tells me we have a Sledge hammer putting in a tack and effectively putting a huge whole in the wall.
Doing it this way should still allow memory mapping unlike my previous hack. Is there any practical downside to commenting that section out?
If the application is truly coded NX incompatible it will fail. That will be the downside. Of course a lot of applications without IMAGE_DLLCHARACTERISTICS_NX_COMPAT flag are NX compatible in there coding. So this does raise the question on security should we have a force NX_COMPAT option.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Windows it self does include in boot-loader nx [Optin |OptOut | AlwaysOn |AlwaysOff] boot option. Yes the nx AlwaysOn and OptOut makes windows complete operate how your code delete does it does force the NX_COMPAT missing flag to be disregarded.

opensense you could call the area you deleting a bug because that should be a registry key or something controlling what it does. Most likely on a per application base to be ACT compadible.
Should bugs be filed
This here I would say is a case where a bug can be filed. Why you have example of wine not replicating windows so blocking application from working when they should run.

Code: Select all

  if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
    {
        ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
        WARN( "disabling no-exec because of %s\n", debugstr_w(wm->ldr.BaseDllName.Buffer) );
        NtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
    }
opensense I am putting this in bold. So you don't miss it this time. Include what C function you are messing with. I don't want to have to dig out source code each time and I don't want to have the case of thinking you have edited X function when you have changes Y. dlls/ntdll/loader.c contains many functions

This section is a incorrectly coded hack. There need to be more logic. I do not truly have a usage case(I need a usage case to open bug it against rules for me to open bugs for other users). But I will post a comment to a bug over this pointing out implementation error. Its only right in opt-in and AlwaysOff mode under windows. Outside those modes applications are required to call NtSetInformationProcess themselves.

I do have bad news for you with drive_c set exec and .wine set noexec for there to be a failure the likes of .reg or something in .wine has to be opened with a exec flag set that should not be as well.

Reading the log gives me a idea. "\\??\\C:\\windows\\system32\\wininet.dll" Particular reading this path.

Would you mind trying something warped. WINEPREFIX/dosdevices mind placing this in a partition that is exec. dosdevices directory itself can be a link and it work. Need to do this to see if we have path logic problem. C: is defines in dosdevices. Really where C: is pointing should define the noexec or exec status. If it turns out that dosdevices directory is defining the exec/noexec status we have a path logic fault somewhere in wine. If this kinda fixes it we have a different bug as well. Lot more of a pain to find.
opensense
Level 1
Level 1
Posts: 7
Joined: Thu Dec 19, 2013 8:40 pm

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by opensense »

Sorry, the section I commented out was in the WINE_MODREF function of dlls/ntdll/loader.c

Code: Select all

/*************************************************************************
 *              alloc_module
 *
 * Allocate a WINE_MODREF structure and add it to the process list
 * The loader_section must be locked while calling this function.
 */
static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )

Actually the first thing I tried right after linking in drive_c from an exec partition was linking in dosdevices too and then all the contents of .wine, that didn't change the behavior. I haven't found the code that looks at the linux filesystem to determine executability or not, but I agree that there is probably a path logic problem where it is looking at the location of .wine and failing to realize that files under there might not be on the same partition due to links.

If I have time I'm going to try a few more experiments over the next week to try to understand this a little more before I file a bug. Please let me know if there's anything else I can document or try to help understand this.
oiaohm
Level 8
Level 8
Posts: 1020
Joined: Fri Feb 29, 2008 2:54 am

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by oiaohm »

opensense if going from what is left only files I can think of in wineprefix that are not in dosdevices or drive_c is the .reg files of the registry. But those should not be mapping with exec enabled. Should not be and are unfortunately be two different things.

IMAGE_DLLCHARACTERISTICS_NX_COMPAT thing is a bug in its own right particularly when you consider Windows it self either by bootloader or ACT(application compatibility toolkit) can override applications missing the flag to act as if it was enabled. For security personally I would set it the other way. NX_COMPAT presumed enabled unless application fails.
static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )

you miss read this. The function name is alloc_module in dlls/ntdll/loader.c

So a bug over alloc_module can be submitted now. Finding the exact cause of why extra stuff in wineprefix are being enabled with exec is another thing to chase down.

Think about it if you could just enable NX mode on everything that fixed your problem most of the time. Ok not a full formal fix but its a fix in the right direction.

Fixing IMAGE_DLLCHARACTERISTICS_NX_COMPAT error is a correct thing todo either way.
oiaohm
Level 8
Level 8
Posts: 1020
Joined: Fri Feb 29, 2008 2:54 am

Re: .wine dir on noexec part fails even if exes/dlls are lin

Post by oiaohm »

http://technet.microsoft.com/en-us/libr ... 10%29.aspx

the more I am reading the more alloc_module in dlls/ntdll/loader.c is wrong.

64 bit mode NX does not have a off switch.
Locked