commit: 7a3367cb3e59695a43a7e7ae0c5c94e74646412e Author: Nicolas PARLANT <nicolas.parlant <AT> parhuet <DOT> fr> AuthorDate: Mon Jul 7 11:02:18 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Tue Jul 8 19:31:51 2025 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=7a3367cb
app-containers/apptainer: backport patches for c23 export PKG_CONFIG for seccomp Closes: https://bugs.gentoo.org/934988 Closes: https://bugs.gentoo.org/946063 Signed-off-by: Nicolas PARLANT <nicolas.parlant <AT> parhuet.fr> Part-of: https://github.com/gentoo/gentoo/pull/42928 Signed-off-by: Sam James <sam <AT> gentoo.org> app-containers/apptainer/apptainer-1.3.6.ebuild | 2 + .../apptainer/files/apptainer-1.3.6-fix_c23.patch | 468 +++++++++++++++++++++ 2 files changed, 470 insertions(+) diff --git a/app-containers/apptainer/apptainer-1.3.6.ebuild b/app-containers/apptainer/apptainer-1.3.6.ebuild index 3d00ec1de151..8244ef0dc076 100644 --- a/app-containers/apptainer/apptainer-1.3.6.ebuild +++ b/app-containers/apptainer/apptainer-1.3.6.ebuild @@ -35,11 +35,13 @@ CONFIG_CHECK="~SQUASHFS" PATCHES=( "${FILESDIR}"/${PN}-1.0.2-trim_upstream_cflags.patch + "${FILESDIR}"/${P}-fix_c23.patch ) DOCS=( README.md CONTRIBUTORS.md CONTRIBUTING.md ) src_configure() { + tc-export PKG_CONFIG local myconfargs=( -c "$(tc-getBUILD_CC)" \ -x "$(tc-getBUILD_CXX)" \ diff --git a/app-containers/apptainer/files/apptainer-1.3.6-fix_c23.patch b/app-containers/apptainer/files/apptainer-1.3.6-fix_c23.patch new file mode 100644 index 000000000000..2d77883c9a41 --- /dev/null +++ b/app-containers/apptainer/files/apptainer-1.3.6-fix_c23.patch @@ -0,0 +1,468 @@ +backport patches from upstream for c23 +From 27a6e9a5ac6f9241779dbb3125f02c6f0efc819c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <[email protected]> +Date: Sun, 12 May 2024 17:28:54 +0200 +Subject: [PATCH] pkg/unshare: fix implicit declaration of basename function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +POSIX requires the prototype of the basename function to be declared +in the libgen.h header file. Therefore, this header file needs to be +included in order to make use of this function in a POSIX environment. + +Some implementations, e.g. glibc, also define this function in string.h. +However, musl (for example) only defines it in libgen.h causing it be +implicitly declared (with an `int` return type) which is by no means +cosmetic and can lead to severe miscompilations. + +Signed-off-by: Sören Tempel <[email protected]> +--- + pkg/unshare/unshare.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pkg/unshare/unshare.c b/pkg/unshare/unshare.c +index f5a7c3a259..a2800654f9 100644 +--- a/vendor/github.com/containers/storage/pkg/unshare/unshare.c ++++ b/vendor/github.com/containers/storage/pkg/unshare//unshare.c +@@ -15,6 +15,7 @@ + #include <termios.h> + #include <errno.h> + #include <unistd.h> ++#include <libgen.h> + #include <sys/vfs.h> + #include <sys/mount.h> + #include <linux/limits.h> +From e99c9bcaa6e7b510f101ddcb6c6be9ac0b7ca072 Mon Sep 17 00:00:00 2001 +From: Dave Dykstra <[email protected]> +Date: Wed, 22 Jan 2025 12:22:57 -0600 +Subject: [PATCH] work around c23 bool restriction + +Signed-off-by: Dave Dykstra <[email protected]> +--- + cmd/starter/c/include/starter.h | 24 ++++---- + cmd/starter/c/starter.c | 56 +++++++++---------- + .../engine/config/starter/starter_linux.go | 46 +++++++-------- + 3 files changed, 63 insertions(+), 63 deletions(-) + +diff --git a/cmd/starter/c/include/starter.h b/cmd/starter/c/include/starter.h +index c62274c714..5dabc49408 100644 +--- a/cmd/starter/c/include/starter.h ++++ b/cmd/starter/c/include/starter.h +@@ -74,9 +74,9 @@ enum goexec { + #endif + + typedef enum { +- false, +- true +-} bool; ++ False, ++ True ++} Bool; + + /* container capabilities */ + struct capabilities { +@@ -94,9 +94,9 @@ struct namespace { + /* container mount namespace propagation */ + unsigned long mountPropagation; + /* namespace join only */ +- bool joinOnly; ++ Bool joinOnly; + /* should bring up loopback interface with network namespace */ +- bool bringLoopbackInterface; ++ Bool bringLoopbackInterface; + + /* namespaces inodes paths used to join namespaces */ + char network[MAX_PATH_SIZE]; +@@ -111,12 +111,12 @@ struct namespace { + /* container privileges */ + struct privileges { + /* value for PR_SET_NO_NEW_PRIVS */ +- bool noNewPrivs; ++ Bool noNewPrivs; + + /* user namespace mappings and setgroups control */ + char uidMap[MAX_MAP_SIZE]; + char gidMap[MAX_MAP_SIZE]; +- bool allowSetgroups; ++ Bool allowSetgroups; + + /* path to external newuidmap/newgidmap binaries */ + char newuidmapPath[MAX_PATH_SIZE]; +@@ -136,7 +136,7 @@ struct container { + /* container process ID */ + pid_t pid; + /* is container will run as instance */ +- bool isInstance; ++ Bool isInstance; + + /* container privileges */ + struct privileges privileges; +@@ -154,14 +154,14 @@ struct starter { + int numfds; + + /* is starter run as setuid */ +- bool isSuid; ++ Bool isSuid; + /* master process will share a mount namespace for container mount propagation */ +- bool masterPropagateMount; ++ Bool masterPropagateMount; + /* hybrid workflow where master process and container doesn't share user namespace */ +- bool hybridWorkflow; ++ Bool hybridWorkflow; + + /* bounding capability set will include caps needed by nvidia-container-cli */ +- bool nvCCLICaps; ++ Bool nvCCLICaps; + }; + + /* engine configuration */ +diff --git a/cmd/starter/c/starter.c b/cmd/starter/c/starter.c +index caf0b7c2f0..a651edd12a 100644 +--- a/cmd/starter/c/starter.c ++++ b/cmd/starter/c/starter.c +@@ -115,7 +115,7 @@ __attribute__ ((returns_twice)) __attribute__((noinline)) static int fork_ns(uns + return clone(clone_fn, child_stack.ptr, (SIGCHLD|flags), env); + } + +-static void priv_escalate(bool keep_fsuid) { ++static void priv_escalate(Bool keep_fsuid) { + uid_t uid = getuid(); + + verbosef("Get root privileges\n"); +@@ -144,7 +144,7 @@ static void priv_escalate(bool keep_fsuid) { + } + } + +-static void priv_drop(bool permanent) { ++static void priv_drop(Bool permanent) { + uid_t uid = getuid(); + gid_t gid = getgid(); + +@@ -176,12 +176,12 @@ static void set_parent_death_signal(int signo) { + } + + /* helper to check if namespace flag is set */ +-static inline bool is_namespace_create(struct namespace *nsconfig, unsigned int nsflag) { ++static inline Bool is_namespace_create(struct namespace *nsconfig, unsigned int nsflag) { + return (nsconfig->flags & nsflag) != 0; + } + + /* helper to check if the corresponding namespace need to be joined */ +-static bool is_namespace_enter(const char *nspath, const char *selfns) { ++static Bool is_namespace_enter(const char *nspath, const char *selfns) { + if ( selfns != NULL && nspath[0] != 0 ) { + struct stat selfns_st; + struct stat ns_st; +@@ -197,17 +197,17 @@ static bool is_namespace_enter(const char *nspath, const char *selfns) { + if ( errno != ENOENT ) { + debugf("Could not stat %s: %s\n", selfns, strerror(errno)); + } +- return false; ++ return False; + } + if ( stat(nspath, &ns_st) < 0 ) { + if ( errno != ENOENT ) { + debugf("Could not stat %s: %s\n", nspath, strerror(errno)); + } +- return false; ++ return False; + } + /* same namespace, don't join */ + if ( selfns_st.st_ino == ns_st.st_ino ) { +- return false; ++ return False; + } + } + return nspath[0] != 0; +@@ -809,7 +809,7 @@ static int cgroup_namespace_init(struct namespace *nsconfig) { + } + } + +-static int mount_namespace_init(struct namespace *nsconfig, bool masterPropagateMount) { ++static int mount_namespace_init(struct namespace *nsconfig, Bool masterPropagateMount) { + if ( is_namespace_enter(nsconfig->mount, SELF_MNT_NS) ) { + if ( enter_namespace(nsconfig->mount, CLONE_NEWNS) < 0 ) { + fatalf("Failed to enter in mount namespace: %s\n", strerror(errno)); +@@ -867,10 +867,10 @@ static int shared_mount_namespace_init(struct namespace *nsconfig) { + } + + /* +- * is_suid returns true if this binary has suid bit set or if it ++ * is_suid returns True if this binary has suid bit set or if it + * has additional capabilities in extended file attributes + */ +-static bool is_suid(void) { ++static Bool is_suid(void) { + unsigned long auxval; + + errno = 0; +@@ -954,7 +954,7 @@ static void cleanup_fd(fdlist_t *master, struct starter *starter) { + DIR *dir; + struct dirent *dirent; + int i, fd; +- bool found; ++ Bool found; + + if ( ( fd_proc = open("/proc/self/fd", O_RDONLY) ) < 0 ) { + fatalf("Failed to open /proc/self/fd: %s\n", strerror(errno)); +@@ -973,12 +973,12 @@ static void cleanup_fd(fdlist_t *master, struct starter *starter) { + continue; + } + +- found = false; ++ found = False; + + /* check if the file descriptor was open before stage 1 execution */ + for ( i = 0; i < master->num; i++ ) { + if ( master->fds[i] == fd ) { +- found = true; ++ found = True; + break; + } + } +@@ -986,12 +986,12 @@ static void cleanup_fd(fdlist_t *master, struct starter *starter) { + continue; + } + +- found = false; ++ found = False; + + /* check if the file descriptor need to remain opened */ + for ( i = 0; i < starter->numfds; i++ ) { + if ( starter->fds[i] == fd ) { +- found = true; ++ found = True; + /* set force close on exec */ + if ( fcntl(starter->fds[i], F_SETFD, FD_CLOEXEC) < 0 ) { + debugf("Can't set FD_CLOEXEC on file descriptor %d: %s\n", starter->fds[i], strerror(errno)); +@@ -1094,7 +1094,7 @@ static void fix_userns_devfuse_fd(struct starter *starter) { + } + } + +-static void wait_child(const char *name, pid_t child_pid, bool noreturn) { ++static void wait_child(const char *name, pid_t child_pid, Bool noreturn) { + int status; + int exit_status = 0; + +@@ -1263,7 +1263,7 @@ __attribute__((constructor)) static void init(void) { + + /* temporarily drop privileges while running as setuid */ + if ( sconfig->starter.isSuid ) { +- priv_drop(false); ++ priv_drop(False); + } + + /* retrieve engine configuration from environment variables */ +@@ -1298,7 +1298,7 @@ __attribute__((constructor)) static void init(void) { + */ + if ( sconfig->starter.isSuid ) { + /* drop privileges permanently */ +- priv_drop(true); ++ priv_drop(True); + } + set_parent_death_signal(SIGKILL); + verbosef("Spawn stage 1\n"); +@@ -1310,7 +1310,7 @@ __attribute__((constructor)) static void init(void) { + } + + debugf("Wait completion of stage1\n"); +- wait_child("stage 1", process, false); ++ wait_child("stage 1", process, False); + + /* change current working directory if requested by stage 1 */ + if ( sconfig->starter.workingDirectoryFd >= 0 ) { +@@ -1369,7 +1369,7 @@ __attribute__((constructor)) static void init(void) { + fatalf("Unblock signals error: %s\n", strerror(errno)); + } + /* loop until master process exits with error */ +- wait_child("instance", process, true); ++ wait_child("instance", process, True); + + /* we should never return from the previous wait_child call */ + exit(1); +@@ -1412,7 +1412,7 @@ __attribute__((constructor)) static void init(void) { + * this will fail if starter is run without suid + */ + if ( sconfig->starter.isSuid ) { +- priv_escalate(true); ++ priv_escalate(True); + } else if ( uid != 0 ) { + fatalf("Installation issue: starter-suid doesn't have setuid bit set\n"); + } +@@ -1489,10 +1489,10 @@ __attribute__((constructor)) static void init(void) { + if ( wait_event(master_socket[1]) < 0 ) { + fatalf("Error while waiting event for shared mount namespace\n"); + } +- mount_namespace_init(&sconfig->container.namespace, true); ++ mount_namespace_init(&sconfig->container.namespace, True); + } else { + send_event(master_socket[1]); +- mount_namespace_init(&sconfig->container.namespace, false); ++ mount_namespace_init(&sconfig->container.namespace, False); + } + + if ( !sconfig->container.namespace.joinOnly ) { +@@ -1518,7 +1518,7 @@ __attribute__((constructor)) static void init(void) { + close(rpc_socket[1]); + + /* wait RPC server exits before running container process */ +- wait_child("rpc server", process, false); ++ wait_child("rpc server", process, False); + + if ( sconfig->starter.hybridWorkflow && sconfig->starter.isSuid ) { + /* make /proc/self readable by user to join instance without SUID workflow */ +@@ -1584,7 +1584,7 @@ __attribute__((constructor)) static void init(void) { + * user mappings setup. User filesystem UID will be restored below by setresuid + * call. + */ +- priv_escalate(false); ++ priv_escalate(False); + chdir_to_proc_pid(sconfig->container.pid); + setup_userns_mappings(&sconfig->container.privileges); + } else { +@@ -1611,7 +1611,7 @@ __attribute__((constructor)) static void init(void) { + /* wait child finish namespaces initialization */ + if ( wait_event(master_socket[0]) < 0 ) { + /* child has exited before sending data */ +- wait_child("stage 2", sconfig->container.pid, true); ++ wait_child("stage 2", sconfig->container.pid, True); + } + + /* engine requested to propagate mount to container */ +@@ -1669,11 +1669,11 @@ __attribute__((constructor)) static void init(void) { + if ( sconfig->container.namespace.joinOnly ) { + /* joining container, don't execute Go runtime, just wait that container process exit */ + if ( sconfig->starter.isSuid ) { +- priv_drop(true); ++ priv_drop(True); + } + debugf("Wait stage 2 child process\n"); + release_memory(sconfig); +- wait_child("stage 2", process, true); ++ wait_child("stage 2", process, True); + } else { + /* close container end of rpc communication socket */ + close(rpc_socket[1]); +diff --git a/internal/pkg/runtime/engine/config/starter/starter_linux.go b/internal/pkg/runtime/engine/config/starter/starter_linux.go +index 9c42c68a4e..737f7114a8 100644 +--- a/internal/pkg/runtime/engine/config/starter/starter_linux.go ++++ b/internal/pkg/runtime/engine/config/starter/starter_linux.go +@@ -55,10 +55,10 @@ func NewConfig(config SConfig) *Config { + } + } + +-// GetIsSUID returns true if the SUID workflow is enabled. ++// GetIsSUID returns True if the SUID workflow is enabled. + // This field is set by starter at the very beginning of its execution. + func (c *Config) GetIsSUID() bool { +- return c.config.starter.isSuid == C.true ++ return c.config.starter.isSuid == C.True + } + + // GetContainerPid returns the container PID (if any). +@@ -68,54 +68,54 @@ func (c *Config) GetContainerPid() int { + } + + // SetInstance changes starter config so that it will spawn an instance +-// instead of a regular container if the passed value is true. ++// instead of a regular container if the passed value is True. + func (c *Config) SetInstance(instance bool) { + if instance { +- c.config.container.isInstance = C.true ++ c.config.container.isInstance = C.True + } else { +- c.config.container.isInstance = C.false ++ c.config.container.isInstance = C.False + } + } + + // SetNoNewPrivs changes starter config so that it will set NO_NEW_PRIVS +-// flag for a container before it starts up if noprivs is true. ++// flag for a container before it starts up if noprivs is True. + func (c *Config) SetNoNewPrivs(noprivs bool) { + if noprivs { +- c.config.container.privileges.noNewPrivs = C.true ++ c.config.container.privileges.noNewPrivs = C.True + } else { +- c.config.container.privileges.noNewPrivs = C.false ++ c.config.container.privileges.noNewPrivs = C.False + } + } + + // SetMasterPropagateMount changes starter config so that the mount propagation + // between master (process that monitors container) and a container itself +-// is set to MS_SHARED if propagate is true. ++// is set to MS_SHARED if propagate is True. + func (c *Config) SetMasterPropagateMount(propagate bool) { + if propagate { +- c.config.starter.masterPropagateMount = C.true ++ c.config.starter.masterPropagateMount = C.True + } else { +- c.config.starter.masterPropagateMount = C.false ++ c.config.starter.masterPropagateMount = C.False + } + } + + // SetNamespaceJoinOnly changes starter config so that the created process + // will join an already running container (used for `apptainer shell` and +-// `apptainer oci exec`) if join is true. ++// `apptainer oci exec`) if join is True. + func (c *Config) SetNamespaceJoinOnly(join bool) { + if join { +- c.config.container.namespace.joinOnly = C.true ++ c.config.container.namespace.joinOnly = C.True + } else { +- c.config.container.namespace.joinOnly = C.false ++ c.config.container.namespace.joinOnly = C.False + } + } + + // SetBringLoopbackInterface changes starter config so that it will bring up +-// a loopback network interface during container creation if bring is true. ++// a loopback network interface during container creation if bring is True. + func (c *Config) SetBringLoopbackInterface(bring bool) { + if bring { +- c.config.container.namespace.bringLoopbackInterface = C.true ++ c.config.container.namespace.bringLoopbackInterface = C.True + } else { +- c.config.container.namespace.bringLoopbackInterface = C.false ++ c.config.container.namespace.bringLoopbackInterface = C.False + } + } + +@@ -166,9 +166,9 @@ func (c *Config) KeepFileDescriptor(fd int) error { + // nvidia-container-cli + func (c *Config) SetNvCCLICaps(enabled bool) { + if enabled { +- c.config.starter.nvCCLICaps = C.true ++ c.config.starter.nvCCLICaps = C.True + } else { +- c.config.starter.nvCCLICaps = C.false ++ c.config.starter.nvCCLICaps = C.False + } + } + +@@ -179,18 +179,18 @@ func (c *Config) SetNvCCLICaps(enabled bool) { + // lives in its own user namespace. + func (c *Config) SetHybridWorkflow(hybrid bool) { + if hybrid { +- c.config.starter.hybridWorkflow = C.true ++ c.config.starter.hybridWorkflow = C.True + } else { +- c.config.starter.hybridWorkflow = C.false ++ c.config.starter.hybridWorkflow = C.False + } + } + + // SetAllowSetgroups allows use of setgroups syscall from user namespace. + func (c *Config) SetAllowSetgroups(allow bool) { + if allow { +- c.config.container.privileges.allowSetgroups = C.true ++ c.config.container.privileges.allowSetgroups = C.True + } else { +- c.config.container.privileges.allowSetgroups = C.false ++ c.config.container.privileges.allowSetgroups = C.False + } + } +
