Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [BUG] With --disable-dynamic-nss, not all functions calls are protected



Hi,

Vincent Lefevre wrote:
> I can notice the following warnings:
> 
> gcc -static   -o zsh main.o  `cat stamp-modobjs`   -lgdbm -lpcre -lcap -lncursesw -ltinfo -ltinfo -lrt -lm  -lc
> /usr/bin/ld: options.o: in function `dosetopt':
> ./obj-static/Src/../../Src/options.c:830: warning: Using 'initgroups' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
[...]
> I can see that Src/zsh_system.h has
> 
> #if defined(HAVE_INITGROUPS) && !defined(DISABLE_DYNAMIC_NSS)
> # define USE_INITGROUPS
> #endif
> 
> #if defined(HAVE_GETGRGID) && !defined(DISABLE_DYNAMIC_NSS)
> # define USE_GETGRGID
> #endif
[…]
> 
> But concerning the first warning, Src/options.c contains
> 
> # ifdef HAVE_INITGROUPS
> 
> I suppose that the test should have been
> 
> # ifdef USE_INITGROUPS
> 
> like in Src/params.c, which has
> 
> # ifdef USE_INITGROUPS
>         initgroups(x, pswd->pw_gid);
> # endif
> 
> I suspect that there is the same issue with the other warnings.

Not exactly. I tried to go down this route with the attached patch,
and it indeed fixes all the "Using '[…] in statically linked
applications requires at runtime the shared libraries from the glibc
version used for linking" warnings.

But copying zsh-static on a system with a different libc6 version
still segfaults, so this patch might be necessary but not sufficient.

Last line is:

  zsh-static: dl-call-libc-early-init.c:37: _dl_call_libc_early_init: Assertion `sym != NULL' failed.

So the attached patch is at least INCOMPLETE and only thought as base
for further debugging, not (yet) for inclusion in git.

Full strace of a run of zsh-static compiled with the attached patch on
Debian Unstable (glibc 2.32) and run on Debian 11 Bullseye (glibc
2.31) attached, too.

		Regards, Axel
-- 
 ,''`.  |  Axel Beckert <abe@xxxxxxxxxx>, https://people.debian.org/~abe/
: :' :  |  Debian Developer, ftp.ch.debian.org Admin
`. `'   |  4096R: 2517 B724 C5F6 CA99 5329  6E61 2FF9 CD59 6126 16B5
  `-    |  1024D: F067 EA27 26B9 C3FC 1486  202E C09E 1D89 9593 0EDE
Description: Try to fix dynamic linking with zsh-static and resulting segfaults on libc updates
Bug-Debian: https://bugs.debian.org/993843
Bug: https://zsh.org/workers/49392
Author: Axel Beckert <abe@xxxxxxxxxx>

--- a/Src/hashnameddir.c
+++ b/Src/hashnameddir.c
@@ -178,7 +178,7 @@
 	    /* Using NIS or NIS+ didn't add any user directories. This seems
 	     * fishy, so we fall back to using getpwent(). If we don't have
 	     * that, we only use the passwd file. */
-#ifdef HAVE_GETPWENT
+#ifdef USE_GETPWENT
 	    struct passwd *pw;
 
 	    setpwent();
@@ -190,7 +190,7 @@
 
 	    endpwent();
 	    usepwf = 0;
-#endif /* HAVE_GETPWENT */
+#endif /* USE_GETPWENT */
 	}
 	if (usepwf) {
 	    /* Don't forget the non-NIS matches from the flat passwd file */
@@ -229,7 +229,7 @@
 	    adduserdir(pw->pw_name, pw->pw_dir, ND_USERNAME, 1);
 
 	endpwent();
-#endif /* HAVE_GETPWENT */
+#endif /* USE_GETPWENT */
 #endif
 	allusersadded = 1;
     }
--- a/Src/options.c
+++ b/Src/options.c
@@ -807,7 +807,7 @@
 	    return -1;
 	}
 
-# ifdef HAVE_INITGROUPS
+# ifdef USE_INITGROUPS
 	/* Set the supplementary groups list.
 	 *
 	 * Note that on macOS, FreeBSD, and possibly some other platforms,
--- a/Src/params.c
+++ b/Src/params.c
@@ -4414,7 +4414,7 @@
 void
 usernamesetfn(UNUSED(Param pm), char *x)
 {
-#if defined(HAVE_SETUID) && defined(HAVE_GETPWNAM)
+#if defined(HAVE_SETUID) && defined(USE_GETPWNAM)
     struct passwd *pswd;
 
     if (x && (pswd = getpwnam(x)) && (pswd->pw_uid != cached_uid)) {
@@ -4431,7 +4431,7 @@
 	    cached_uid = pswd->pw_uid;
 	}
     }
-#endif /* HAVE_SETUID && HAVE_GETPWNAM */
+#endif /* HAVE_SETUID && USE_GETPWNAM */
     zsfree(x);
 }
 
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1115,7 +1115,7 @@
 char *
 get_username(void)
 {
-#ifdef HAVE_GETPWUID
+#ifdef USE_GETPWUID
     struct passwd *pswd;
     uid_t current_uid;
 
@@ -1128,9 +1128,9 @@
 	else
 	    cached_username = ztrdup("");
     }
-#else /* !HAVE_GETPWUID */
+#else /* !USE_GETPWUID */
     cached_uid = getuid();
-#endif /* !HAVE_GETPWUID */
+#endif /* !USE_GETPWUID */
     return cached_username;
 }
 
@@ -1306,7 +1306,7 @@
 	return str;
     }
 
-#ifdef HAVE_GETPWNAM
+#ifdef USE_GETPWNAM
     {
 	/* Retrieve an entry from the password table/database for this user. */
 	struct passwd *pw;
@@ -1322,7 +1322,7 @@
 		return dupstring(pw->pw_dir);
 	}
     }
-#endif /* HAVE_GETPWNAM */
+#endif /* USE_GETPWNAM */
 
     /* There are no more possible sources of directory names, so give up. */
     return NULL;
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -137,13 +137,13 @@
 	    strcat(outbuf, " (");
     }
     if (flags & STF_STRING) {
-#ifdef HAVE_GETPWUID
+#ifdef USE_GETPWUID
 	struct passwd *pwd;
 	pwd = getpwuid(uid);
 	if (pwd)
 	    strcat(outbuf, pwd->pw_name);
 	else
-#endif /* !HAVE_GETPWUID */
+#endif /* !USE_GETPWUID */
 	{
 	    char *optr;
 	    for (optr = outbuf; *optr; optr++)
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -2055,7 +2055,9 @@
 
     /* Get group names */
     for (gaptr = gs->array; gaptr < gs->array + gs->num; gaptr++) {
+#ifdef USE_GETGRGID
 	grptr = getgrgid(gaptr->gid);
+#endif /* USE_GETGRGID */
 	if (!grptr) {
 	    return NULL;
 	}
--- a/Src/Modules/files.c
+++ b/Src/Modules/files.c
@@ -734,6 +734,7 @@
 	struct passwd *pwd;
 	if(end)
 	    *end = 0;
+#ifdef USE_GETPWNAM
 	pwd = getpwnam(p);
 	if(pwd)
 	    chm.uid = pwd->pw_uid;
@@ -746,20 +747,35 @@
 		return 1;
 	    }
 	}
+#else /* !USE_GETPWNAM */
+	zwarnnam(nam, "%s: getpwnam not usable in static build", p);
+	free(uspec);
+	return 1;
+#endif /* !USE_GETPWNAM */
 	if(end) {
 	    p = end+1;
 	    if(!*p) {
+#ifdef USE_GETPWUID
 		if(!pwd && !(pwd = getpwuid(chm.uid))) {
 		    zwarnnam(nam, "%s: no such user", uspec);
 		    free(uspec);
 		    return 1;
 		}
+#else /* !USE_GETPWUID */
+                if(!pwd) {
+		    zwarnnam(nam, "%s: getpwuid not usable in static build",
+			     uspec);
+		    free(uspec);
+		    return 1;
+		}
+#endif /* !USE_GETPWUID */
 		chm.gid = pwd->pw_gid;
 	    } else if(p[0] == ':' && !p[1]) {
 		chm.gid = -1;
 	    } else {
 		struct group *grp;
 		dogroup:
+#ifdef USE_GETGRNAM
 		grp = getgrnam(p);
 		if(grp)
 		    chm.gid = grp->gr_gid;
@@ -772,6 +788,11 @@
 			return 1;
 		    }
 		}
+#else /* !USE_GETGRNAM */
+		zwarnnam(nam, "%s: getgrnam not usable in static build", p);
+		free(uspec);
+		return 1;
+#endif /* !USE_GETGRNAM */
 	    }
 	 } else
 	    chm.gid = -1;
execve("tmp/zsh-static", ["tmp/zsh-static"], 0x7fffde861e50 /* 53 vars */) = 0
brk(NULL)                               = 0xea9000
brk(0xea9e00)                           = 0xea9e00
arch_prctl(ARCH_SET_FS, 0xea9400)       = 0
uname({sysname="Linux", nodename="emehari", ...}) = 0
readlink("/proc/self/exe", "/home/abe/tmp/zsh-static", 4096) = 24
brk(0xecae00)                           = 0xecae00
brk(0xecb000)                           = 0xecb000
mprotect(0x642000, 32768, PROT_READ)    = 0
prctl(PR_CAPBSET_READ, CAP_MAC_OVERRIDE) = 1
prctl(PR_CAPBSET_READ, 0x30 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, CAP_CHECKPOINT_RESTORE) = 1
prctl(PR_CAPBSET_READ, 0x2c /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x2a /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x29 /* CAP_??? */) = -1 EINVAL (Invalid argument)
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3726656, ...}) = 0
mmap(NULL, 3726656, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8581aba000
close(3)                                = 0
prlimit64(0, RLIMIT_NOFILE, NULL, {rlim_cur=4*1024, rlim_max=4*1024}) = 0
getuid()                                = 1000
geteuid()                               = 1000
getgid()                                = 1000
getegid()                               = 1000
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
fstat(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
readlink("/proc/self/fd/0", "/dev/pts/0", 4095) = 10
stat("/dev/pts/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
openat(AT_FDCWD, "/dev/pts/0", O_RDWR|O_NOCTTY) = 3
fcntl(3, F_DUPFD, 10)                   = 10
close(3)                                = 0
fcntl(10, F_GETFD)                      = 0
fcntl(10, F_SETFD, FD_CLOEXEC)          = 0
fcntl(10, F_GETFL)                      = 0x8002 (flags O_RDWR|O_LARGEFILE)
ioctl(10, TCGETS, {B38400 opost isig icanon echo ...}) = 0
getpid()                                = 32389
getpgrp()                               = 32386
getpgrp()                               = 32386
rt_sigprocmask(SIG_BLOCK, [TSTP TTIN TTOU], [], 8) = 0
ioctl(10, TIOCGPGRP, [32386])           = 0
setpgid(0, 0)                           = 0
ioctl(10, TIOCSPGRP, [32389])           = 0
rt_sigprocmask(SIG_SETMASK, [], [TSTP TTIN TTOU], 8) = 0
pipe([3, 4])                            = 0
dup(0)                                  = 5
dup(0)                                  = 6
dup(0)                                  = 7
dup(0)                                  = 8
dup(0)                                  = 9
getppid()                               = 32386
getpid()                                = 32389
getuid()                                = 1000
stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat(".", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
stat("/home/abe", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
stat(".", {st_mode=S_IFDIR|0755, st_size=12288, ...}) = 0
mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8581ab6000
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 11
fstat(11, {st_mode=S_IFREG|0644, st_size=27002, ...}) = 0
mmap(NULL, 27002, PROT_READ, MAP_SHARED, 11, 0) = 0x7f8581aaf000
close(11)                               = 0
uname({sysname="Linux", nodename="emehari", ...}) = 0
openat(AT_FDCWD, "/proc/self/loginuid", O_RDONLY) = 11
read(11, "1000", 12)                    = 4
close(11)                               = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 11
connect(11, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(11)                               = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 11
connect(11, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(11)                               = 0
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 11
fstat(11, {st_mode=S_IFREG|0644, st_size=494, ...}) = 0
read(11, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 494
read(11, "", 4096)                      = 0
close(11)                               = 0
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 11
fstat(11, {st_mode=S_IFREG|0644, st_size=161344, ...}) = 0
mmap(NULL, 161344, PROT_READ, MAP_PRIVATE, 11, 0) = 0x7f8581a87000
close(11)                               = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 11
read(11, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0003\0\0\0\0\0\0"..., 832) = 832
fstat(11, {st_mode=S_IFREG|0644, st_size=51696, ...}) = 0
mmap(NULL, 79672, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 11, 0) = 0x7f8581a73000
mmap(0x7f8581a76000, 28672, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x3000) = 0x7f8581a76000
mmap(0x7f8581a7d000, 8192, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0xa000) = 0x7f8581a7d000
mmap(0x7f8581a7f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0xb000) = 0x7f8581a7f000
mmap(0x7f8581a81000, 22328, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8581a81000
close(11)                               = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 11
read(11, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@n\2\0\0\0\0\0"..., 832) = 832
fstat(11, {st_mode=S_IFREG|0755, st_size=1839792, ...}) = 0
mmap(NULL, 1852680, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 11, 0) = 0x7f85818ae000
mprotect(0x7f85818d3000, 1662976, PROT_NONE) = 0
mmap(0x7f85818d3000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x25000) = 0x7f85818d3000
mmap(0x7f8581a1e000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x170000) = 0x7f8581a1e000
mmap(0x7f8581a69000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x1ba000) = 0x7f8581a69000
mmap(0x7f8581a6f000, 13576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f8581a6f000
close(11)                               = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2", O_RDONLY|O_CLOEXEC) = 11
read(11, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\20\0\0\0\0\0\0"..., 832) = 832
fstat(11, {st_mode=S_IFREG|0755, st_size=177928, ...}) = 0
mmap(NULL, 180600, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 11, 0) = 0x7f8581881000
mprotect(0x7f8581882000, 167936, PROT_NONE) = 0
mmap(0x7f8581882000, 131072, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x1000) = 0x7f8581882000
mmap(0x7f85818a2000, 32768, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x21000) = 0x7f85818a2000
mmap(0x7f85818ab000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 11, 0x29000) = 0x7f85818ab000
mmap(0x7f85818ad000, 376, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f85818ad000
close(11)                               = 0
mprotect(0x7f85818ab000, 4096, PROT_READ) = 0
mprotect(0x7f8581a69000, 12288, PROT_READ) = 0
mprotect(0x7f8581a7f000, 4096, PROT_READ) = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 11
fstat(11, {st_mode=S_IFREG|0644, st_size=2996, ...}) = 0
read(11, "# Locale name alias data base.\n#"..., 4096) = 2996
read(11, "", 4096)                      = 0
close(11)                               = 0
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "zsh-static: dl-call-libc-early-i"..., 100) = 100
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8581880000
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid()                                = 32389
gettid()                                = 32389
tgkill(32389, 32389, SIGABRT)           = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=32389, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++

Attachment: signature.asc
Description: PGP signature



Messages sorted by: Reverse Date, Date, Thread, Author