herumi / xbyak

a JIT assembler for x86(IA-32)/x64(AMD64, x86-64) MMX/SSE/SSE2/SSE3/SSSE3/SSE4/FPU/AVX/AVX2/AVX-512 by C++ header

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Keep getting 'ERR: Can't Protect', but not in gdb mode

ardiyu07 opened this issue · comments

$ ./bf64 hello.bf
64bit mode
ERR:can't protect

Is there any explanation into this? I can't debug it with gdb since it runs fine in debug mode..
I'm using 64-bit CentOS 6.4, with gcc 4.4.7

FYI I also tried in Win7 with msvc 10 and did not get that error either..

And FWIW output of this machine's less /proc/cpuinfo is listed below

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 23
model name      : Intel(R) Core(TM)2 Quad CPU    Q8400  @ 2.66GHz
stepping        : 10
cpu MHz         : 2657.908
cache size      : 2048 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 4
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dts tpr_shadow vnmi flexpriority
bogomips        : 5315.81
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

..and the other 3 cores..

Maybe SELinux is enable on your CentOS.
Thought I don't know how to change the policy for bf64, could you see http://wiki.centos.org/HowTos/SELinux for example?

@herumi
Yes, that was exactly the problem.
I traced which selinux policy that restricts this error, and I found that in xbyak.h:L.730

return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;

Gives the following error for SELinux:

type=AVC msg=audit(1391070483.348:3026): avc:  denied  { execheap } for  pid=13041 comm="bf" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=process
type=SYSCALL msg=audit(1391070483.348:3026): arch=40000003 syscall=125 success=no exit=-13 a0=8a9f000 a1=186a0 a2=7 a3=1 items=0 ppid=8771 pid=13041 auid=501 uid=501 gid=501 euid=501 suid=501 fsuid=501 egid=501 sgid=501 fsgid=501 tty=pts19 ses=1 comm="bf" exe="/home/y_ardila/Develop/xbyak/sample/bf" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)

Setting allow_execheap to true for SELinux eludes this error, but apparently (excerpted from an article from Ulrich), using memory regions that are both executable and writable is a bad idea.

The program mapped from a file with mmap and the MAP_PRIVATE flag and write permission. Then the memory region has been written to, resulting in copy-on-write (COW) of the affected page(s). This memory region is then made executable with code like this:

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
int main (void)
{
  int fd = open ("inputfile", O_RDWR);
  char *p = mmap (NULL, 42, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
  p[0] = 'a';
  int r = mprotect (p, 42, PROT_READ | PROT_EXEC);
  printf ("mprotect = %d\n", r);
  return 0;
}

The mprotect call will fail with EACCES in this case. Note that this happens even though the mprotect call removes the write permissions. To fix the problem one could map the file for execution right from the beginning and avoid the problem. But this is very dangerous: programs should never use memory regions which are writable and executable at the same time. Assuming that it is really necessary to generate executable code while the program runs the method employed should be reconsidered.

Should this be something to be aware of?

Setting allow_execheap to true for SELinux eludes this error, but apparently >(excerpted from an article from Ulrich), using memory regions that are both >executable and writable is a bad idea.

I know the fact, but I think it is difficult and complex to avoid it, so I select a simple implementation now. I try to consider the problem again. Do you have any ideas?

You're right.. I'm afraid enormous changes must be made in order to achieve this. For instance create a mapping in the first place statically.

Anyway I had the initial issue resolved.