backport patches from upstream for c23
From 27a6e9a5ac6f9241779dbb3125f02c6f0efc819c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net>
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 <soeren+git@soeren-tempel.net>
---
 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 <2129743+DrDaveD@users.noreply.github.com>
Date: Wed, 22 Jan 2025 12:22:57 -0600
Subject: [PATCH] work around c23 bool restriction

Signed-off-by: Dave Dykstra <2129743+DrDaveD@users.noreply.github.com>
---
 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
 	}
 }
 
