Metamod:Source and PAX
Metamod:Source is not compatible with PAX. This article is a brief discussion of the issues and how to work around them.
If you have PAX enabled, you probably already know what it is. If you don't, PAX is typically installed alongside GRsecurity, SELinux, or other "hardened Linux" distributions. From a technical standpoint, PAX has one important feature that concerns us:
PAX prevents writing to memory that is marked as executable, and prevents marking memory as executable if it was once writable.
Why this affects Metamod
Metamod:Source, or more specifically SourceHook (or even any normal plugins that wish to edit virtual tables), works by editing virtual tables.
Objects in C++ have a list of functions. The addresses to a object's functions are stored in an array, and a pointer to the array is located at the base of every object. By altering entries in this array, the functions can be routed elsewhere, allowing Metamod:Source to dispatch callbacks in plugins.
The problem is that these arrays are located in a .text-equivalent section in ELF binaries, meaning that they are treated as code instead of data. With PAX in control, the arrays can't be modified because the memory page is marked as executable.
Why this affects SourceMod
SourceMod uses a JIT, or "Just-In-Time" Compiler. It generates executable code on the fly for performance. With PAX in control, SourceMod is unable to allocate writable memory, then mark it as executable.
The problems PAX poses are well-known. As a system-wide restriction, PAX is probably a good idea. In general, applications will not be modifying memory in a way that conflicts with PAX. However there are cases where PAX's restrictions are not only draconian, but counter-productive to the point where the fundamental requirements of some technologies cannot be met.
This is the case with Metamod:Source, and probably a good deal of Source plugins, where you essentially have two options:
- Whitelist the Source Engine so PAX's restrictions are removed, or;
- Do not use plugins.
As you've probably enabled PAX to mind security, now you have to ask yourself: is disabling PAX worth the security risk? We submit that in a well-administered environment, PAX would not be necessary at all. Not to harp on Valve, but in the past they have not been known to write secure code. Half-Life 1 is full of exploits, and it is probable that Half-Life 2 has a few lingering around too.
Essentially, proper Source security boils down to:
- Never run a Source server as root.
- The account attached to the Source server should be limited and have access to very little sensitive data.
If the Source process is incapable of breaching anything outside of its isolated environment, it doesn't matter if Gabe Newell himself manages to hack your server.
If you are paranoid to the extent that this risk is unacceptable, you are going to have to live with the fact that Metamod:Source just won't work. There is absolutely no way to work around PAX's restrictions because it specifically blocks the fundamental purpose of Metamod:Source.
Whitelisting your Server with PAX
You can easily whitelist your Source server binary such that PAX's restrictions won't affect it. Find the binary that srcds_run is launching (it will be one of srcds_i486, srcds_amd, or srcds_i686), and perform the following commands on the binary. I've used srcds_i486 as an example.
paxctl -c srcds_i486 paxctl -m srcds_i486
Warning: This will physically modify the binaries. It is possible the Steam updater tool will overwrite them.