zsh-workers
 help / color / mirror / code / Atom feed
From: Axel Beckert <abe@debian.org>
To: zsh-workers@zsh.org, 993843@bugs.debian.org
Subject: Re: [BUG] With --disable-dynamic-nss, not all functions calls are protected
Date: Wed, 15 Sep 2021 16:31:03 +0200	[thread overview]
Message-ID: <20210915143102.pw5uup7bvufi7wse@sym.noone.org> (raw)
In-Reply-To: <20210908011251.GA2387366@zira.vinc17.org>


[-- Attachment #1.1: Type: text/plain, Size: 2143 bytes --]

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@debian.org>, 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

[-- Attachment #1.2: make-zsh-static-really-static-#993843.patch --]
[-- Type: text/x-diff, Size: 4662 bytes --]

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@debian.org>

--- 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;

[-- Attachment #1.3: zsh-static-still-segfaults.strace --]
[-- Type: text/plain, Size: 8360 bytes --]

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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2021-09-15 14:31 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-08  1:12 Vincent Lefevre
2021-09-15 14:31 ` Axel Beckert [this message]
2021-09-15 19:13   ` Bart Schaefer
2021-09-16  7:37     ` Jun T
2021-09-16 12:10       ` Axel Beckert
2021-09-16 16:48         ` Bart Schaefer
2021-09-16 18:21           ` Jun. T
2021-09-16 18:34             ` Axel Beckert
2021-09-16 22:01               ` Bart Schaefer
2021-09-17  1:23             ` Jun T
2021-09-17  8:45               ` Jun T
2021-09-17 13:44                 ` Axel Beckert
2021-09-17 13:55                   ` Roman Perepelitsa
2021-09-17 14:16                     ` Axel Beckert
2021-09-17 15:02                 ` Bart Schaefer
2021-09-21  0:53                   ` Jun T
2021-09-21  3:38                     ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210915143102.pw5uup7bvufi7wse@sym.noone.org \
    --to=abe@debian.org \
    --cc=993843@bugs.debian.org \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).