diff mbox series

[pseudo] pseudo/pseudo_client: Add wrapper functions to operate correctly with glibc 2.38 onwards

Message ID 20250504164519.65912-1-richard.purdie@linuxfoundation.org
State New
Headers show
Series [pseudo] pseudo/pseudo_client: Add wrapper functions to operate correctly with glibc 2.38 onwards | expand

Commit Message

Richard Purdie May 4, 2025, 4:45 p.m. UTC
glibc 2.38 would include  __isoc23_strtol and similar symbols. This is trggerd by
_GNU_SOURCE but we have to set that for other definitions. Therefore add seperate
wrapper functions so we can control the contexts correctly and avoid that include
when using the problematic functions (strtol, strtoll, atoi, fscanf and sscanf).

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
 Makefile.in              | 16 +++++++++-------
 ports/unix/guts/linkat.c |  2 +-
 pseudo.c                 |  2 +-
 pseudo.h                 |  4 ++++
 pseudo_client.c          | 21 +++++----------------
 pseudo_client.h          |  4 ++++
 pseudo_client_scanf.c    | 39 +++++++++++++++++++++++++++++++++++++++
 pseudo_util.c            |  2 +-
 pseudolog.c              |  4 ++--
 strtol.c                 | 26 ++++++++++++++++++++++++++
 10 files changed, 92 insertions(+), 28 deletions(-)
 create mode 100644 pseudo_client_scanf.c
 create mode 100644 strtol.c
diff mbox series

Patch

diff --git a/Makefile.in b/Makefile.in
index 48fdbd2..7ecb325 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -57,7 +57,7 @@  SOURCES=$(wildcard *.c)
 OBJS=$(subst .c,.o,$(SOURCES))
 TESTS=$(patsubst %.c,%,$(wildcard test/*.c))
 
-SHOBJS=pseudo_tables.o pseudo_util.o
+SHOBJS=pseudo_tables.o pseudo_util.o strtol.o
 DBOBJS=pseudo_db.o
 WRAPOBJS=pseudo_wrappers.o
 
@@ -100,15 +100,15 @@  $(BIN) $(LIB):
 
 pseudo: $(PSEUDO)
 
-$(PSEUDO): pseudo.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_server.o pseudo_ipc.o | $(BIN)
+$(PSEUDO): pseudo.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_client_scanf.o pseudo_server.o pseudo_ipc.o | $(BIN)
 	$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDO) \
-		pseudo.o pseudo_server.o pseudo_client.o pseudo_ipc.o \
+		pseudo.o pseudo_server.o pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o \
 		$(DBOBJS) $(SHOBJS) $(LDFLAGS) $(DB_LDFLAGS) $(CLIENT_LDFLAGS)
 
 pseudolog: $(PSEUDOLOG)
 
-$(PSEUDOLOG): pseudolog.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_ipc.o | $(BIN)
-	$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDOLOG) pseudolog.o pseudo_client.o pseudo_ipc.o \
+$(PSEUDOLOG): pseudolog.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o | $(BIN)
+	$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDOLOG) pseudolog.o pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o \
 		$(DBOBJS) $(SHOBJS) $(LDFLAGS) $(DB_LDFLAGS) $(CLIENT_LDFLAGS)
 
 pseudodb: $(PSEUDODB)
@@ -119,9 +119,9 @@  $(PSEUDODB): pseudodb.o $(SHOBJS) $(DBOBJS) pseudo_ipc.o | $(BIN)
 
 libpseudo: $(LIBPSEUDO)
 
-$(LIBPSEUDO): $(WRAPOBJS) pseudo_client.o pseudo_ipc.o $(SHOBJS) | $(LIB)
+$(LIBPSEUDO): $(WRAPOBJS) pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o $(SHOBJS) | $(LIB)
 	$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \
-		pseudo_client.o pseudo_ipc.o \
+		pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o \
 		$(WRAPOBJS) $(SHOBJS) $(LDFLAGS) $(CLIENT_LDFLAGS)
 
 # *everything* now relies on stuff that's generated in the
@@ -135,6 +135,8 @@  pseudo_client.o pseudo_server.o pseudo_ipc.o: pseudo_ipc.h
 
 pseudo_client.o: pseudo_client.h
 
+pseudo_client_scanf.o: pseudo_client.h
+
 pseudo_server.o: pseudo_server.h
 
 tables: enums/*.in maketables templatefile.py $(TABLES)
diff --git a/ports/unix/guts/linkat.c b/ports/unix/guts/linkat.c
index 7d8dff4..e1712a9 100644
--- a/ports/unix/guts/linkat.c
+++ b/ports/unix/guts/linkat.c
@@ -55,7 +55,7 @@ 
 		errno = ENOSYS;
 		return -1;
 #endif
-		tmpfile_fd = atoi(oldpath + 14);
+		tmpfile_fd = pseudo_atoi_wrapper(oldpath + 14);
 		// call actual link
 		rc = real_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, AT_SYMLINK_FOLLOW);
 	} else
diff --git a/pseudo.c b/pseudo.c
index e98e5d6..132d24a 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -212,7 +212,7 @@  main(int argc, char *argv[]) {
 			opt_S = 1;
 			break;
 		case 't': /* timeout */
-			pseudo_server_timeout = strtol(optarg, &s, 10);
+			pseudo_server_timeout = pseudo_strtol_wrapper(optarg, &s, 10);
 			if (*s && !isspace(*s)) {
 				pseudo_diag("Timeout must be an integer value.\n");
 				usage(EXIT_FAILURE);
diff --git a/pseudo.h b/pseudo.h
index 4b5eaab..b6c13f2 100644
--- a/pseudo.h
+++ b/pseudo.h
@@ -85,6 +85,10 @@  extern int pseudo_etc_file(const char *filename, char *realname, int flags, cons
 extern void pseudo_stat32_from64(struct stat *, const struct stat64 *);
 extern void pseudo_stat64_from32(struct stat64 *, const struct stat *);
 
+extern long pseudo_strtol_wrapper(const char *, char **, int);
+extern long long pseudo_strtoll_wrapper(const char *, char **, int);
+extern int pseudo_atoi_wrapper(const char *);
+
 extern char *pseudo_version;
 
 #ifndef PSEUDO_BINDIR
diff --git a/pseudo_client.c b/pseudo_client.c
index a03d6b1..1cc7a92 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -614,7 +614,7 @@  pseudo_init_client(void) {
 			 * at all.
 			 */
 			if (*env) {
-				pseudo_nosymlinkexp = strtol(env, &endptr, 10);
+				pseudo_nosymlinkexp = pseudo_strtol_wrapper(env, &endptr, 10);
 				if (*endptr)
 					pseudo_nosymlinkexp = 1;
 			} else {
@@ -624,20 +624,9 @@  pseudo_init_client(void) {
 			pseudo_nosymlinkexp = 0;
 		}
 		free(env);
-		env = pseudo_get_value("PSEUDO_UIDS");
-		if (env)
-			sscanf(env, "%d,%d,%d,%d",
-				&pseudo_ruid, &pseudo_euid,
-				&pseudo_suid, &pseudo_fuid);
-		free(env);
-
-		env = pseudo_get_value("PSEUDO_GIDS");
-		if (env)
-			sscanf(env, "%d,%d,%d,%d",
-				&pseudo_rgid, &pseudo_egid,
-				&pseudo_sgid, &pseudo_fuid);
-		free(env);
 
+		readenv_uids();
+		readenv_gids();
 		env = pseudo_get_value("PSEUDO_CHROOT");
 		if (env) {
 			pseudo_chroot = strdup(env);
@@ -1030,7 +1019,7 @@  client_spawn_server(void) {
 			pseudo_pidfile = pseudo_localstatedir_path(PSEUDO_PIDFILE);
 			fp = fopen(pseudo_pidfile, "r");
 			if (fp) {
-				if (fscanf(fp, "%d", &server_pid) != 1) {
+				if (read_pidfile(fp, &server_pid) != 1) {
 					pseudo_debug(PDBGF_CLIENT, "Opened server PID file, but didn't get a pid.\n");
 				}
 				fclose(fp);
@@ -1295,7 +1284,7 @@  pseudo_client_setup(void) {
 	fp = fopen(pseudo_pidfile, "r");
 	free(pseudo_pidfile);
 	if (fp) {
-		if (fscanf(fp, "%d", &server_pid) != 1) {
+		if (read_pidfile(fp, &server_pid) != 1) {
 			pseudo_debug(PDBGF_CLIENT, "Opened server PID file, but didn't get a pid.\n");
 		}
 		fclose(fp);
diff --git a/pseudo_client.h b/pseudo_client.h
index d7944ce..e963d95 100644
--- a/pseudo_client.h
+++ b/pseudo_client.h
@@ -74,6 +74,10 @@  extern int pseudo_nosymlinkexp;
 
 extern int pseudo_umask;
 
+extern void readenv_uids(void);
+extern void readenv_gids(void);
+extern int read_pidfile(FILE *, int *);
+
 /* Root can read and write files, and enter directories which have no
  * read, write, or execute permissions.  (But can't execute files without
  * execute permissions!)
diff --git a/pseudo_client_scanf.c b/pseudo_client_scanf.c
new file mode 100644
index 0000000..4a55d5d
--- /dev/null
+++ b/pseudo_client_scanf.c
@@ -0,0 +1,39 @@ 
+#include <stdio.h>
+#include "pseudo.h"
+#include "pseudo_ipc.h"
+#include "pseudo_client.h"
+
+/*
+ * glibc 2.38 would include  __isoc23_strtol and similar symbols if _GNU_SOURCE
+ * is used. We have to set that for other definitions so delcare this wrapper
+ * in a context where we don't have that set.
+ *
+ * We need to wrap strtol, strtoll, atoi, fscanf and sscanf.
+ */
+
+void readenv_uids(void)
+{
+	char *env;
+	env = pseudo_get_value("PSEUDO_UIDS");
+	if (env)
+		sscanf(env, "%d,%d,%d,%d",
+			&pseudo_ruid, &pseudo_euid,
+			&pseudo_suid, &pseudo_fuid);
+	free(env);
+}
+
+void readenv_gids(void)
+{
+	char *env;
+	env = pseudo_get_value("PSEUDO_GIDS");
+	if (env)
+		sscanf(env, "%d,%d,%d,%d",
+			&pseudo_rgid, &pseudo_egid,
+			&pseudo_sgid, &pseudo_fuid);
+	free(env);
+}
+
+int read_pidfile(FILE *fp, int *server_pid)
+{
+	return fscanf(fp, "%d", server_pid);
+}
diff --git a/pseudo_util.c b/pseudo_util.c
index 24115ff..081b8d2 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -229,7 +229,7 @@  pseudo_init_util(void) {
 	env = pseudo_get_value("PSEUDO_DEBUG");
 	if (env) {
 		int i;
-		int level = atoi(env);
+		int level = pseudo_atoi_wrapper(env);
 		if (level > 0) {
 			for (i = 0; i < level; ++i) {
 				pseudo_debug_verbose();
diff --git a/pseudolog.c b/pseudolog.c
index ad04753..44f7dbf 100644
--- a/pseudolog.c
+++ b/pseudolog.c
@@ -452,7 +452,7 @@  plog_trait(int opt, char *string) {
 	case PSQF_GID:
 	case PSQF_INODE:
 	case PSQF_UID:
-		new_trait->data.ivalue = strtoll(string, &endptr, 0);
+		new_trait->data.ivalue = pseudo_strtoll_wrapper(string, &endptr, 0);
 		if (*endptr) {
 			pseudo_diag("Unexpected garbage after number (%llu): '%s'\n",
 				new_trait->data.ivalue, endptr);
@@ -462,7 +462,7 @@  plog_trait(int opt, char *string) {
 		break;
 	case PSQF_MODE:
 	case PSQF_PERM:
-		new_trait->data.ivalue = strtoll(string, &endptr, 8);
+		new_trait->data.ivalue = pseudo_strtoll_wrapper(string, &endptr, 8);
 		if (!*endptr) {
 			break;
 		}
diff --git a/strtol.c b/strtol.c
new file mode 100644
index 0000000..258f02f
--- /dev/null
+++ b/strtol.c
@@ -0,0 +1,26 @@ 
+#include <stdio.h>
+#include <stdlib.h>
+#include "pseudo.h"
+
+/*
+ * glibc 2.38 would include  __isoc23_strtol and similar symbols if _GNU_SOURCE
+ * is used. We have to set that for other definitions so delcare this wrapper
+ * in a context where we don't have that set.
+ *
+ * We need to wrap strtol, strtoll, atoi, fscanf and sscanf.
+ */
+
+int pseudo_atoi_wrapper(const char *nptr)
+{
+	return atoi(nptr);
+}
+
+long pseudo_strtol_wrapper(const char *nptr, char **endptr, int base)
+{
+	return strtol(nptr, endptr, base);
+}
+
+long long pseudo_strtoll_wrapper(const char *nptr, char **endptr, int base)
+{
+	return strtoll(nptr, endptr, base);
+}