diff --git a/lix/libstore/platform/linux.cc b/lix/libstore/platform/linux.cc index 3b11822fc..aeb1af127 100644 --- a/lix/libstore/platform/linux.cc +++ b/lix/libstore/platform/linux.cc @@ -231,6 +231,7 @@ static std::vector compileSyscallFilter() // Run check-syscalls to determine which new syscalls should be added. // New syscalls must be audited and handled in a way that blocks the following dangerous operations: // * Creation of non-empty setuid/setgid files + // * Creation of extended attributes (including ACLs) // // BEGIN extract-syscalls allowSyscall(ctx, SCMP_SYS(accept)); @@ -320,7 +321,7 @@ static std::vector compileSyscallFilter() allowSyscall(ctx, SCMP_SYS(fork)); allowSyscall(ctx, SCMP_SYS(fremovexattr)); allowSyscall(ctx, SCMP_SYS(fsconfig)); - allowSyscall(ctx, SCMP_SYS(fsetxattr)); + // skip fsetxattr (dangerous) allowSyscall(ctx, SCMP_SYS(fsmount)); allowSyscall(ctx, SCMP_SYS(fsopen)); allowSyscall(ctx, SCMP_SYS(fspick)); @@ -424,7 +425,7 @@ static std::vector compileSyscallFilter() allowSyscall(ctx, SCMP_SYS(lookup_dcookie)); allowSyscall(ctx, SCMP_SYS(lremovexattr)); allowSyscall(ctx, SCMP_SYS(lseek)); - allowSyscall(ctx, SCMP_SYS(lsetxattr)); + // skip lsetxattr (dangerous) allowSyscall(ctx, SCMP_SYS(lstat)); allowSyscall(ctx, SCMP_SYS(lstat64)); allowSyscall(ctx, SCMP_SYS(madvise)); @@ -622,7 +623,7 @@ static std::vector compileSyscallFilter() allowSyscall(ctx, SCMP_SYS(set_tls)); allowSyscall(ctx, SCMP_SYS(setuid)); allowSyscall(ctx, SCMP_SYS(setuid32)); - allowSyscall(ctx, SCMP_SYS(setxattr)); + // skip setxattr (dangerous) allowSyscall(ctx, SCMP_SYS(sgetmask)); allowSyscall(ctx, SCMP_SYS(shmat)); allowSyscall(ctx, SCMP_SYS(shmctl)); @@ -729,6 +730,15 @@ static std::vector compileSyscallFilter() ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat), 2); ALLOW_CHMOD_IF_SAFE(ctx, SCMP_SYS(fchmodat2), 2); + // setxattr family: prevent creation of extended attributes or ACLs. + // Not all filesystems support them, and they're incompatible with the NAR format. + if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(setxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(lsetxattr), 0) != 0 + || seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOTSUP), SCMP_SYS(fsetxattr), 0) != 0) + { + throw SysError("unable to add seccomp rule"); + } + Pipe filterPipe; filterPipe.create(); auto filterBytes_ = std::async([&]() { diff --git a/tests/functional2/build/test_xattrs.py b/tests/functional2/build/test_xattrs.py index 899c73c23..13b4f66e1 100644 --- a/tests/functional2/build/test_xattrs.py +++ b/tests/functional2/build/test_xattrs.py @@ -1,5 +1,3 @@ -import sys - import pytest from pathlib import Path from testlib.fixtures.file_helper import with_files @@ -7,10 +5,15 @@ 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) @@ -26,9 +29,7 @@ def build_and_get_store_path(nix: Nix, asset: str, attribute: str) -> Path: @with_files( {"config.nix": get_global_asset("config.nix"), "xattrs.nix": CopyFile("assets/xattrs.nix")} ) -@pytest.mark.skipif( - sys.platform != "linux", reason="xattrs scrubbing is not expected to function outside of Linux" -) +@pytest.mark.skip(reason="xattrs are forbidden in builds") def test_xattrs_in_output(nix: Nix): skip_if_xattrs_are_unsupported(nix.env)