Skip to main content

Axle Runtime is the runtime part of the Python Wheel enhancement library

Project description

Axle-Runtime - Python Wheel enhancement library

Gitter Build Status Coverage Status

PyBuilder Version PyBuilder Python Versions PyBuilder Downloads Per Day PyBuilder Downloads Per Week PyBuilder Downloads Per Month

This is a companion project to Wheel Axle/bdist_axle

Problem

  1. Python wheels do not support symlinks.
  2. PIP installation procedure is not locally extensible and does not allow adding post-install hooks.

Solution

WARNING: THIS IS EXPERIMENTAL BETA SOFTWARE. THERE ARE NO WARRANTIES OF ANY KIND. USE AT YOUR OWN RISK. ADDITIONAL INCLUDED DISCLAIMERS ALSO APPLY.

Wheel Axle Runtime library utilizes a little-known trick used in site.py's .pth files that allows executing arbitrary code while the site packages are being added. Thus, specially-crafted wheels can silently execute installed code on Python interpreter startup, facilitating the "post-install hook" functionality.

Python Invariants

The core functionality relies on the following Python behaviors:

These invariants have not changed for 18 years.

Implementation

Once the distribution-specific .pth is executed by the Python interpreter, the Wheel Axle Runtime behaves as follows:

  1. The library checks whether a file .dist-info/axle.done exists. If it does it is the indication that the post-install hook has executed successfully and nothing more is to be done, terminating all further processing.
  2. A process-wide inter-thread lock is acquired.
  3. An OS-wide inter-process file lock is acquired on a file .dist-info/axle.lck.
  4. Once the locks are acquired the .dist-info/axle.done existence is rechecked (double-checked locking optimization).
  5. Now that in-process and inter-process race conditions are excluded the post-install work can begin.
  6. Registered installers are run in sequence. Installers should be idempotent. The following installers are currently implemented:
    1. Symlinks installer processes .dist-info/symlinks.txt, if any.
      1. Based on the location of the .pth file being executed the current installation schema and its paths are determined. Currently, installation into a virtual environment or user location is supported and tested.
      2. For each symlink the target path is resolved and realpath is used to determine the final target path.
      3. If the symlink path and symlink target path are within one of the permitted schema locations the symlink is created. Otherwise, an exception is raised and the processing is aborted.
      4. After all symlinks are created, the .dist-info/RECORD file is updated to reflect the created symlinks.
    2. Axle installer finalizes the installation. This installer is always executed last.
      1. The .dist-info/RECORD is updated with .dist-info/axle.done file record.
      2. .dist-info/axle.done is created.
      3. <distribution name and version>.pth is then removed. If the file cannot be removed it is left in place. This can happen on Windows, since the .pth file in question is likely opened for exclusive reading on Windows.
  7. Any failure anywhere in the above process will result in an abort, an error message, and a retry the next time the .pth will be activated.

Security

There are several security requirements and implications of having post-install hooks implemented this way.

  1. The installation requires write permissions to the distribution. This will be a problem if the package is installed as root in locations such as /usr or /usr/local, or is otherwise not write-permitted, unless the post-install hook is also ran with the sufficient privileges. This is generally acceptable as the primary use is considered to be installation into virtual envs and user locations. That said, simply running python -c pass or any other python invocation that does activate site.py under the required privileges will finalize post-install procedures.
  2. There is an attempt to ensure that that axle wheels symlinks and targets don't extend beyond the allowed schema locations. Those attempts are superficial and have not been formally verified. For example, it may be possible to escape the path validation/confinement by:
    • hacking symlink creation order
    • hacking symlink directory targets
    • exploiting OS-specific realpath implementation idiosyncrasies (i.e. strict vs not, and what is considered strict)

TODOs

  • Support schema detection for home and prefix installations.
  • Validate and verify Windows support.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wheel-axle-runtime-0.0.3.tar.gz (15.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wheel_axle_runtime-0.0.3-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file wheel-axle-runtime-0.0.3.tar.gz.

File metadata

  • Download URL: wheel-axle-runtime-0.0.3.tar.gz
  • Upload date:
  • Size: 15.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.2

File hashes

Hashes for wheel-axle-runtime-0.0.3.tar.gz
Algorithm Hash digest
SHA256 ca5788d0a6b7939815bf0e02a8a5a9ace86f19e43373a6f4b72f1e2471d97f77
MD5 c73de3c95562a9df621ea0bb78c4dc22
BLAKE2b-256 e6d30fd40f99bca77df4fc278e317acd638203c4a4864493016ec95d9d36b637

See more details on using hashes here.

File details

Details for the file wheel_axle_runtime-0.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for wheel_axle_runtime-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 45b12289be60cadcefddac86dde938b2d72536bf3f72f94a1f6b16c5308dda3d
MD5 29ac7b67b500fefb57de8d180fc3472e
BLAKE2b-256 c3ea11fa84c2fa021aff514417df127540e11dbb0349d6f625a9108b31c551a5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page