Skip to content

Commit

Permalink
python bindings: add a minimal README
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksa Sarai <[email protected]>
  • Loading branch information
cyphar committed Oct 2, 2024
1 parent 0e1c9de commit 3dbd089
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased] ##
### Fixes ###
- python bindings: add a minimal README for PyPI.
- python bindings: actually export `PROC_ROOT`.

## [0.1.1] - 2024-10-01 ##
Expand Down
85 changes: 85 additions & 0 deletions contrib/bindings/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
## python-pathrs ##

This is a basic Python wrapper around [libpathrs][libpathrs], a safe path
resolution library for Linux. For more details about the security protections
provided by [libpathrs][libpathrs], [see the main README][libpathrs-readme].

In order to use this library, you need to have `libpathrs.so` installed on your
system.

### Examples ###

libpathrs allows you to operate on a container root filesystem safely, without
worrying about an attacker swapping components and tricking you into operating
on host files.

```python
import pathrs

# Get a handle to the root filesystem.
with pathrs.Root("/path/to/rootfs") as root:
# Get an O_PATH handle to a path we want to operate on.
with root.resolve("/etc/passwd") as passwd:
# Upgrade the handle to one you can do regular IO on.
with root.reopen("r") as f:
for line in f:
print(line.rstrip("\n"))
```

Aside from just opening files, libpathrs also allows you to do most common
filesystem operations:

```python
import pathrs

# <fcntl.h>
RENAME_EXCHANGE = 0x2

with pathrs.Root("/path/to/rootfs") as root:
# symlink
root.symlink("foo", "bar") # foo -> bar
# link
root.hardlink("a", "b") # a -> b
# rename(at2)
root.rename("foo", "b", flags=RENAME_EXCHANGE) # foo <-> b
# open(O_CREAT)
with root.creat("newfile", "w+") as f:
f.write("Some contents.")
```

It also supports operations like `mkdir -p` and `rm -f`, which are a little
tricky to implement safely.

```python
import pathrs

with pathrs.Root("/path/to/rootfs") as root:
# rm -r
root.remove_all("/tmp/foo")
# mkdir -p
root.mkdir_all("/tmp/foo/bar/baz/bing/boop", 0o755)
```

In addition, libpathrs provides a safe `procfs` API, to allow for privileged
programs to operate on `/proc` in a way that detects a maliciously-configured
mount table. This is a somewhat esoteric requirement, but privileged processes
that have to operate in untrusted mount namespaces need to handle this
properly or risk serious security issues.

```python
import pathrs

# readlink("/proc/thread-self/fd/0")
stdin_path = pathrs.proc_readlink(pathrs.PROC_THREAD_SELF, "fd/0")

# readlink("/proc/self/exe")
exe_path = pathrs.proc_readlink(pathrs.PROC_SELF, "exe")

# Read data from /proc/cpuinfo.
with pathrs.proc_open(pathrs.PROC_ROOT, "cpuinfo", "r") as cpuinfo:
for line in cpuinfo:
print(line.rstrip("\n"))
```

[libpathrs]: https://github.com/openSUSE/libpathrs
[libpathrs-readme]: https://github.com/openSUSE/libpathrs/blob/main/README.md
2 changes: 2 additions & 0 deletions contrib/bindings/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ name = "pathrs"
# TODO: Figure out a way to keep this version up-to-date with Cargo.toml.
version = "0.1.1+dev"
description = "Python bindings for libpathrs, a safe path resolution library for Linux."
readme = "README.md"
keywords = ["libpathrs", "pathrs"]
license = { file = "COPYING.APACHE-2.0" }
authors = [
Expand Down Expand Up @@ -57,3 +58,4 @@ dependencies = [
[project.urls]
Homepage = "https://github.com/openSUSE/libpathrs"
Repository = "https://github.com/openSUSE/libpathrs"
Documentation = "https://docs.rs/pathrs"

0 comments on commit 3dbd089

Please sign in to comment.