public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* libffi & fork
       [not found] <CAP+vr+PX9gw7Ot6Zc7AN8Gks9P+WHVQg8bX5S7YRnTRyRBHp7A@mail.gmail.com>
@ 2012-04-24 19:41 ` Gaash Hazan
  2012-04-25  9:11   ` Andrew Haley
  0 siblings, 1 reply; 12+ messages in thread
From: Gaash Hazan @ 2012-04-24 19:41 UTC (permalink / raw)
  To: libffi-discuss

Hi experts,

I am new to libffi, so forgive me for my ignorance.

I have a python crash involving ctypes and functions callbacks (read
closures) and fork. The crash happens when process is forked, some
callbacks are modified and a function callback is made. I suspect that
the problem could be related to libffi closures and fork.

dlmmap() at libffi/closures.c allocates memory block that has to be
both read-write and read-execute. To achieve that, libffi creates a
temp file and performs two mmap-s to the that file, the first
read-write and the 2nd read-execute.

7fe27d64f000-7fe27d650000 rw-s 00000000 08:02 1840563
  /tmp/ffiHf53x5 (deleted)
7fe27d650000-7fe27d651000 r-xs 00000000 08:02 1840563
  /tmp/ffiHf53x5 (deleted)

The thing is that those maps are marked as shared. Hence when the
process is forked the allocated(mapped) memory block is *shared*
between the processes (and not copied-on-write). So, when father
process changes something in that memory block, the child process will
be affected as well, creating unplanned shared-memory block between
the two processes. I suspect that this is not the intended behavior
and that it leads to the crash.

snips from /proc/XXX/maps: father PID=7975, child PID=7976
----------------------------------------------------------------------------------------
$cat /proc/7975/maps  | grep /tmp/
7fc537d49000-7fc537d4a000 rw-s 00000000 08:02 1840370
  /tmp/ffiqyLKFR (deleted)
7fc537d4a000-7fc537d4b000 r-xs 00000000 08:02 1840370
  /tmp/ffiqyLKFR (deleted)

$cat /proc/7976/maps  | grep /tmp/
7fc537d49000-7fc537d4a000 rw-s 00000000 08:02 1840370
  /tmp/ffiqyLKFR (deleted)
7fc537d4a000-7fc537d4b000 r-xs 00000000 08:02 1840370
  /tmp/ffiqyLKFR (deleted)

test .py:
-----------
import os,time
import ctypes
os.fork()
print str(os.getpid())
time.sleep( 1000)

system info: centos 6.0, pyhton 2.6.5, selinux disabled, x86_64. Also
tested with python 2.7.3

Thanks,
Gaash

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-24 19:41 ` libffi & fork Gaash Hazan
@ 2012-04-25  9:11   ` Andrew Haley
  2012-04-25 17:33     ` Gaash Hazan
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Haley @ 2012-04-25  9:11 UTC (permalink / raw)
  To: libffi-discuss

On 04/24/2012 08:40 PM, Gaash Hazan wrote:

> I am new to libffi, so forgive me for my ignorance.
> 
> I have a python crash involving ctypes and functions callbacks (read
> closures) and fork. The crash happens when process is forked, some
> callbacks are modified and a function callback is made. I suspect that
> the problem could be related to libffi closures and fork.

There is, as far as I can see, only one way to remedy this: allow
python to map anonymous memory with both write and execute permission.
Then it should work fine.

Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-25  9:11   ` Andrew Haley
@ 2012-04-25 17:33     ` Gaash Hazan
  2012-04-26 10:00       ` Andrew Haley
  0 siblings, 1 reply; 12+ messages in thread
From: Gaash Hazan @ 2012-04-25 17:33 UTC (permalink / raw)
  To: Andrew Haley; +Cc: libffi-discuss

> There is, as far as I can see, only one way to remedy this: allow
> python to map anonymous memory with both write and execute permission.
> Then it should work fine.
>

I believe memory allocation is a service provided by the OS and not by
the application or interpreter. Python does not provide memory
allocation service to libffi. In this case libffi creates
read-write-exec memory block using mmap to a tmp file. I guess the
problem is common to libff users and it is not unique to python.

libffi uses mmap with MAP_SHARED at libffi:closures.c:dlmap(). What
was the reason for using MAP_SHARED  in the first place?

I think MAP_PRIVATE would create the desired behavior of copy-on-write
when forked. Would that be a proper fix?

Gaash

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-25 17:33     ` Gaash Hazan
@ 2012-04-26 10:00       ` Andrew Haley
  2012-04-29 15:34         ` Gaash Hazan
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Haley @ 2012-04-26 10:00 UTC (permalink / raw)
  To: libffi-discuss

On 04/25/2012 06:32 PM, Gaash Hazan wrote:
>> There is, as far as I can see, only one way to remedy this: allow
>> python to map anonymous memory with both write and execute permission.
>> Then it should work fine.
>
> I believe memory allocation is a service provided by the OS and not by
> the application or interpreter.

The usual problem is a mechanism such as SELinux that is forbidding
Python from mmap()ing PROT_WRITE|PROT_EXEC .  If you label the
executable unconfined_execmem_exec_t it may work because then libffi
won't bother with all this multiple maps though a shared file
descriptor business.

> Python does not provide memory allocation service to libffi. In this
> case libffi creates read-write-exec memory block using mmap to a tmp
> file. I guess the problem is common to libff users and it is not
> unique to python.

It's special to Python because Python is the only common libffi client
that forks and then tries to use the closures.

> libffi uses mmap with MAP_SHARED at libffi:closures.c:dlmap(). What
> was the reason for using MAP_SHARED  in the first place?
>
> I think MAP_PRIVATE would create the desired behavior of copy-on-write
> when forked. Would that be a proper fix?

No, memory regions that are backed by a real file are always shared
between processes.  There is a single file descriptor that
references the block of memory that holds the closures.  The only
way you'll get it to work is to create a new file.

Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-26 10:00       ` Andrew Haley
@ 2012-04-29 15:34         ` Gaash Hazan
  2012-04-29 17:58           ` Anthony Green
  0 siblings, 1 reply; 12+ messages in thread
From: Gaash Hazan @ 2012-04-29 15:34 UTC (permalink / raw)
  To: Andrew Haley; +Cc: libffi-discuss

Hi Andrew,

Thanks for the detailed answer.

I think I found the root cause of the problem. The libffi version that
I use (3.0.5) contains a bug in closures.c:selinux_enabled_check()
that incorrectly detected non-selinux systsem as selinux system.

Because system is detected (incorrectly) as selinux dlmap() does not
attempts to do mmap() for private anonymous block with write-exec
protection. It reverts to the trick with two mmap()s on a tmp file.
But trick does not with fork.

If the system is detected (correctly) as non-selinux, then dlmp()
would use anonymous write-exec mmap() and it would  not use the trick.
Hence the fork problem would not occurred.

The selinux detected problem was fixed in
https://github.com/atgreen/libffi/commit/eaf444eabc4c78703c0f98ac0197b1619c1b1bef#src/closures.c
(closures.c line 149)

Unfortunately Redhat 6.2 and 6.3-bets uses libffi 3.0.5 that has this problem.

Regards,
Gaash


On Thu, Apr 26, 2012 at 1:00 PM, Andrew Haley <aph@redhat.com> wrote:
>
> On 04/25/2012 06:32 PM, Gaash Hazan wrote:
> >> There is, as far as I can see, only one way to remedy this: allow
> >> python to map anonymous memory with both write and execute permission.
> >> Then it should work fine.
> >
> > I believe memory allocation is a service provided by the OS and not by
> > the application or interpreter.
>
> The usual problem is a mechanism such as SELinux that is forbidding
> Python from mmap()ing PROT_WRITE|PROT_EXEC .  If you label the
> executable unconfined_execmem_exec_t it may work because then libffi
> won't bother with all this multiple maps though a shared file
> descriptor business.
>
> > Python does not provide memory allocation service to libffi. In this
> > case libffi creates read-write-exec memory block using mmap to a tmp
> > file. I guess the problem is common to libff users and it is not
> > unique to python.
>
> It's special to Python because Python is the only common libffi client
> that forks and then tries to use the closures.
>
> > libffi uses mmap with MAP_SHARED at libffi:closures.c:dlmap(). What
> > was the reason for using MAP_SHARED  in the first place?
> >
> > I think MAP_PRIVATE would create the desired behavior of copy-on-write
> > when forked. Would that be a proper fix?
>
> No, memory regions that are backed by a real file are always shared
> between processes.  There is a single file descriptor that
> references the block of memory that holds the closures.  The only
> way you'll get it to work is to create a new file.
>
> Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-29 15:34         ` Gaash Hazan
@ 2012-04-29 17:58           ` Anthony Green
  2012-04-30  8:32             ` Andrew Haley
  0 siblings, 1 reply; 12+ messages in thread
From: Anthony Green @ 2012-04-29 17:58 UTC (permalink / raw)
  To: Gaash Hazan; +Cc: Andrew Haley, libffi-discuss

On Sun, Apr 29, 2012 at 11:34 AM, Gaash Hazan <gaash@qwilt.com> wrote:
> The selinux detected problem was fixed in
> https://github.com/atgreen/libffi/commit/eaf444eabc4c78703c0f98ac0197b1619c1b1bef#src/closures.c
> (closures.c line 149)
>
> Unfortunately Redhat 6.2 and 6.3-bets uses libffi 3.0.5 that has this problem.

Thanks Gaash.

Andrew - it would be nice if we could upgrade RHEL's libffi to a
non-ABI breaking 3.0.10.  If, however, it makes more sense to
cherry-pick patches since 3.0.5, I can see some nice ones from mjw and
jakub back in 2010, and there are likely more.  If you think we should
open an RFE I can propose some specific patches for consideration.
There may only be 4 or 5 and they are all pretty obvious.

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-29 17:58           ` Anthony Green
@ 2012-04-30  8:32             ` Andrew Haley
  2012-04-30 19:16               ` Anthony Green
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Haley @ 2012-04-30  8:32 UTC (permalink / raw)
  To: libffi-discuss

On 04/29/2012 06:58 PM, Anthony Green wrote:
> On Sun, Apr 29, 2012 at 11:34 AM, Gaash Hazan <gaash@qwilt.com> wrote:
>> The selinux detected problem was fixed in
>> https://github.com/atgreen/libffi/commit/eaf444eabc4c78703c0f98ac0197b1619c1b1bef#src/closures.c
>> (closures.c line 149)
>>
>> Unfortunately Redhat 6.2 and 6.3-bets uses libffi 3.0.5 that has this problem.
> 
> Thanks Gaash.
> 
> Andrew - it would be nice if we could upgrade RHEL's libffi to a
> non-ABI breaking 3.0.10.  If, however, it makes more sense to
> cherry-pick patches since 3.0.5, I can see some nice ones from mjw and
> jakub back in 2010, and there are likely more.  If you think we should
> open an RFE I can propose some specific patches for consideration.
> There may only be 4 or 5 and they are all pretty obvious.

I think we should do that.

Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-30  8:32             ` Andrew Haley
@ 2012-04-30 19:16               ` Anthony Green
  2012-05-01  7:56                 ` Andrew Haley
  0 siblings, 1 reply; 12+ messages in thread
From: Anthony Green @ 2012-04-30 19:16 UTC (permalink / raw)
  To: Andrew Haley; +Cc: libffi-discuss

On Mon, Apr 30, 2012 at 4:32 AM, Andrew Haley <aph@redhat.com> wrote:
>> Andrew - it would be nice if we could upgrade RHEL's libffi to a
>> non-ABI breaking 3.0.10.  If, however, it makes more sense to
>> cherry-pick patches since 3.0.5, I can see some nice ones from mjw and
>> jakub back in 2010, and there are likely more.  If you think we should
>> open an RFE I can propose some specific patches for consideration.
>> There may only be 4 or 5 and they are all pretty obvious.
>
> I think we should do that.

Hmm.. check out this bug:
https://bugzilla.redhat.com/show_bug.cgi?id=772657

If our selinux state detection code really is this fragile, maybe we
should link against libselinux and use is_selinux_enabled() as
suggested in comment 4.

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-04-30 19:16               ` Anthony Green
@ 2012-05-01  7:56                 ` Andrew Haley
  2012-05-02 20:23                   ` Anthony Green
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Haley @ 2012-05-01  7:56 UTC (permalink / raw)
  To: Anthony Green; +Cc: libffi-discuss

On 04/30/2012 08:16 PM, Anthony Green wrote:
> On Mon, Apr 30, 2012 at 4:32 AM, Andrew Haley <aph@redhat.com> wrote:
>>> Andrew - it would be nice if we could upgrade RHEL's libffi to a
>>> non-ABI breaking 3.0.10.  If, however, it makes more sense to
>>> cherry-pick patches since 3.0.5, I can see some nice ones from mjw and
>>> jakub back in 2010, and there are likely more.  If you think we should
>>> open an RFE I can propose some specific patches for consideration.
>>> There may only be 4 or 5 and they are all pretty obvious.
>>
>> I think we should do that.
> 
> Hmm.. check out this bug:
> https://bugzilla.redhat.com/show_bug.cgi?id=772657
> 
> If our selinux state detection code really is this fragile, maybe we
> should link against libselinux and use is_selinux_enabled() as
> suggested in comment 4.

Would it not make far more sense simply to try to map the region
and fall back if that fails?

Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-05-01  7:56                 ` Andrew Haley
@ 2012-05-02 20:23                   ` Anthony Green
  2012-05-04  9:00                     ` Andrew Haley
  0 siblings, 1 reply; 12+ messages in thread
From: Anthony Green @ 2012-05-02 20:23 UTC (permalink / raw)
  To: Andrew Haley; +Cc: libffi-discuss

On Tue, May 1, 2012 at 3:56 AM, Andrew Haley <aph@redhat.com> wrote:
>> Hmm.. check out this bug:
>> https://bugzilla.redhat.com/show_bug.cgi?id=772657
>>
>> If our selinux state detection code really is this fragile, maybe we
>> should link against libselinux and use is_selinux_enabled() as
>> suggested in comment 4.
>
> Would it not make far more sense simply to try to map the region
> and fall back if that fails?

Wouldn't that generate spurious SELinux warnings/errors?  I'd rather
not have that as expected behaviour.

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-05-02 20:23                   ` Anthony Green
@ 2012-05-04  9:00                     ` Andrew Haley
  2012-05-05 13:19                       ` Anthony Green
  0 siblings, 1 reply; 12+ messages in thread
From: Andrew Haley @ 2012-05-04  9:00 UTC (permalink / raw)
  To: libffi-discuss

On 05/02/2012 09:23 PM, Anthony Green wrote:
> On Tue, May 1, 2012 at 3:56 AM, Andrew Haley <aph@redhat.com> wrote:
>>> Hmm.. check out this bug:
>>> https://bugzilla.redhat.com/show_bug.cgi?id=772657
>>>
>>> If our selinux state detection code really is this fragile, maybe we
>>> should link against libselinux and use is_selinux_enabled() as
>>> suggested in comment 4.
>>
>> Would it not make far more sense simply to try to map the region
>> and fall back if that fails?
> 
> Wouldn't that generate spurious SELinux warnings/errors?  I'd rather
> not have that as expected behaviour.

I suppose it would.  We could ask Dan Walsh what we should do.
Detecting the presence of SELinux is incorrect because:

1.  SELinux might be configured to allow write/exec regions.

2.  SELinux might be configured to allow write/exec regions for
    Python.

3.  Some non-SELinux mechanism might disallow write/exec regions.

One more alternative would be to probe but only at install time.
That's still wrong because someone could change SELinux settings.

Andrew.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: libffi & fork
  2012-05-04  9:00                     ` Andrew Haley
@ 2012-05-05 13:19                       ` Anthony Green
  0 siblings, 0 replies; 12+ messages in thread
From: Anthony Green @ 2012-05-05 13:19 UTC (permalink / raw)
  To: Andrew Haley; +Cc: libffi-discuss

On Fri, May 4, 2012 at 4:59 AM, Andrew Haley <aph@redhat.com> wrote:
> I suppose it would.  We could ask Dan Walsh what we should do.

This is exactly what I've done in that bugzilla ticket.

Thanks,

AG

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-05-05 13:19 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAP+vr+PX9gw7Ot6Zc7AN8Gks9P+WHVQg8bX5S7YRnTRyRBHp7A@mail.gmail.com>
2012-04-24 19:41 ` libffi & fork Gaash Hazan
2012-04-25  9:11   ` Andrew Haley
2012-04-25 17:33     ` Gaash Hazan
2012-04-26 10:00       ` Andrew Haley
2012-04-29 15:34         ` Gaash Hazan
2012-04-29 17:58           ` Anthony Green
2012-04-30  8:32             ` Andrew Haley
2012-04-30 19:16               ` Anthony Green
2012-05-01  7:56                 ` Andrew Haley
2012-05-02 20:23                   ` Anthony Green
2012-05-04  9:00                     ` Andrew Haley
2012-05-05 13:19                       ` Anthony Green

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).