Adding support for Linux IMA (Integrity Measurement Architecture) and Linux executability secure bits

Hey everyone,

Linux has added through the years many ways to verify integrity of executable files, or just files in general. One of those is IMA (Integrity Measurement Architecture).

This feature makes use of the linux keyrings and a new security.ima extended attribute to verify file integrity, which contains a signed hash of the file. Linux users with a Linux kernel built with the IMA configuration option can then enable it, set policies, and the kernel will be in charge of verifying that the file’s integrity is correct, by verifying its checksum against the signed hash contained in that new extended attribute.
One of the most common usage regards executable files, libraries, etc.

This would prevent, for example, a modified cpython binary to be run. These checks are also applied if a python script is called “directly”, i.e “./my-python-script.py”.
However, “indirect” invocation of such scripts (python my-python-script.py), imports, or interactive invocations (“python -c” or just the regular python interpreter command line), are not covered by this.

In order to cover those, Linux integrated in 6.14, a couple of new secure bits as well as a new flag for execveat:

The idea behind those is to allow a feature like IMA to work in the cases mentioned above, if enabled on the system.
Those two new bits, SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE, are to be used by interpreters and odther source of indirect code execution to verify, if needed, any code that is loaded. The new flag added to execveat is used to “dry run” the execution checks that usually happen during IMA appraisals.
If EXEC_RESTRICT_FILE is set, the interpreter would call execveat with this new flag, triggering the appraisal by IMA, and returning a to-be-defined permission denied or similar error if the appraisal fails.
If EXEC_DENY_INTERACTIVE is set, things like “python -c” or just the regular stdin interpreter would be denied.

This is to add coverage for a big missing piece of coverage in the IMA feature. To be honest, beside an issue opened for perl on github, I could not track any other progress being made for any other interpreter, like bash, even though I might have missed it. . This would also be a platform specific change, as it requires a Linux kernel.

I am new to the cpython source code. Obviously the overall idea would need to be accepted first, but I think codepath that would need to be changed are relatively well isolated, from a quick naive look.