CrossKylix
Sponsor:

Viprinet Multichannel VPN Router allows bonding of up to six ADSL lines

The Viprinet® Multichannel VPN Router™ lets you bundle up to six physical broadband lines like ADSL into a single virtual dedicated line.

Fix for Kylix-built applications crashing under Linux 2.6.8 Kernels with Exec-Shield enabled

Users of CrossKylix Version 0.9.0 and up are no longer affected by this compiler issue!

As reported in the Borland Kylix Newsgroups, applications compiled with Kylix will crash on Linux distributions running the 2.6.8 Kernel including the exec-shield patch. Currently this is happening with Red Had Fedora Core 2, but soon other distributions probably will also be affected.

Scroll down if you don't care about the story behind this, but simply wish to get a fix.

As you probably know, there has lately been quite some fuzz about making memory non-executable to prevent buffer overflows by using the no-execute flag of the new AMD64 and newer P4 CPUs. Well, some guy at Red Hat went a step further than that. By using the segmentation feature of the CPU they now managed to make memory not marked for execution to be really non-executable on all x86 machines. This technology is called "exec-shield" and described here:

http://people.redhat.com/mingo/exec-shield/ANNOUNCE-exec-shield

Exec-shield is currently included in the 2.6.8 Fedora Core 2 Kernel.

Now for the Kylix part of the story - corresponding with Borland (thanks again Danny!), the following issue was found:

When initializing classes.pas, TSimpleRWSync.Create is called and the result is assigned to the GlobalNameSpace interface. This internally calls System.IntfCopy, which then does this:

17886           CALL    DWORD PTR [EAX] + VMTOFFSET IInterface._AddRef

Problem is: The interface stub code where this jumps to is part of a data segment inside the ELF file. And when dumping the ELF file, we can see:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000a0 0x000a0 R E 0x4
  INTERP         0x0000d4 0x080480d4 0x080480d4 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x29ba4 0x2dba4 R E 0x1000
  LOAD           0x029ba4 0x08076ba4 0x08076ba4 0x04594 0x055d8 RW  0x1000
  DYNAMIC        0x02e0b0 0x0807b0b0 0x0807b0b0 0x00088 0x00088 RW  0x4

The second LOAD section is marked as read-write, but NOT as executable. And well, execution inside a memory block marked as read-write will give you a segfault with exec-shield.

This is more or less Borlands fault - as this really is a data segment, they chose to mark it as read/write only, even if it has the executable interface stub in it. Back when the Kylix compiler was written, a missing execution flag on memory could not be enforced, so this flaw wasn't really a problem. Well, now it is.

There are three different ways to fix this:

  • Change the protection flags of the created ELF file after compilation.
  • Fix this in the RTL (or provide a unit to include as first unit in the use clause) so that the memory block is marked for execution before anything else is happening.
  • Fix the compiler/linker to either emit the correct flags for the segment, or move the interface stub into a different segment. We'll have to wait for a Kylix update from Borland for that.

I'm providing two different solutions to the problem. The first solution is a unit that fixes the problem at runtime, during program initialization. The second one is a tool that allows you to patch the ELF header of an already compiled (and possibly deployed) application.

The runtime fix

Download my runtime fix (1.5KB, ZIP). In the ZIP file you'll find the execshieldfix.pas Unit. Copy this to somewhere in your Kylix unit search path. Now, include the execshieldfix Unit as very first Unit in your projects use clause. Like this:

program hello;

uses
  execshieldfix, SysUtils, Classes;

Remember, it needs to be the first unit so it is able to mark the memory segment as executable before the RTL/CLX initialization happens (which will crash without the fix).

The binary fix for already compiled applications

I have written a small command line tool that is able to add the missing execution flag to the sections affected. Using this you can fix your Kylix compiled executables. You may also pass this tool to your customers to fix already deployed Kylix applications.

The tool is called "patchelf". The archive includes both a Linux and a Windows version of the tool, so you can also do the patching on a Windows machine. Source also is included.

Usage:

patchelf [-q] filename

  -q     Quiet mode (no output)

Download patchelf (160KB, Linux+Windows executables, Source)

Does this affect CrossKylix users?

No. CrossKylix automatically fixes the problem during compilation.

© Simon Kissel 2004. This project is sponsored by chatjet.com.