Files
lix/tests/functional2/build/test_xattrs.py
T
Raito Bezarius e083a68a9f libstore/linux: forbid xattrs syscalls
xattrs are revealing some unfortunate brittleness in real world
derivations that are getting -EINVAL errors while executing their test
code.

The reason for this is that Linux checks [1] UID delegations for xattrs
writes.

In the Lix sandbox, except if you enabled a uid-range feature, you have
exactly 3 UIDs: root, nixbld and nobody.

If your test code makes use of UIDs which have not been delegated, you
will receive an EINVAL on your operation. Test code is not resilient
with respect to the number of available UIDs in their namespace.

To avoid further issues for end users who are running into spurious
derivation build failures, we forbid xattrs again for now.

For more information about the plans, please consult or chime in [2].

Fixes #1105. Reopens #838. Fixes #1103.

[1]: https://elixir.bootlin.com/linux/v6.18.6/source/fs/posix_acl.c#L257
[2]: https://zulip.lix.systems/#narrow/channel/9-Store/topic/disablement.20of.20xattrs/with/5295

Change-Id: I864066b34cd8319d2271fac1b179cb4f950d836e
Signed-off-by: Raito Bezarius <raito@lix.systems>
2026-01-26 18:54:51 +00:00

48 lines
1.9 KiB
Python

import pytest
from pathlib import Path
from testlib.fixtures.file_helper import with_files
from testlib.fixtures.nix import Nix
from testlib.utils import get_global_asset, CopyFile
from testlib.xattrs import verify_no_xattrs_in_tree, skip_if_xattrs_are_unsupported
# NOTE(Raito): xattrs are forbidden in builds for the time being.
# See: https://zulip.lix.systems/#narrow/channel/9-Store/topic/disablement.20of.20xattrs/with/5295 for the rationale.
# Once these hurddles are cleared, remove the skip markers.
@with_files(
{"config.nix": get_global_asset("config.nix"), "xattrs.nix": CopyFile("assets/xattrs.nix")}
)
@pytest.mark.skip(reason="xattrs are forbidden in builds")
def test_xattrs_during_build(nix: Nix):
skip_if_xattrs_are_unsupported(nix.env)
nix.nix_build(["xattrs.nix", "-A", "during-build", "--no-out-link"]).run().ok()
def build_and_get_store_path(nix: Nix, asset: str, attribute: str) -> Path:
return nix.physical_store_path_for(
nix.nix_build([asset, "-A", attribute, "--no-out-link"]).run().ok().stdout_plain
)
@with_files(
{"config.nix": get_global_asset("config.nix"), "xattrs.nix": CopyFile("assets/xattrs.nix")}
)
@pytest.mark.skip(reason="xattrs are forbidden in builds")
def test_xattrs_in_output(nix: Nix):
skip_if_xattrs_are_unsupported(nix.env)
# We assert that xattrs producing derivations in the outputs should complete with no xattrs in the final output path.
# NOTE: if another platform is added, another `verify_no_acl_in_tree`
# should be added to ensure that ACLs are truly removed.
# On Linux, this is not necessary.
output_path = build_and_get_store_path(nix, "xattrs.nix", "in-root-outputs-file")
verify_no_xattrs_in_tree(output_path)
output_path = build_and_get_store_path(nix, "xattrs.nix", "in-root-outputs-dir")
verify_no_xattrs_in_tree(output_path)
output_path = build_and_get_store_path(nix, "xattrs.nix", "in-output-content")
verify_no_xattrs_in_tree(output_path)