tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Use an anonymous file to back mmap


From: Michael Matz
Subject: Re: [Tinycc-devel] Use an anonymous file to back mmap
Date: Sat, 11 Jan 2014 19:41:51 +0100 (CET)
User-agent: Alpine 2.00 (LNX 1167 2008-08-23)

Hi,

On Thu, 9 Jan 2014, Keren Tan wrote:

I just submitted a tentative patch to the mob branch about mmap. When selinux is enabled, tccrun.c uses mmap to hold the dynamically generated code/data. It is backed by a randomly named file under /tmp directory. My patch is to use an anonymous file in mmap instead, so that the generated code/data only resides in memory, and tcc does not depend on a writable /tmp anymore.

It's customary to actually test changes before committing.  In your case:

% ./configure --with-selinux
% make && make test
...
------------ test3 ------------
../tcc -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -run tcctest.c > test.out3 /bin/sh: line 1: 15954 Segmentation fault ../tcc -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -DCONFIG_LDDIR="\"lib64\"" -DTCC_TARGET_X86_64 -DONE_SOURCE -run ../tcc.c -B.. -I.. -I.. -I../include -run tcctest.c > test.out3
make[1]: *** [test3] Error 139

This is no wonder because the former mmap mechanism had some special requirements mandated by SElinux that you ignored. Your patch basically did this:

         s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
-            MAP_SHARED, fd, 0);
+            MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
...
         s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
-            MAP_SHARED, fd, 0);
+            MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

So it replaced two mmaps of the same region (the file), one mapping being writable (pointer to it in ->write_mem), and another mapping being executable (pointer in ->runtime_mem) by two completely unrelated anon mappings, one writable, one executable.

The requirements of the whole things are such, that changes to the writable mapping via ->write_mem need to be reflected in the mapping reachable via ->runtime_mem. I.e. both mappings really need to be two views on _exactly_ the same data.

Depending on the configuration of an SElinux system the following things might be disallowed:
* creating mapping which is WRITE|EXEC
* changing flags of an existing writable mapping to include EXEC when it
  didn't before (no matter if WRITE is now removed or not)

The first means you won't get away with just a single mmap of some ANON|PRIVATE that is writable and executable. The second means you also don't get away with first mapping something writable, let tcc generate its code therein and then remap it executable (either via mprotect or mremap). That is you indeed need two separate mappings. And because both mappings need to be actually from the same underlying data they need to be related somehow. And the only way to relate two separate mappings is via a file descriptor and a MAP_SHARED mapping.

IOW: the former way of mapping a writable and executable piece of memory via a shared mapping backed by a file is the only way that works in SElinux. And yes, that means it needs to have a place for that file, and it needs to be on a file system that isn't mounted noexec (i.e. /tmp might actually not be the right place).

In still other words: please revert, sorry. :-/

tcc is fantastic! I am new to this community. Your comments are very welcome!

Yeah, sorry to spoil the fun ;) Thanks for contributing, I hope the above at least explains things. Testing is the key :)


Ciao,
Michael.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]