Bug 2374569 - selinux-policy build fails on sepolicy-manpage execution
Summary: selinux-policy build fails on sepolicy-manpage execution
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: policycoreutils
Version: rawhide
Hardware: Unspecified
OS: Linux
unspecified
high
Target Milestone: ---
Assignee: Petr Lautrbach
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: PYTHON3.14
TreeView+ depends on / blocked
 
Reported: 2025-06-24 13:05 UTC by Zdenek Pytela
Modified: 2025-06-25 19:38 UTC (History)
9 users (show)

Fixed In Version: policycoreutils-3.8-3.fc43
Clone Of:
Environment:
Last Closed: 2025-06-25 19:38:03 UTC
Type: ---
Embargoed:
plautrba: mirror+


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker FC-1741 0 None None None 2025-06-24 13:24:02 UTC

Description Zdenek Pytela 2025-06-24 13:05:55 UTC
Rawhide builds currently cannot be made, so F42 is actually ahead.
This is the failing part of the package build.log:

install -m 644 support/Makefile.devel /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/targeted/include/Makefile
+ mkdir /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/devel/
+ mv /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/targeted/include /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/devel/include
+ install -p -m 644 /builddir/build/SOURCES/Makefile.devel /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/devel/Makefile
+ install -p -m 644 doc/example.fc doc/example.if doc/example.te /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/devel/
+ install -p -m 644 doc/policy.dtd doc/policy.xml /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/selinux/devel/
+ sepolicy manpage -a -p /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT/usr/share/man/man8/ -w -r /builddir/build/BUILD/selinux-policy-41.44-build/BUILDROOT
ValueError: No SELinux Policy installed
Exception ignored while calling deallocator <function Pool.__del__ at 0x3ff8c7873d0>:

Failing on
https://src.fedoraproject.org/rpms/selinux-policy/pull-request/545 2025-06-17

Last worked on
https://src.fedoraproject.org/rpms/selinux-policy/pull-request/542 2025-06-04

Reproducible: Always

Comment 1 Petr Lautrbach 2025-06-24 16:55:03 UTC
This seems to be related to some python 3.14 change in multiprocessing module

It's possible we get it wrong, please take a look.

The problematic code is https://github.com/fedora-selinux/selinux/blob/rawhide/python/sepolicy/sepolicy.py#L353 :

    from multiprocessing import Pool
    ...
    p = Pool()
    async_results = []
    for domain in test_domains:
        async_results.append(p.apply_async(manpage_work, [domain, path, args.root, args.source_files, args.web]))
    for result in async_results:
        domains, roles = result.get()
        manpage_domains.update(domains)
        manpage_roles.update(roles)

    p.close()
    p.join()


The reproducer is:

    selinux-policy$ fedpkg mockbuild -N
    selinux-policy$ mock -r fedora-rawhide-x86_64 --shell -N
    ...
    <mock-chroot> sh-5.2# sepolicy manpage -a -p /builddir/build/BUILD/selinux-policy-41.43-build/BUILDROOT/usr/share/man/man8/ -w -r /builddir/build/BUILD/selinux-policy-41.43-build/BUILDROOT
    ValueError: No SELinux Policy installed
    Exception ignored while calling deallocator <function Pool.__del__ at 0x7f36f9d333d0>:
    Traceback (most recent call last):
      File "/usr/lib64/python3.14/multiprocessing/pool.py", line 271, in __del__
        self._change_notifier.put(None)
      File "/usr/lib64/python3.14/multiprocessing/queues.py", line 397, in put
        self._writer.send_bytes(obj)
      File "/usr/lib64/python3.14/multiprocessing/connection.py", line 206, in send_bytes
        self._send_bytes(m[offset:offset + size])
      File "/usr/lib64/python3.14/multiprocessing/connection.py", line 444, in _send_bytes
        self._send(header + buf)
      File "/usr/lib64/python3.14/multiprocessing/connection.py", line 400, in _send
        n = write(self._handle, buf)
    BrokenPipeError: [Errno 32] Broken pipe

Comment 2 Miro Hrončok 2025-06-24 21:53:01 UTC
A significant change in the multiprocessing module in Python 3.13 is that is now uses the forkserver method by default (instead of the fork method).

To force the previous behavior, you could try:

  import multiprocessing
  
  context = multiprocessing.get_context(method="fork")
  p = context.Pool()
  ...

I am not able to try that right now, but could you?

---

How can we get the ValueError's traceback?

Comment 3 Miro Hrončok 2025-06-24 21:59:04 UTC
Traceback (most recent call last):
  File "/usr/bin/sepolicy", line 702, in <module>
    args.func(args)
    ~~~~~~~~~^^^^^^
  File "/usr/bin/sepolicy", line 347, in manpage
    test_domains = gen_domains()
  File "/usr/lib/python3.14/site-packages/sepolicy/manpage.py", line 113, in gen_domains
    for d in sepolicy.get_all_domains():
             ~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/sepolicy/__init__.py", line 930, in get_all_domains
    all_domains = list(list(info(ATTRIBUTE, "domain"))[0]["types"])
                            ~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.14/site-packages/sepolicy/__init__.py", line 200, in info
    init_policy()
    ~~~~~~~~~~~^^
  File "/usr/lib/python3.14/site-packages/sepolicy/__init__.py", line 194, in init_policy
    policy_file = get_installed_policy()
  File "/usr/lib/python3.14/site-packages/sepolicy/__init__.py", line 149, in get_installed_policy
    raise ValueError(_("No SELinux Policy installed"))
ValueError: No SELinux Policy installed

Comment 4 Miro Hrončok 2025-06-24 22:27:55 UTC
The exception is raised from https://github.com/fedora-selinux/selinux/blob/4a078ef23bcd87f8df9f024208ec61d21986b527/python/sepolicy/sepolicy/__init__.py#L141

The path is //etc/selinux/targeted/policy/policy (yes, double slash at the start), which is empty (but not because of the double slash).

As a result, return policies[-1] raises IndexError, which is silenced with the catch-all try-except-pass block, only to raise the raised ValueError, but not from the raised ignored IndexError. The flow of that try-raise-except-pass-raise function seems a bit convoluted to me.

Nevertheless, the reason this raises is the path is nonexistent. That was the case with Python 3.13 as well, so I guess the real issue here is that get_installed_policy() is called with a wrong root argument with the multiprocessing forkserver method?


Anyway, by hotpatching /var/lib/mock/fedora-rawhide-x86_64/root/usr/bin/sepolicy with:

-from multiprocessing import Pool
+from multiprocessing import get_context
+context = get_context(method="fork")
+Pool = context.Pool

The problem disappears.

Comment 5 Miro Hrončok 2025-06-24 22:40:05 UTC
Is it possible that:

  sepolicy.policy(sepolicy.get_installed_policy(args.root))

Modifies some in-process state that is forked to all the other processes with the fork multiprocessing method, but the forkserver method does not get it and it is not pickled from globals() and locals() because the state is on the C level of the _selinux module.



https://docs.python.org/3.14/library/multiprocessing.html#contexts-and-start-methods

"""
spawn: The parent process starts a fresh Python interpreter process. The child process will only inherit those resources necessary to run the process object’s run() method.

fork: The parent process uses os.fork() to fork the Python interpreter. The child process, when it begins, is effectively identical to the parent process. All resources of the parent are inherited by the child process.

forkserver: When the program starts and selects the forkserver start method, a server process is spawned. From then on, whenever a new process is needed, the parent process connects to the server and requests that it fork a new process. ... No unnecessary resources are inherited.
"""

I assume the way /usr/bin/sepolicy uses multiprocessign is not compatible with the forkserver method.

Either don't assume modified global state, or use the fork method.

Comment 6 Petr Lautrbach 2025-06-25 14:38:44 UTC
The important of the fork method documentation part is:

    Changed in version 3.14: This is no longer the default start method on any platform. Code that requires fork must explicitly specify that via get_context() or set_start_method().

Thanks for pointers!

Comment 7 Fedora Update System 2025-06-25 16:47:23 UTC
FEDORA-2025-2666fc4b84 (policycoreutils-3.8-3.fc43) has been submitted as an update to Fedora 43.
https://bodhi.fedoraproject.org/updates/FEDORA-2025-2666fc4b84

Comment 8 Fedora Update System 2025-06-25 19:38:03 UTC
FEDORA-2025-2666fc4b84 (policycoreutils-3.8-3.fc43) has been pushed to the Fedora 43 stable repository.
If problem still persists, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.