Bug 772657 - selinux prevents proper operation of mod_python because libffi is restricted.
Summary: selinux prevents proper operation of mod_python because libffi is restricted.
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: libffi
Version: 16
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Miroslav Grepl
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2012-01-09 14:45 UTC by john.haxby@oracle.com
Modified: 2019-05-21 11:12 UTC (History)
8 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2013-02-13 18:50:03 UTC
Type: ---


Attachments (Terms of Use)

Description john.haxby@oracle.com 2012-01-09 14:45:48 UTC
Description of problem:

I have a mod_python scripts that has "import ctypes" and nothing else.  This fails with a "memory" error which results in this snipped from httpd:

  open("/dev/shm/ffiOG04Hl", O_RDWR|O_CREAT|O_EXCL, 0600) = 18
  unlink("/dev/shm/ffiOG04Hl")            = 0
  ftruncate(18, 4096)                     = 0
  mmap(NULL, 4096, PROT_READ|PROT_EXEC, MAP_SHARED, 18, 0) =
                                    -1 EACCES (Permission denied)
  close(18)                               = 0

Version-Release number of selected component (if applicable):
  selinux-policy-3.10.0-69.fc16.noarch
  selinux-policy-targeted-3.10.0-69.fc16.noarch

How reproducible:
  Always


Steps to Reproduce:
1. yum install mod_python and make sure you have an accessible httpd
   running

2. Create /etc/httpd/conf.d/bug.conf containing this:

      LoadModule python_module modules/mod_python.so

      <Location /bug>
          SetHandler python-program
          PythonPath "sys.path + ['/var/www/html' ]"
          PythonHandler bug
          PythonDebug On
      </Location>

and /var/www/html/bug.py containing just one line:

      import ctypes

3. Restart httpd and run

      curl http://localhost/bug

  
Actual results:

   An error ending with "Memory Error" arising from the import

Expected results:

   AttributeError: module '/var/www/html/bug.py' contains no 'handler'
   (You can put a handler in if you like with the intention of getting
    no error at all, but this is only to reproduce the problem after all.)

Additional info:

  From way back, bug 582009 and bug 522731 both mention this.  Setting 
  httpd_tmp_exec does work around the problem, though it would seem that this
  is not the right thing to do.

Comment 1 Daniel Walsh 2012-01-09 20:38:30 UTC
I believe this is the only solution, you need to be able to create a file that you can write and execute to allow this access.

I think this stuff was added to prevent an  execmod/execstack avc?

Comment 2 john.haxby@oracle.com 2012-01-10 14:20:16 UTC
What's odd is that this was a problem around F11 and pygments (which is what does the import ctypes) works just fine from mod_python in F15.

I wonder if libffi changed?  Does it really need the shared memory to be executable?

Comment 3 john.haxby@oracle.com 2012-01-10 14:39:48 UTC
Bingo: in libffi/src/closures.c:

------------------------
#if FFI_MMAP_EXEC_SELINUX
#include <sys/statfs.h>
#include <stdlib.h>

static int selinux_enabled = -1;

static int
selinux_enabled_check (void)
{
  struct statfs sfs;
  FILE *f;
  char *buf = NULL;
  size_t len = 0;

  if (statfs ("/selinux", &sfs) >= 0
      && (unsigned int) sfs.f_type == 0xf97cff8cU)
    return 1;
...
---------------------

That should be /sys/fs/selinux for F16 ...  creating a symbolic link from that to /selinux makes libffi work as expected.

Changing the component to libffi.  Thanks Dan.

Comment 4 Daniel Walsh 2012-01-10 14:52:45 UTC
is_selinux_enabled() within libselinux is a better way to check this, if you are linking against libselinux.

If not then searching for selinuxfs in /proc/filesystems would be a better check to see if the kernel has selinux support.

# grep selinuxfs /proc/filesystems 
nodev	selinuxfs


/selinux has moved to /sys/fs/selinux in F16.

Note that just searching for selinuxfs or the existance of /sys/fs/selinux is not considered enough of a check of whether or not SELinux is fully enabled, which is why I would suggest using is_selinux_enabeled()

Comment 5 Anthony Green 2012-05-05 13:17:48 UTC
(In reply to comment #4)
> Note that just searching for selinuxfs or the existance of /sys/fs/selinux is
> not considered enough of a check of whether or not SELinux is fully enabled,
> which is why I would suggest using is_selinux_enabeled()

Hi Dan, libffi author here...

Is there a way to tell whether or not SELinux will allow write/exec regions that doesn't involve creation of spurious SELinux errors?

See this thread for context:
http://sourceware.org/ml/libffi-discuss/2012/msg00180.html

Thanks!

AG

Comment 6 Daniel Walsh 2012-05-07 13:39:43 UTC
Well other then we are trying to prevent this.  We do not want to allow apps to allocate memory for both write and execute, since this an attack vector for buffer overflow attacks.

http://www.akkadia.org/drepper/selinux-mem.html

In most cases if it is considered critical that an app do this, then we allow the user to set a boolean to allow this like httpd_execmem or allow_execmem.

Anyways your question was about telling if SELinux would allow or deny it. You would have to know the type of the app that is running.  For example if you were checking to see if apache allows it, you would check httpd_t and execmem permission.

sesearch -CA -s httpd_t -p execmem
DT allow httpd_t httpd_t : process { execmem execstack } ; [ httpd_execmem ]

This says that it would be allowed but only if the httpd_execmem boolean was turned on and currently it is not. D - tells you whether it is enabled or disabled.

sesearch -CA -s unconfined_t -p execmem
EF allow unconfined_t unconfined_t : process execmem ; [ allow_execmem ]

This is checking for the default user, unconfined_t and it says if the allow_execmem In this case it is enabled "E"

Comment 7 Andrew Haley 2012-05-08 14:16:24 UTC
(In reply to comment #6)

> Anyways your question was about telling if SELinux would allow or
> deny it. You would have to know the type of the app that is running.
> For example if you were checking to see if apache allows it, you
> would check httpd_t and execmem permission.
> 
> sesearch -CA -s httpd_t -p execmem
> DT allow httpd_t httpd_t : process { execmem execstack } ; [ httpd_execmem ]
> 
> This says that it would be allowed but only if the httpd_execmem
> boolean was turned on and currently it is not. D - tells you whether
> it is enabled or disabled.
> 
> sesearch -CA -s unconfined_t -p execmem
> EF allow unconfined_t unconfined_t : process execmem ; [ allow_execmem ]
> 
> This is checking for the default user, unconfined_t and it says if the
> allow_execmem In this case it is enabled "E"

Yabbut, how to do this programmatically?  This is a library, and we
want to know if the current process is allowed execmem.

Andrew.

Comment 8 john.haxby@oracle.com 2012-05-08 14:52:16 UTC
Can't you just assume that execmem is not allowed?   After all, selinux prevents it simply because it's a particularly rich source of security errors.   Otherwise it's like not wearing a seatbelt unless he law demands it: it's no less of a safety feature whether it's legally required or not.

Comment 9 Daniel Walsh 2012-05-08 15:17:10 UTC
Andrew you can make yourself a resource manage and ask the policy if your current policy allows you to execmem.

#include <stdio.h>
#include <errno.h>
#include <selinux/selinux.h>

void main(int argc, char *argv) {

	int rc;
	security_context_t con;

	getcon(&con);

	rc = selinux_check_access(con, con, "process", "execmem", NULL);
	switch (rc) {
		case 0:
			printf("Allowed\n");
			break;
		case -1:
			perror("Unknown");
			break;
		default:
			printf("Denied\n");
		}
}

Comment 10 Andrew Haley 2012-05-08 15:23:58 UTC
(In reply to comment #9)
> Andrew you can make yourself a resource manage and ask the policy if your
> current policy allows you to execmem.

Aha!  That is exactly what we need.  Thank you very much.

Comment 11 Fedora End Of Life 2013-01-16 15:42:12 UTC
This message is a reminder that Fedora 16 is nearing its end of life.
Approximately 4 (four) weeks from now Fedora will stop maintaining
and issuing updates for Fedora 16. It is Fedora's policy to close all
bug reports from releases that are no longer maintained. At that time
this bug will be closed as WONTFIX if it remains open with a Fedora 
'version' of '16'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version prior to Fedora 16's end of life.

Bug Reporter: Thank you for reporting this issue and we are sorry that 
we may not be able to fix it before Fedora 16 is end of life. If you 
would still like to see this bug fixed and are able to reproduce it 
against a later version of Fedora, you are encouraged to click on 
"Clone This Bug" and open it against that version of Fedora.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

The process we are following is described here: 
http://fedoraproject.org/wiki/BugZappers/HouseKeeping

Comment 12 Fedora End Of Life 2013-02-13 18:50:07 UTC
Fedora 16 changed to end-of-life (EOL) status on 2013-02-12. Fedora 16 is 
no longer maintained, which means that it will not receive any further 
security or bug fix updates. As a result we are closing this bug.

If you can reproduce this bug against a currently maintained version of 
Fedora please feel free to reopen this bug against that version.

Thank you for reporting this bug and we are sorry it could not be fixed.


Note You need to log in before you can comment on or make changes to this bug.