landlockpy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ cooldown:
8
+ default-days: 7
9
+ open-pull-requests-limit: 5
10
+ - package-ecosystem: uv
11
+ directory: /
12
+ schedule:
13
+ interval: weekly
14
+ cooldown:
15
+ default-days: 7
16
+ open-pull-requests-limit: 5
@@ -0,0 +1,58 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ schedule:
8
+ - cron: "9 7 * * 1"
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ lint:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
17
+ with:
18
+ egress-policy: audit
19
+
20
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21
+ with:
22
+ persist-credentials: false
23
+
24
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
25
+ with:
26
+ version: "0.11.32"
27
+ enable-cache: true
28
+
29
+ - run: uv sync --locked
30
+
31
+ - run: uv run ruff check .
32
+ - run: uv run ruff format --check .
33
+ - run: uv run bandit -r src/
34
+ - run: uv run mypy
35
+
36
+ test:
37
+ runs-on: ubuntu-latest
38
+ strategy:
39
+ fail-fast: false
40
+ matrix:
41
+ python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
42
+ steps:
43
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
44
+ with:
45
+ egress-policy: audit
46
+
47
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
48
+ with:
49
+ persist-credentials: false
50
+
51
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
52
+ with:
53
+ version: "0.11.32"
54
+ enable-cache: true
55
+
56
+ - run: uv python install ${{ matrix.python }}
57
+ - run: uv sync --locked --python ${{ matrix.python }}
58
+ - run: uv run pytest
@@ -0,0 +1,35 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ schedule:
8
+ - cron: "17 3 * * 4"
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ analyze:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ actions: read
17
+ contents: read
18
+ security-events: write
19
+ steps:
20
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
21
+ with:
22
+ egress-policy: audit
23
+
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ with:
26
+ persist-credentials: false
27
+
28
+ - uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
29
+ with:
30
+ languages: python
31
+ queries: security-and-quality
32
+
33
+ - uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
34
+ with:
35
+ category: "/language:python"
@@ -0,0 +1,22 @@
1
+ name: Dependency Review
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ permissions: {}
7
+
8
+ jobs:
9
+ dependency-review:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ steps:
14
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
15
+ with:
16
+ egress-policy: audit
17
+
18
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19
+ with:
20
+ persist-credentials: false
21
+
22
+ - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
@@ -0,0 +1,63 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions: {}
8
+
9
+ jobs:
10
+ release:
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/landlockpy
15
+ permissions:
16
+ contents: write
17
+ id-token: write
18
+ attestations: write
19
+ steps:
20
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
21
+ with:
22
+ egress-policy: audit
23
+
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ with:
26
+ persist-credentials: false
27
+
28
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
29
+ with:
30
+ version: "0.11.32"
31
+
32
+ - run: uv sync --locked
33
+
34
+ - name: Verify tag matches package version
35
+ run: |
36
+ tag="${GITHUB_REF_NAME#v}"
37
+ version="$(uv run python -c 'import landlockpy; print(landlockpy.__version__)')"
38
+ if [ "$tag" != "$version" ]; then
39
+ echo "tag $tag does not match package version $version" >&2
40
+ exit 1
41
+ fi
42
+
43
+ - run: uv build
44
+
45
+ - name: Attest build provenance
46
+ uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
47
+ with:
48
+ subject-path: dist/*
49
+
50
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
51
+ with:
52
+ attestations: true
53
+
54
+ - name: Create GitHub release
55
+ env:
56
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57
+ run: |
58
+ gh release create "${GITHUB_REF_NAME}" \
59
+ --repo "${GITHUB_REPOSITORY}" \
60
+ --verify-tag \
61
+ --title "${GITHUB_REF_NAME}" \
62
+ --generate-notes \
63
+ dist/*
@@ -0,0 +1,41 @@
1
+ name: OpenSSF Scorecard
2
+
3
+ on:
4
+ branch_protection_rule:
5
+ push:
6
+ branches: [master]
7
+ schedule:
8
+ - cron: "42 5 * * 6"
9
+
10
+ permissions: read-all
11
+
12
+ jobs:
13
+ analysis:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ security-events: write
17
+ id-token: write
18
+ steps:
19
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
20
+ with:
21
+ egress-policy: audit
22
+
23
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
+ with:
25
+ persist-credentials: false
26
+
27
+ - uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
28
+ with:
29
+ results_file: results.sarif
30
+ results_format: sarif
31
+ publish_results: true
32
+
33
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
34
+ with:
35
+ name: SARIF file
36
+ path: results.sarif
37
+ retention-days: 5
38
+
39
+ - uses: github/codeql-action/upload-sarif@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4.38.1
40
+ with:
41
+ sarif_file: results.sarif
@@ -0,0 +1,28 @@
1
+ name: zizmor
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ paths: [.github/**]
7
+ pull_request:
8
+ paths: [.github/**]
9
+
10
+ permissions: {}
11
+
12
+ jobs:
13
+ zizmor:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ security-events: write
17
+ steps:
18
+ - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
19
+ with:
20
+ egress-policy: audit
21
+
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
+ with:
24
+ persist-credentials: false
25
+
26
+ - uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
27
+ with:
28
+ advanced-security: false
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv/
7
+ .mypy_cache/
8
+ .pytest_cache/
9
+ .ruff_cache/
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - 2026-09-22
4
+
5
+ Initial release.
6
+
7
+ - Ruleset construction with handled filesystem, network and scope rights.
8
+ - Path-hierarchy rules and TCP/UDP port rules, including quiet rules (ABI 10).
9
+ - Scoped domains for abstract UNIX sockets and signals (ABI 6).
10
+ - Restrict flags covering audit logging, TSYNC and atomic no_new_privs
11
+ (ABI 11, prctl fallback on older kernels).
12
+ - Best-effort masking to the running kernel, strict mode via
13
+ best_effort=False.
14
+ - Kernel probes: abi_version(), errata(), supported(), and the for_abi
15
+ helpers for computing which rights a given ABI supports.
@@ -0,0 +1,12 @@
1
+ Copyright (c) 2026 Quad4
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose
4
+ with or without fee is hereby granted.
5
+
6
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
8
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
9
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
11
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
12
+ PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,15 @@
1
+ .PHONY: check lint test build
2
+
3
+ check: lint test
4
+
5
+ lint:
6
+ uv run ruff check .
7
+ uv run ruff format --check .
8
+ uv run bandit -r src/
9
+ uv run mypy
10
+
11
+ test:
12
+ uv run pytest
13
+
14
+ build:
15
+ uv build
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.5
2
+ Name: landlockpy
3
+ Version: 0.1.0
4
+ Summary: Python bindings for the Landlock Linux security module
5
+ Project-URL: Homepage, https://quad4.io
6
+ Project-URL: Repository, https://github.com/Quad4-Software/landlockpy
7
+ Project-URL: Documentation, https://docs.kernel.org/userspace-api/landlock.html
8
+ Author: Quad4
9
+ License-Expression: 0BSD
10
+ License-File: LICENSE
11
+ Keywords: landlock,linux,lsm,sandbox,security
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: BSD License
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Security
18
+ Classifier: Topic :: System :: Operating System Kernels :: Linux
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+
23
+ # landlockpy
24
+
25
+ [![CI](https://github.com/Quad4-Software/landlockpy/actions/workflows/ci.yml/badge.svg)](https://github.com/Quad4-Software/landlockpy/actions/workflows/ci.yml)
26
+ [![CodeQL](https://github.com/Quad4-Software/landlockpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/Quad4-Software/landlockpy/actions/workflows/codeql.yml)
27
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/Quad4-Software/landlockpy/badge)](https://securityscorecards.dev/viewer/?uri=github.com/Quad4-Software/landlockpy)
28
+ [![License: 0BSD](https://img.shields.io/badge/license-0BSD-blue)](LICENSE)
29
+
30
+ Dependency-free Python bindings for the Landlock Linux security module.
31
+ Landlock lets unprivileged processes sandbox themselves with filesystem,
32
+ network and IPC restrictions enforced by the kernel. Supports ABI versions
33
+ 1 through 11 with best-effort degradation on older kernels.
34
+
35
+ Requires Python 3.10+ and Linux 5.13+ with Landlock enabled in the LSM list.
36
+
37
+ ## Install
38
+
39
+ pip install landlockpy
40
+
41
+ ## Usage
42
+
43
+ ```python
44
+ from landlockpy import AccessFS, AccessNet, Ruleset
45
+
46
+ with Ruleset() as ruleset:
47
+ ruleset.allow_path(
48
+ "/usr", AccessFS.READ_FILE | AccessFS.READ_DIR | AccessFS.EXECUTE
49
+ )
50
+ ruleset.allow_port(443, AccessNet.CONNECT_TCP)
51
+ ruleset.restrict()
52
+
53
+ # everything not granted above is now denied for this thread and its children
54
+ ```
55
+
56
+ `landlockpy.supported()` reports whether the running kernel has Landlock,
57
+ and `landlockpy.abi_version()` returns its ABI version.
58
+
59
+ ## Documentation
60
+
61
+ - API: docstrings in `src/landlockpy/`, mostly `ruleset.py`
62
+ - Landlock API reference: https://docs.kernel.org/userspace-api/landlock.html
63
+ - Project site: https://landlock.io/
64
+
65
+ License: 0BSD.
@@ -0,0 +1,43 @@
1
+ # landlockpy
2
+
3
+ [![CI](https://github.com/Quad4-Software/landlockpy/actions/workflows/ci.yml/badge.svg)](https://github.com/Quad4-Software/landlockpy/actions/workflows/ci.yml)
4
+ [![CodeQL](https://github.com/Quad4-Software/landlockpy/actions/workflows/codeql.yml/badge.svg)](https://github.com/Quad4-Software/landlockpy/actions/workflows/codeql.yml)
5
+ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/Quad4-Software/landlockpy/badge)](https://securityscorecards.dev/viewer/?uri=github.com/Quad4-Software/landlockpy)
6
+ [![License: 0BSD](https://img.shields.io/badge/license-0BSD-blue)](LICENSE)
7
+
8
+ Dependency-free Python bindings for the Landlock Linux security module.
9
+ Landlock lets unprivileged processes sandbox themselves with filesystem,
10
+ network and IPC restrictions enforced by the kernel. Supports ABI versions
11
+ 1 through 11 with best-effort degradation on older kernels.
12
+
13
+ Requires Python 3.10+ and Linux 5.13+ with Landlock enabled in the LSM list.
14
+
15
+ ## Install
16
+
17
+ pip install landlockpy
18
+
19
+ ## Usage
20
+
21
+ ```python
22
+ from landlockpy import AccessFS, AccessNet, Ruleset
23
+
24
+ with Ruleset() as ruleset:
25
+ ruleset.allow_path(
26
+ "/usr", AccessFS.READ_FILE | AccessFS.READ_DIR | AccessFS.EXECUTE
27
+ )
28
+ ruleset.allow_port(443, AccessNet.CONNECT_TCP)
29
+ ruleset.restrict()
30
+
31
+ # everything not granted above is now denied for this thread and its children
32
+ ```
33
+
34
+ `landlockpy.supported()` reports whether the running kernel has Landlock,
35
+ and `landlockpy.abi_version()` returns its ABI version.
36
+
37
+ ## Documentation
38
+
39
+ - API: docstrings in `src/landlockpy/`, mostly `ruleset.py`
40
+ - Landlock API reference: https://docs.kernel.org/userspace-api/landlock.html
41
+ - Project site: https://landlock.io/
42
+
43
+ License: 0BSD.
@@ -0,0 +1,6 @@
1
+ # Security policy
2
+
3
+ Only the latest release is supported.
4
+
5
+ Report vulnerabilities to security@quad4.io. Do not open public issues for
6
+ security reports.
@@ -0,0 +1,64 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "landlockpy"
7
+ dynamic = ["version"]
8
+ description = "Python bindings for the Landlock Linux security module"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "0BSD"
12
+ authors = [{ name = "Quad4" }]
13
+ keywords = ["landlock", "lsm", "sandbox", "security", "linux"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: BSD License",
18
+ "Operating System :: POSIX :: Linux",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Security",
21
+ "Topic :: System :: Operating System Kernels :: Linux",
22
+ "Typing :: Typed",
23
+ ]
24
+ dependencies = []
25
+
26
+ [project.urls]
27
+ Homepage = "https://quad4.io"
28
+ Repository = "https://github.com/Quad4-Software/landlockpy"
29
+ Documentation = "https://docs.kernel.org/userspace-api/landlock.html"
30
+
31
+ [tool.hatch.version]
32
+ path = "src/landlockpy/__init__.py"
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "pytest>=9.1.1",
37
+ "ruff>=0.16.8",
38
+ "bandit>=1.9.4",
39
+ "mypy>=2.3.1",
40
+ ]
41
+
42
+ [tool.ruff]
43
+ target-version = "py310"
44
+ src = ["src", "tests"]
45
+
46
+ [tool.ruff.lint]
47
+ select = ["E", "F", "I", "UP", "B", "SIM", "S", "PTH", "C90", "RUF", "TRY"]
48
+ ignore = ["TRY003"]
49
+
50
+ [tool.ruff.lint.per-file-ignores]
51
+ "tests/*" = ["S101", "S603"]
52
+
53
+ [tool.mypy]
54
+ strict = true
55
+ files = ["src", "tests"]
56
+
57
+ [tool.bandit]
58
+ exclude_dirs = ["tests"]
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
62
+ markers = [
63
+ "enforced: tests that apply a Landlock ruleset in a child process",
64
+ ]
@@ -0,0 +1,81 @@
1
+ # SPDX-License-Identifier: 0BSD
2
+ """Python bindings for the Landlock Linux security module.
3
+
4
+ Landlock lets unprivileged processes sandbox themselves with filesystem,
5
+ network and IPC restrictions enforced by the kernel. Rulesets are scoped to
6
+ what the running kernel supports, so applications get best-effort protection
7
+ across kernel versions.
8
+
9
+ Kernel reference: https://docs.kernel.org/userspace-api/landlock.html
10
+ Project site: https://landlock.io/
11
+ """
12
+
13
+ import errno
14
+
15
+ from . import _syscall
16
+ from .errors import LandlockError, UnsupportedError
17
+ from .flags import (
18
+ AccessFS,
19
+ AccessNet,
20
+ RestrictFlag,
21
+ Scope,
22
+ fs_for_abi,
23
+ net_for_abi,
24
+ restrict_for_abi,
25
+ scope_for_abi,
26
+ )
27
+ from .ruleset import Ruleset
28
+
29
+ __version__ = "0.1.0"
30
+
31
+ __all__ = [
32
+ "AccessFS",
33
+ "AccessNet",
34
+ "LandlockError",
35
+ "RestrictFlag",
36
+ "Ruleset",
37
+ "Scope",
38
+ "UnsupportedError",
39
+ "__version__",
40
+ "abi_version",
41
+ "errata",
42
+ "fs_for_abi",
43
+ "net_for_abi",
44
+ "restrict_for_abi",
45
+ "scope_for_abi",
46
+ "supported",
47
+ ]
48
+
49
+
50
+ def abi_version() -> int:
51
+ """Return the Landlock ABI version of the running kernel, or 0.
52
+
53
+ A return value of 0 means the kernel is too old (ENOSYS) or Landlock is
54
+ disabled at boot time (EOPNOTSUPP).
55
+ """
56
+ try:
57
+ return _syscall.abi_version()
58
+ except LandlockError as exc:
59
+ if exc.errno in (errno.ENOSYS, errno.EOPNOTSUPP):
60
+ return 0
61
+ raise
62
+
63
+
64
+ def errata() -> int:
65
+ """Return the errata bitmask for the current ABI version, or 0.
66
+
67
+ Bit N set means erratum N is fixed in the running kernel. Older kernels
68
+ without the errata mechanism report 0. Most applications should not
69
+ check errata; best-effort enforcement is the safer default.
70
+ """
71
+ try:
72
+ return _syscall.errata()
73
+ except LandlockError as exc:
74
+ if exc.errno in (errno.ENOSYS, errno.EOPNOTSUPP, errno.EINVAL):
75
+ return 0
76
+ raise
77
+
78
+
79
+ def supported() -> bool:
80
+ """Return whether the running kernel supports Landlock."""
81
+ return abi_version() >= 1