@@ -1531,16 +1531,23 @@ async fn usroverlay(access_mode: FilesystemOverlayAccessMode) -> Result<()> {
15311531 Err ( Command :: new ( "ostree" ) . args ( args) . exec ( ) . into ( ) )
15321532}
15331533
1534- /// Perform process global initialization. This should be called as early as possible
1535- /// in the standard `main` function.
1536- #[ allow( unsafe_code) ]
1537- pub fn global_init ( ) -> Result < ( ) > {
1538- // Join the host IPC namespace if we're in an isolated one. Inside a
1539- // container with a separate IPC namespace (the podman/docker default),
1540- // udevd on the host cannot see the container's semaphores, causing
1541- // cryptsetup operations to deadlock on semop(). The primary fix is to
1542- // run the install container with --ipc=host; this is defense-in-depth
1543- // for cases where the caller forgets that flag.
1534+ /// Join the host IPC namespace if we're in an isolated one and have
1535+ /// sufficient privileges. The default for `podman run` is a separate IPC
1536+ /// namespace, which for e.g. `bootc install` can cause failures where tools
1537+ /// like udev/cryptsetup expect semaphores to be in sync with the host.
1538+ /// While we do want callers to pass `--ipc=host`, we don't want to force
1539+ /// them to need to either.
1540+ ///
1541+ /// Requires `CAP_SYS_ADMIN` (needed for `setns()`); silently skipped when
1542+ /// running unprivileged (e.g. during RPM build for manpage generation).
1543+ fn join_host_ipc_namespace ( ) -> Result < ( ) > {
1544+ let caps = rustix:: thread:: capabilities ( None ) . context ( "capget" ) ?;
1545+ if !caps
1546+ . effective
1547+ . contains ( rustix:: thread:: CapabilitySet :: SYS_ADMIN )
1548+ {
1549+ return Ok ( ( ) ) ;
1550+ }
15441551 let ns_pid1 = std:: fs:: read_link ( "/proc/1/ns/ipc" ) . context ( "reading /proc/1/ns/ipc" ) ?;
15451552 let ns_self = std:: fs:: read_link ( "/proc/self/ns/ipc" ) . context ( "reading /proc/self/ns/ipc" ) ?;
15461553 if ns_pid1 != ns_self {
@@ -1552,6 +1559,14 @@ pub fn global_init() -> Result<()> {
15521559 . context ( "setns(ipc)" ) ?;
15531560 tracing:: debug!( "Joined pid1 IPC namespace" ) ;
15541561 }
1562+ Ok ( ( ) )
1563+ }
1564+
1565+ /// Perform process global initialization. This should be called as early as possible
1566+ /// in the standard `main` function.
1567+ #[ allow( unsafe_code) ]
1568+ pub fn global_init ( ) -> Result < ( ) > {
1569+ join_host_ipc_namespace ( ) ?;
15551570 // In some cases we re-exec with a temporary binary,
15561571 // so ensure that the syslog identifier is set.
15571572 ostree:: glib:: set_prgname ( bootc_utils:: NAME . into ( ) ) ;
0 commit comments